STM32CUbeMAX 串口+DMA中断收发实验
作者:互联网
串口配置: 异步,波特率:19200,每帧:1字节;无校验;1停止位
中断设置:考虑到后期使用freertos,可控制中断配置为:4位抢占优先级,15>=中断优先级级>=5(越低,优先级越高)
DMA设置:以字节为数据单位,内存地址累加
生成工程文件:
在stm32f1xx_it.h 文件添加
#define BUFF_MAX 100 #接收缓冲区大小 extern volatile uint8_t rx_len; //接收一帧数据的长度 extern volatile uint8_t recv_end_flag; //一帧数据接收完成标志 extern uint8_t rx_buffer[BUFFER_SIZE]; //接收数据缓存数组
在stm32f1xx_it.c文件添加
volatile uint8_t rx_len ; //接收一帧数据的长度 volatile uint8_t recv_end_flag; //一帧数据接收完成标志 uint8_t rx_buffer[BUFFER_SIZE]; //接收数据缓存数组
在stm32f1xx_it.c修改中断串口1中断函数为
void USART1_IRQHandler(void) { /* USER CODE BEGIN USART1_IRQn 0 */ uint32_t tmp_flag = 0; uint32_t temp; tmp_flag =__HAL_UART_GET_FLAG(&huart1,UART_FLAG_IDLE); //获取IDLE标志位 if((tmp_flag != RESET))//idle标志被置位 { __HAL_UART_CLEAR_IDLEFLAG(&huart1);//清除标志位 HAL_UART_DMAStop(&huart1); // temp = __HAL_DMA_GET_COUNTER(&hdma_usart1_rx);// 获取DMA中未传输的数据个数 //temp = hdma_usart1_rx.Instance->NDTR;//读取NDTR寄存器 获取DMA中未传输的数据个数, //这句和上面那句等效 rx_len = BUFFER_SIZE - temp; //总计数减去未传输的数据个数,得到已经接收的数据个数 recv_end_flag = 1; // 接受完成标志位置1 } /* USER CODE END USART1_IRQn 0 */ HAL_UART_IRQHandler(&huart1); /* USER CODE BEGIN USART1_IRQn 1 */ /* USER CODE END USART1_IRQn 1 */ }
在main函数添加:
uint8_t Recive_buff[Buff_Max]={0};//转存缓冲区数据,避免DMA引用的数组被其他地方操作而发生错误 HAL_UARTEx_ReceiveToIdle_DMA(&huart1,rx_buffer,BUFFER_SIZE);//打开DMA接收 while (1) { if(recv_end_flag == 1) //接收完成标志 { memcpy(Recive_buff,rx_buffer,rx_len); DMA_Usart_Send(Recive_buff,rx_len); memset(rx_buffer,0,rx_len); rx_len = 0;//清除计数 recv_end_flag = 0;//清除接收结束标志位 HAL_UARTEx_ReceiveToIdle_DMA(&huart1,rx_buffer,BUFFER_SIZE);//重新打开DMA接收
/** HAL_StatusTypeDef HAL_UARTEx_ReceiveToIdle_DMA(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size);
* 开串口hartx的DMA接收中断,响应IDLE中断,调用中断处理函数UART1_IQRHeahler();
* *huart:调用串口x
* *pData:dma转存数据地址
* BUFFER_SIZE:转存数据地址大小,此值大于最大传输数据+1(停止位),同时为 *hdma_usartx_rx->Instance->CNDTR 赋初始值,即temp = __HAL_DMA_GET_COUNTER(&hdma_usart1_rx)为该值(初值)-已转移值
*/
}
HAL_Delay(10); }
void DMA_Usart_Send(uint8_t *buf,uint8_t len)//串口发送封装 { if(HAL_UART_Transmit_DMA(&huart1, buf,len)!= HAL_OK) //判断是否发送正常,如果出现异常则进入异常中断函数 { Error_Handler(); } }
整体流程为:开串口及DMA中断,等待串口接收数据 -> 有数据传输,DMA转存数据,触发IDLE中断 -> 串口中断处理函数,关闭DMA传输,返回接收标志、数据大小 -> 主程序判断串口接收数据标志 - > DMA传输数据 -> 清除缓冲区 ->开启串口1 DMA接收中断
搜索
复制
标签:STM32CUbeMAX,DMA,HAL,rx,uint8,len,串口 来源: https://www.cnblogs.com/ysyyrps-hhl/p/16331335.html