串口几种通信模式:
Mode:异步通信(Asynchronous)、同步通信(Synchronous)、Single Wire(Half-Duplex)单线半双工通信、Multiprocessor Communication多机通信、irDA红外数据、LIN总线、SmartCard(智能卡IC卡)、SmartCard With Card Clock
这里介绍串口接收不定长数据的三种方式:
方法一:串口接受数据,定时器来判断超时是否接受数据完成。
方法二:DMA+IDLE中断。
方法三:直接利用STM32的RXNE和IDLE中断实现接收不定长数据。
这里主要讲解一下方法二的实现:
采用STM32F103的串口1,并配置成空闲中断IDLE模式且使能DMA接收,并同时设置接收缓冲区和初始化DMA。那么初始化完成之后,当外部给单片机发送数据的时候,假设这帧数据长度是200个字节,那么在单片机接收到一个字节的时候并不会产生串口中断,而是DMA在后台把数据默默地搬运到你指定的缓冲区里面。当整帧数据发送完毕之后串口才会产生一次中断,此时可以利用DMA_GetCurrDataCounter();函数计算出本次的数据接受长度,从而进行数据处理。
应用对象:适用于各种串口相关的通信协议,如:MODBUS,PPI ;还有类似于GPS数据接收解析,串口WIFI的数据接收等,都是很好的应用对象。
STM32CuBe_MX配置
配置成异步通信、打开全局中断
打开串口DMA
上拉输入引脚
代码的修改配置:
回调函数的代码
extern uint8_t rebuf[200];
void USER_UART_IRQHandler(UART_HandleTypeDef *huart)
{
if(USART1 == huart1.Instance) //判断是否是串口1
{
if(RESET != __HAL_UART_GET_FLAG(&huart1, UART_FLAG_IDLE)) //判断是否是空闲中断
{
__HAL_UART_CLEAR_IDLEFLAG(&huart1); //清楚空闲中断标志(否则会一直不断进入中断)
HAL_UART_DMAStop(&huart1); //停止本次DMA传输
uint8_t data_length = BUFFER_SIZE - __HAL_DMA_GET_COUNTER(&hdma_usart1_rx); //计算接收到的数据长度
HAL_UART_Transmit_DMA(&huart1,rebuf,data_length); //DMA发送函数:将接收到的数据打印出去
data_length = 0; //数据长度清零
}
}
__HAL_UART_ENABLE_IT(&huart1, UART_IT_IDLE);
HAL_UART_Receive_DMA(&huart1, (uint8_t*)rebuf, 200);
}
主函数
uint8_t rebuf[200];
__HAL_UART_ENABLE_IT(&huart1, UART_IT_IDLE);
HAL_UART_Receive_DMA(&huart1, (uint8_t*)rebuf, 200);
HAL_UART_Transmit_DMA(&huart1,rebuf,29);
中断函数添加
void USART1_IRQHandler(void)
{
/* USER CODE BEGIN USART1_IRQn 0 */
/* USER CODE END USART1_IRQn 0 */
HAL_UART_IRQHandler(&huart1);
/* USER CODE BEGIN USART1_IRQn 1 */
USER_UART_IRQHandler(&huart1);
/* USER CODE END USART1_IRQn 1 */
}
原文:https://www.cnblogs.com/ddwork/p/14356487.html