其他分享
首页 > 其他分享> > STM32CUbeMAX 串口+DMA中断收发实验

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