STM32F429 CubeMX DMA+空闲中断实现RS485不定长度自动收发
建立工程
-
选择好芯片后,首先设置RCC
-
设配置时钟,我这里选择了外部晶振,配置到180MHZ的频率。
-
调试借口用的是jlink的SWD,HAL库的时基选择systick
-
配置USART1为异步串口
-
添加DMA接收,单字节,正常模式
-
添加DMA发送,单字节,正常模式
-
打开串口中断
-
配置NVIC分组为2,这里还可以配置各个中断的优先级
-
配置了两个GPIO,一个是LED,还有一个是485的收发控制引脚U1_EN
-
配置工程IDE为mdk工程
-
勾选此处为每个外设单独创建c和h文件
-
这里默认都是HAL库
-
最后点击生成GENERATE CODE,生成代码,然后直接打开MDK工程
添加代码
- “usart.h”中创建一个串口收发缓存结构体
/* USER CODE BEGIN Private defines */
#define USART_BUFF_SIZE 512
typedef struct
{
uint8_t Rxbuff[USART_BUFF_SIZE];
uint8_t Txbuff[USART_BUFF_SIZE];
uint16_t Rxlen;
uint16_t Txlen;
} _USART_Buff;
/* USER CODE END Private defines */
- “usart.c”中创建串口收发缓存全局变量,添加"string.h"头文件
/* USER CODE BEGIN 0 */
#include "string.h"
_USART_Buff USART1_Buff;
/* USER CODE END 0 */
- 在MX_USART1_UART_Init中添加代码
/* USER CODE BEGIN USART1_Init 2 */
__HAL_UART_ENABLE_IT(&huart1, UART_IT_IDLE); //开启IDLE中断,以帧方式接收不定长数据
HAL_UART_Receive_DMA(&huart1, USART1_Buff.Rxbuff, USART_BUFF_SIZE); //开始DMA接收
/* USER CODE END USART1_Init 2 */
- “usart.c”文件末尾添加空闲中断处理程序
/* USER CODE BEGIN 1 */
void UsartReceive_IDLE(UART_HandleTypeDef *huart) //串口接收空闲中断
{
if((__HAL_UART_GET_FLAG(huart,UART_FLAG_IDLE) != RESET))
{
if(huart->Instance == USART1)
{
__HAL_UART_CLEAR_IDLEFLAG(huart); //清中断
HAL_UART_AbortReceive(huart); //已经接收完一帧数据,所以这里要停止接收,然后再重新接收
USART1_Buff.Rxlen=USART_BUFF_SIZE-hdma_usart1_rx.Instance->NDTR; //获取接收到的数据数量
memcpy(USART1_Buff.Txbuff,USART1_Buff.Rxbuff,USART1_Buff.Rxlen); //将接收到的数据复制到发送缓冲区
USART1_Buff.Txlen=USART1_Buff.Rxlen; //设置发送的字节数
if(USART1_Buff.Txlen>0)
{
HAL_GPIO_WritePin(U1_EN_GPIO_Port,U1_EN_Pin,GPIO_PIN_SET); //U1_EN置高电平为发送模式
HAL_UART_Transmit_DMA(huart,USART1_Buff.Txbuff,USART1_Buff.Txlen); //DMA发送数据
}
memset(USART1_Buff.Rxbuff,0x00,USART_BUFF_SIZE); //清空缓存,重新接收
HAL_UART_Receive_DMA(huart,(uint8_t *)&USART1_Buff.Rxbuff,USART_BUFF_SIZE); //开启DMA接收
}
}
}
void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart) //HAL的发送完成回调函数
{
HAL_GPIO_WritePin(U1_EN_GPIO_Port,U1_EN_Pin,GPIO_PIN_RESET); //U1_EN置低电平为接收模式
}
/* USER CODE END 1 */
- “usart.h”添加串口空闲中断程序的声明
/* USER CODE BEGIN Prototypes */
void UsartReceive_IDLE(UART_HandleTypeDef *huart);
/* USER CODE END Prototypes */
- "stm32f4xx_it.c"添加usart.h头文件
/* USER CODE BEGIN Includes */
#include "usart.h"
/* USER CODE END Includes */
- USART1_IRQHandler中断服务函数里面添加空闲中断处理程序
/* USER CODE BEGIN USART1_IRQn 0 */
UsartReceive_IDLE(&huart1);
/* USER CODE END USART1_IRQn 0 */
- 最后在“main.c"的大循环里添加LED闪烁程序
while (1)
{
HAL_GPIO_TogglePin(LED_GPIO_Port,LED_Pin);
HAL_Delay(500);
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
}
- xcom串口测试,数据回环很稳定