[STM32F1] STM32cubeMX+DMA+USART 接收任意长度的数据

[复制链接]
 楼主| 杨寅辉 发表于 2020-6-28 11:20 | 显示全部楼层 |阅读模式
DMA接收选用circle模式,如果是normal模式的话,需要每次在中断里面接收完成后重新开启DMA接收,circle模式不用每次都开启dma接收中断。如图
872624-20200603234451317-1706727508.jpg
 楼主| 杨寅辉 发表于 2020-6-28 11:21 | 显示全部楼层

  1. #define UART_BUFFER_SIZE        64

  2. typedef struct _uart_rx_struct{
  3.         uint8_t rx_flag;
  4.         uint8_t rx_size;
  5.         uint8_t buffer[UART_BUFFER_SIZE];
  6. }uart_rx_struct;

  7. uart_rx_struct uart1_rx;
  8. uint8_t uart1_rx_buffer[UART_BUFFER_SIZE];
 楼主| 杨寅辉 发表于 2020-6-28 11:25 | 显示全部楼层
  1. void MX_USART1_UART_Init(void)
  2. {

  3.   huart1.Instance = USART1;
  4.   huart1.Init.BaudRate = 115200;
  5.   huart1.Init.WordLength = UART_WORDLENGTH_8B;
  6.   huart1.Init.StopBits = UART_STOPBITS_1;
  7.   huart1.Init.Parity = UART_PARITY_NONE;
  8.   huart1.Init.Mode = UART_MODE_TX_RX;
  9.   huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE;
  10.   huart1.Init.OverSampling = UART_OVERSAMPLING_16;
  11.   if (HAL_UART_Init(&huart1) != HAL_OK)
  12.   {
  13.     Error_Handler();
  14.   }
  15.     __HAL_UART_ENABLE_IT(&huart1, UART_IT_IDLE);//使能idle中断
  16.     HAL_UART_Receive_DMA(&huart1,uart1_rx_buffer,UART_BUFFER_SIZE);//打开DMA接收,数据存入

  17. }
 楼主| 杨寅辉 发表于 2020-6-28 11:26 | 显示全部楼层
接收中断里面按如下所示
  1. void USART1_IRQHandler(void)
  2. {
  3.         uint32_t temp;
  4.     static uint8_t dma_rx_last_pt=0;
  5.     uint8_t rx_len=0;
  6.         uint32_t tmp_flag =__HAL_UART_GET_FLAG(&huart1,UART_FLAG_IDLE); //获取IDLE标志位
  7.         if((tmp_flag != RESET))//idle标志被置位
  8.         {
  9.                 __HAL_UART_CLEAR_IDLEFLAG(&huart1);//清除标志位
  10.                 temp  = hdma_usart1_rx.Instance->NDTR;// 获取DMA中未传输的数据个数,NDTR寄存器分析见下面
  11.                 if(dma_rx_last_pt > temp)
  12.                 {
  13.             rx_len = dma_rx_last_pt - temp;
  14.             for(uint8_t i=0;i<rx_len;i++)
  15.                     uart1_rx.buffer[i] = uart1_rx_buffer[UART_BUFFER_SIZE-dma_rx_last_pt+i];
  16.                         uart1_rx.rx_flag = 1;
  17.                         uart1_rx.rx_size = rx_len;
  18.                 }
  19.         else
  20.         {
  21.             rx_len = UART_BUFFER_SIZE + dma_rx_last_pt - temp;
  22.             for(uint8_t i=0;i<dma_rx_last_pt;i++)
  23.                     uart1_rx.buffer[i] = uart1_rx_buffer[UART_BUFFER_SIZE-dma_rx_last_pt+i];
  24.             for(uint8_t i=0;i<UART_BUFFER_SIZE-temp;i++)
  25.                     uart1_rx.buffer[dma_rx_last_pt+i] = uart1_rx_buffer[i];
  26.                         uart1_rx.rx_flag = 1;
  27.                         uart1_rx.rx_size = rx_len;
  28.         }
  29.                 dma_rx_last_pt = temp;
  30.     }
  31.         tmp_flag =__HAL_UART_GET_FLAG(&huart1,USART_SR_TC);
  32.         if((tmp_flag != RESET))
  33.         {
  34.                 __HAL_UART_CLEAR_FLAG(&huart1, UART_IT_TC);
  35.                 huart1.gState = HAL_UART_STATE_READY;
  36.         }
  37. }


 楼主| 杨寅辉 发表于 2020-6-28 11:27 | 显示全部楼层
STM32F767单片机串口中断
  1. void UART4_IRQHandler(void)
  2. {
  3.         uint32_t temp;
  4.     static uint8_t dma_rx_last_pt=0;
  5.     uint8_t rx_len=0;
  6.         uint32_t tmp_flag =__HAL_UART_GET_FLAG(&huart4,UART_FLAG_IDLE); //获取IDLE标志
  7.         if((tmp_flag != RESET))//idle标志被置
  8.         {
  9.                 __HAL_UART_CLEAR_IDLEFLAG(&huart4);//清除标志
  10.                 temp  = hdma_uart4_rx.Instance->NDTR;// 获取DMA中未传输的数据个数,NDTR寄存器分析见下面
  11.                 if(dma_rx_last_pt > temp)
  12.                 {
  13.             rx_len = dma_rx_last_pt - temp;
  14.             for(uint8_t i=0;i<rx_len;i++)
  15.                     uart4_rx.buffer[i] = uart4_rx_buffer[UART_BUFFER_SIZE-dma_rx_last_pt+i];
  16.             uart4_rx.rx_flag = 1;
  17.             uart4_rx.rx_size = rx_len;
  18.                 }
  19.         else
  20.         {
  21.             rx_len = UART_BUFFER_SIZE + dma_rx_last_pt - temp;
  22.             for(uint8_t i=0;i<dma_rx_last_pt;i++)
  23.                     uart4_rx.buffer[i] = uart4_rx_buffer[UART_BUFFER_SIZE-dma_rx_last_pt+i];
  24.             for(uint8_t i=0;i<UART_BUFFER_SIZE-temp;i++)
  25.                     uart4_rx.buffer[dma_rx_last_pt+i] = uart4_rx_buffer[i];
  26.             uart4_rx.rx_flag = 1;
  27.             uart4_rx.rx_size = rx_len;
  28.         }
  29.                 dma_rx_last_pt = temp;
  30.         }
  31.         tmp_flag =__HAL_UART_GET_FLAG(&huart4,USART_ISR_TC);
  32.         if((tmp_flag != RESET))
  33.         {
  34.                 __HAL_UART_CLEAR_FLAG(&huart1, UART_IT_TC);
  35.                 huart4.gState = HAL_UART_STATE_READY;
  36.         }

  37. }


 楼主| 杨寅辉 发表于 2020-6-28 11:28 | 显示全部楼层
  1. void user_Uart1Handler()
  2. {
  3.         if((__HAL_UART_GET_FLAG(&huart1,UART_FLAG_RXNE)!=RESET))
  4.         {
  5.                         if(uart1RxState==UART_RX_STATE_READY)   //接收到一帧中的第一个字节
  6.                         {
  7.                                    uart1RxState=UART_RX_STATE_START;
  8.                                   __HAL_UART_ENABLE_IT(&huart1,UART_IT_IDLE);   //打开空闲中断
  9.                                   uart1RxCounter=0;                             //计数清零
  10.                                   uart1RxBuf[uart1RxCounter]=(uint8_t)(huart1.Instance->DR & (uint8_t)0x00FF);
  11.                                   uart1RxCounter++;
  12.                         }
  13.                         else if(uart1RxState==UART_RX_STATE_START)  
  14.                         {
  15.                                   uart1RxBuf[uart1RxCounter]=(uint8_t)(huart1.Instance->DR & (uint8_t)0x00FF);
  16.                                   uart1RxCounter++;
  17.                         }
  18.                         __HAL_UART_CLEAR_FLAG(&huart1,UART_FLAG_RXNE);
  19.                   
  20.         }
  21.         if((__HAL_UART_GET_FLAG(&huart1,UART_FLAG_IDLE)!=RESET))  //进入空闲中断
  22.         {         
  23.                   __HAL_UART_CLEAR_FLAG(&huart1, UART_FLAG_IDLE);    //关了空闲中断
  24.                   __HAL_UART_DISABLE_IT(&huart1,UART_IT_RXNE);    //关了接收完成中断
  25.                   uart1RxState=UART_RX_STATE_DEAL;                //状态表明一帧数据接收完成了,需要处理。处理完以后再把接收中断打开
  26.         }
  27. }


您需要登录后才可以回帖 登录 | 注册

本版积分规则

39

主题

295

帖子

2

粉丝
快速回复 在线客服 返回列表 返回顶部