手把手教你,通过HAL库实现MODBUS从机程序编写与调试(二)-串口及定时函数的完善

目录

1.STM32CubeMX操作

 2、程序完善

2.1完善usart.h

 2.2完善usart.c

2.2.1头文件完善

2.2.2增加回调函数

2.2.3串口初始化函数

2.3完善tim.h

2.4完善tim.c

2.4.1完善头文件

 2.4.2完善回调函数和初始化函数

2.5完善main.c

2.6调试

2.6.1KEIL的设置

 2.6.2程序下载调试


 1.STM32CubeMX操作

此部分在上一个文章,链接如下:

手把手教你,通过HAL库实现MODBUS从机程序编写与调试(一)-----STM32CubeMX操作篇_tangxianyu的博客-CSDN博客

 2、程序完善

2.1完善usart.h

为了确保在更新STM32CubeMX的时候,我们自己增加的程序不会被删除掉。我们在完善程序的时候需要将程序增加到制定的位置。例如在usart.h内的,我们将需要增加的程序到:

/* USER CODE BEGIN Private defines */

/* USER CODE END Private defines */

首先定义一个UART_BUF结构体,里面包含接收的缓冲数据和大小,以及发送的数据集大小。

然后定义一个串口的初始化函数E_USART_INIT来对定义的UART_BUF进行初始化。定义一个串口中断回调函数HAL_UART_RxCpltCallback.

/* USER CODE BEGIN Private defines */
typedef struct
{
	uint8_t *rx_buf;		//接收缓冲数组
	uint16_t rx_buf_cnt;	//接收缓冲计数值
	uint16_t rx_size;		//接收数据大小
	uint8_t rx_flag;		//接收完成标志位
	
	uint8_t *tx_buf;		//发送缓冲数组
	uint16_t tx_buf_cnt;	//发送缓冲计数值
	uint16_t tx_size;		//实际发送数据大小
}UART_BUF;					//串口结构体

extern UART_BUF uart4;		//串口结构体实体
/* USER CODE END Private defines */

void MX_UART4_Init(void);

/* USER CODE BEGIN Prototypes */
void E_USART_INIT(UART_HandleTypeDef *huart);
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart);

/* USER CODE END Prototypes */

 2.2完善usart.c

2.2.1头文件完善

在/*USER CODE BEGIN 0*/和/*USER CODE END 0*/中间添加完善程序

/* USER CODE BEGIN 0 */
#include "string.h"
#include "tim.h"
#define UART4_RXSIZE	1024	//一帧接收数据的最大值
#define UART4_TXSIZE	1024	//一帧发送数据的最大值

uint8_t uart4_rx_buf[UART4_RXSIZE];	//发送数据缓冲数组
uint8_t uart4_tx_buf[UART4_TXSIZE];	//接收数据缓冲数据

UART_BUF uart4;			//串口结构体实体
uint8_t RxBuffer;		//接收数据中间变量
/* USER CODE END 0 */

2.2.2增加回调函数

在/* USER CODE BEGIN 1 */和/* USER CODE END 1 */增加回调函数HAL_UART_RxCpltCallback。

基本原理为接收到一个数据调用回调函数(RxBuffer),然后将数据赋值给rx_buf这个数组,然后清除定时器的计数,重新开始计数,防止定时器产生中断。

/*****************************重写回调函数,实现串口数据接收**********************/
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
	if(huart->Instance == UART4)
	{
		if(uart4.rx_buf_cnt >= UART4_RXSIZE-1)	//接收数据量超限,错误
		{
			uart4.rx_buf_cnt = 0;
			memset(uart4.rx_buf, 0x00, sizeof(uart4.rx_buf));
			HAL_UART_Transmit(huart, (uint8_t *)"数据溢出", 10, 0xFFFF);		
		}
		else									//接收正常
		{
			uart4.rx_buf[uart4.rx_buf_cnt++] = RxBuffer;	//接收数据存储到rx_buf
			HAL_TIM_Base_Stop_IT(&htim7);
			__HAL_TIM_SET_COUNTER(&htim7, 0);
			HAL_TIM_Base_Start_IT(&htim7);		//将定时器7的计数值清零后重新计数
		}
		HAL_UART_Receive_IT(huart, (uint8_t *)&RxBuffer, 1);
	}
}

2.2.3串口初始化函数

在回调函数下方增加串口参数初始化函数E_USART_INIT

/*****************************对UART_BUF结构体的实体uart4赋值**********************/
void E_USART_INIT(UART_HandleTypeDef *huart)
{
	if(huart->Instance == UART4)
	{
		uart4.rx_buf = uart4_rx_buf;	//接收数据变量初始化
		uart4.rx_buf_cnt = 0;
		uart4.rx_size = 0;
		uart4.rx_flag = 0;
		
		uart4.tx_buf = uart4_rx_buf;	//发送数据变量初始化
		uart4.tx_buf_cnt = UART4_TXSIZE;
		uart4.tx_size = 0;		
		
		HAL_UART_Receive_IT(huart, uart4.rx_buf, 1);	//开启接收中断
	}

}

在初始化过程中最后一句话是开启中断,让每接收一个数据进入一次回调函数。

2.3完善tim.h

增加在tim.c中的函数声明,在/* USER CODE BEGIN Prototypes */和/* USER CODE END Prototypes */中间增加:

/* USER CODE BEGIN Prototypes */
void E_TIM_INIT(TIM_HandleTypeDef *htim);
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim);
/* USER CODE END Prototypes */

2.4完善tim.c

2.4.1完善头文件

在头文件增加一个函数引用

/* USER CODE BEGIN 0 */
#include "usart.h"
/* USER CODE END 0 */

 2.4.2完善回调函数和初始化函数

在/* USER CODE BEGIN 1 */和/* USER CODE END 1 */内部增加时间回调函数和时间初始化函数。具体含义已在注释内说明,此处不赘述。

/* USER CODE BEGIN 1 */
/*****************************重写时间回调函数**********************/
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
	if(htim == &htim7)
	{
		__HAL_TIM_CLEAR_FLAG(&htim7, TIM_FLAG_UPDATE);	//产生中断证明超过4ms没有接收到数据了,一帧接收完成
		HAL_TIM_Base_Stop_IT(&htim7);		//中断之后停止定时器,开启在下一次接收到数据开始
		uart4.rx_size = uart4.rx_buf_cnt;	//将接收到数据数量赋值
		uart4.rx_buf_cnt = 0;				//清零
		uart4.rx_flag = 1;					//接收完成,置1
	}

}

void E_TIM_INIT(TIM_HandleTypeDef *htim)
{
	if(htim == &htim7)
	{
		__HAL_TIM_CLEAR_FLAG(htim, TIM_FLAG_UPDATE);		//手动添加
		HAL_TIM_Base_Start_IT(htim);
	}

}

/* USER CODE END 1 */

2.5完善main.c

上面的函数完善都是为了处理数据发送和接收的函数,通过以上处理可以完成数据的发送和接受。在移植MODBUS函数之前可以对数据发送和接受是否正常进行测试。此处的main.c就是完成数据的转发功能,即接收到什么数据就向外转发什么数据。

首先在  /* USER CODE BEGIN 2 */和  /* USER CODE END 2 */内部增加定时器和串口的初始化函数

  /* USER CODE BEGIN 2 */
	E_USART_INIT(&huart4);
	E_TIM_INIT(&htim7);
  /* USER CODE END 2 */

然后再在主函数的while循环内增加程序:

  while (1)
  {
    /* USER CODE END WHILE */
	  
    /* USER CODE BEGIN 3 */
	  // 此处是用来测试收啥发啥的。	  
	  if(uart4.rx_flag == 1)	//如果一帧数据接收完成,其在tim7的回调函数置位
	  {
		HAL_UART_Transmit(&huart4, (uint8_t *)(uart4.rx_buf), uart4.rx_size, 500);//向外转发收到的数据
		while(__HAL_UART_GET_FLAG(&huart4,UART_FLAG_TC)!=SET);	//死循环等待
		uart4.rx_buf_cnt = 0;									//计数值清零
		uart4.rx_flag=0;										//接收完成标志位清零
	  }
	  
	  HAL_Delay(5);		//每间隔5ms循环一次
  }
  /* USER CODE END 3 */
}

2.6调试

2.6.1KEIL的设置

为了确保每次程序下载完成后后自动复位运行,需要对KEIL进行的debug进行设置,设置步骤如下:将Reset and Run前面的√点上。

 

 2.6.2程序下载调试

编译无误后将程序下载到电路板中,然后将电路板的UART4的串口与电脑口相连。打开串口调试助手,按照程序在串口调试助手内进行相应配置。

配置完成之后,打开串口就可以进行数据发送接收了。

 

 

 

### 回答1: STM32 HAL库可以与FreeRTOS和FreeModbus相结合使用,以实现IAR IAR作为开发环境。 FreeRTOS是一个开源的实时操作系统,可以优化处理器资源使用,提供任务调度、时间管理、IPC等功能。STM32 HAL库提供与FreeRTOS的适配层,使得在STM32芯片上可以轻松地使用FreeRTOS。 FreeModbus是一个开源的Modbus通信协议栈,用于在主机和从机之间进行通信。通过使用HAL库串口驱动功能,可以实现STM32作为Modbus从机或主机。 将HAL库和FreeRTOS集成到IAR开发环境中,可以按照以下步骤进行: 1. 创建一个新的项目,并包括HAL库和FreeRTOS的源码文件。可以从ST官网下载最新版本的HAL库和FreeRTOS。 2. 配置IAR工程,包括编译器选项、链接器脚本等。确保HAL库和FreeRTOS的路径正确,并添加需要的头文件和文件。 3. 在main函数中初始化HAL库和FreeRTOS。HAL库提供了相应的初始化函数和配置选项,可以根据具体的需求进行设置。在FreeRTOS中,可以创建任务、定时器、队列等。 4. 在任务中添加FreeModbus代码。根据需要,可以实现STM32作为Modbus从机或主机的功能。在从机模式下,可以使用HAL库中的串口驱动来接收和发送Modbus数据。 5. 编译和下载代码STM32芯片。使用IAR进行编译和链接,并通过JTAG/SWD调试器将代码下载到芯片上。 通过以上步骤,即可实现STM32 HAL库与FreeRTOS和FreeModbus的结合使用,从而在IAR开发环境中实现相应的功能。 ### 回答2: STM32 HAL库可以与FreeRTOS和FreeModbus从机和主机)一起使用来开发IAR嵌入式系统。 首先,STM32 HAL库为开发者提供了许多硬件抽象层函数,可以轻松控制STM32系列微控制器的各种外设和功能。它简化了对硬件的操作,提高了开发效率。 FreeRTOS是一个流行的实时操作系统,可用于嵌入式系统的并发和调度管理。通过与STM32 HAL库的配合使用,开发者可以在STM32微控制器上运行多个任务,并使用FreeRTOS提供的任务管理功能来调度和控制任务的执行。 FreeModbus是一种用于Modbus通信协议的开源实现。它提供了主机和从机两种模式,可以在STM32微控制器上实现Modbus通信。通过STM32 HAL库和FreeModbus的集成,开发者可以使用STM32的串行通信外设来实现Modbus通信,并利用FreeModbus函数来处理Modbus消息的接收和发送。 IAR是一种广泛使用的集成开发环境(IDE),用于开发嵌入式系统的软件。通过在IAR中配置STM32 HAL库、FreeRTOS和FreeModbus,开发者可以将它们整合在一起,并通过IAR的编译器和调试器来构建和调试嵌入式应用程序。 综上所述,开发者可以使用STM32 HAL库实现FreeRTOS和FreeModbus从机和主机)功能,通过IAR进行开发。这样的设计方案可以提高开发效率和可靠性,使得在STM32微控制器上开发嵌入式系统变得更加容易和高效。 ### 回答3: STM32 HAL库可以与FreeRTOS和FreeModbus一起使用来在IAR集成开发环境中实现主机和从机的通信。 首先,需要在IAR环境中配置STM32 HAL库,并根据需要选择所需的外设和功能。然后,导入FreeRTOS和FreeModbus,并将其配置为HAL库的一部分。这可以通过在IAR中设置包含路径和链接实现。 对于FreeRTOS的实现,首先需要配置任务和中断管理器。可以使用HAL库提供的任务和中断API来创建、挂起和恢复任务,并设置任务优先级。使用HAL库提供的定时器或计数器来实现任务调度。 对于FreeModbus实现,需要配置串口或其他通信接口以与主机进行通信。可以使用HAL库提供的串口或SPI接口功能来配置通信接口。然后,可以使用FreeModbus函数实现Modbus协议的从机或主机功能。这些函数包括读写寄存器、处理请求和响应等。 在主机端,可以使用HAL库提供的定时器或计数器来实现Modbus主机的发送和定时功能。在从机端,可以使用HAL库提供的中断或轮询功能来处理Modbus从机的请求和响应。同时,还需要实现处理从机地址和功能码的逻辑。 最后,可以在IAR中编译、调试和烧录代码。使用HAL库、FreeRTOS和FreeModbus的API来编写主机和从机的应用程序代码。在应用程序中,可以实现与其他设备的通信,并处理数据传输和处理的逻辑。 通过使用STM32 HAL库、FreeRTOS和FreeModbus,可以方便地在IAR环境中实现主机和从机的通信,并实现Modbus协议的功能。
评论 15
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值