FreeRTOS + ModbusRTU
通过正点原子的STM32F407板子,实现了ModbusRTU,03,06,10,三个功能,可以实现电脑主站和板子的通信,本文还加入了FreeRTOS,当做是练习了。
1.STM32CubeMX的配置
1.1
首先调试功能选择Trace Asynchronous Sw,时钟选择TIM1,是为了跟踪调试
1.2 RCC设置
1.3定时器选择
我选的是TIM3
时钟源是Internal Clock;
自动重装载值arr=9;
预分频系数PSC=7199;
主频Tclk=72M;
根据定时器溢出时间公式Tout= ((arr+1)*(psc+1))/Tclk,(1M=1000000)
溢出时间Tout=((9+1)*(7199+1))/72000000=1ms
然后使能时钟
1.4 USART设置
波特率为9600
1.5 FreeRTOS设置
任务线程设置
1.6 中断优先级设置
1.7 USART
PA9,PA10设置相同
1.8
1.9
生成代码
2.0 代码
2.1首先在freertos.c文件中添加任务线程函数
void StartModbusTask(void *argument)
{
/* USER CODE BEGIN StartModbusTask */
/* Infinite loop */
for(;;)
{
if(uart1.rx_start == 0x01)
{
uart1.rx_start = 0x00;
ModbusTask();
osDelay(1);
}
} /* USER CODE END StartModbusTask */
}
在/* USER CODE BEGIN Includes / 和/ USER CODE END Includes */中添加头文件
/* USER CODE BEGIN Includes */
#include "modbustask.h"
#include "defaultTask.h"
/* USER CODE END Includes */
2.2定时器回调函数
在main.c中添加
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
/* USER CODE BEGIN Callback 0 */
/* USER CODE END Callback 0 */
if (htim->Instance == TIM1) {
HAL_IncTick();
}
/* USER CODE BEGIN Callback 1 */
if(htim == &htim3)
{
uCnt ++;
if(uCnt >= 4)
{
uCnt = 0;
HAL_TIM_Base_Stop_IT(&htim3); // 停止定时器
HAL_UART_RxCpltCallback(&huart1); // 一帧传输完成
}
}
/* USER CODE END Callback 1 */
}
同样在main.c中/* USER CODE BEGIN 2 /和 / USER CODE END 2 */之间添加
/* USER CODE BEGIN 2 */
E_USART_INIT(&huart1);
/* USER CODE END 2 */
在main.c中添加头文件
/* USER CODE BEGIN Includes */
#include <stdarg.h>
#include "modbustask.h"
/* USER CODE END Includes */
在tim.h中添加
```c
/* USER CODE BEGIN Includes */
extern uint8_t uCnt;
/* USER CODE END Includes */
同时在 tim.c 中添加对"usart.h"的包含,并定义 uCnt 变量
#include "tim.h"
#include "usart.h"
/* USER CODE BEGIN 0 */
uint8_t uCnt = 0;
/* USER CODE END 0 */
TIM_HandleTypeDef htim3 ;
``
2.3在stm32f4xx_hal_uart.c文件中在void HAL_UART_IRQHandler(UART_HandleTypeDef *huart)函数中对以下的函数片段进行丰富
/
* UART in mode Receiver -------------------------------------------------*/
if (((isrflags & USART_SR_RXNE) != RESET) && ((cr1its & USART_CR1_RXNEIE) != RESET))
{
UART_Receive_IT(huart);
return;
}
改为如下
的中断处理
/* UART in mode Receiver -------------------------------------------------*/
if (((isrflags & USART_SR_RXNE) != RESET) && ((cr1its & USART_CR1_RXNEIE) != RESET))
{
UART_Receive_IT(huart);
if(uCnt >= 2) // 数据接收非法,清除已经接收数据
{
uCnt = 0;