打印
[STM32F1]

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

[复制链接]
465|5
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
DMA接收选用circle模式,如果是normal模式的话,需要每次在中断里面接收完成后重新开启DMA接收,circle模式不用每次都开启dma接收中断。如图

使用特权

评论回复
沙发
杨寅辉|  楼主 | 2020-6-28 11:21 | 只看该作者

#define UART_BUFFER_SIZE        64

typedef struct _uart_rx_struct{
        uint8_t rx_flag;
        uint8_t rx_size;
        uint8_t buffer[UART_BUFFER_SIZE];
}uart_rx_struct;

uart_rx_struct uart1_rx;
uint8_t uart1_rx_buffer[UART_BUFFER_SIZE];

使用特权

评论回复
板凳
杨寅辉|  楼主 | 2020-6-28 11:25 | 只看该作者
void MX_USART1_UART_Init(void)
{

  huart1.Instance = USART1;
  huart1.Init.BaudRate = 115200;
  huart1.Init.WordLength = UART_WORDLENGTH_8B;
  huart1.Init.StopBits = UART_STOPBITS_1;
  huart1.Init.Parity = UART_PARITY_NONE;
  huart1.Init.Mode = UART_MODE_TX_RX;
  huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE;
  huart1.Init.OverSampling = UART_OVERSAMPLING_16;
  if (HAL_UART_Init(&huart1) != HAL_OK)
  {
    Error_Handler();
  }
    __HAL_UART_ENABLE_IT(&huart1, UART_IT_IDLE);//使能idle中断
    HAL_UART_Receive_DMA(&huart1,uart1_rx_buffer,UART_BUFFER_SIZE);//打开DMA接收,数据存入

}

使用特权

评论回复
地板
杨寅辉|  楼主 | 2020-6-28 11:26 | 只看该作者
接收中断里面按如下所示
void USART1_IRQHandler(void)
{
        uint32_t temp;
    static uint8_t dma_rx_last_pt=0;
    uint8_t rx_len=0;
        uint32_t tmp_flag =__HAL_UART_GET_FLAG(&huart1,UART_FLAG_IDLE); //获取IDLE标志位
        if((tmp_flag != RESET))//idle标志被置位
        {
                __HAL_UART_CLEAR_IDLEFLAG(&huart1);//清除标志位
                temp  = hdma_usart1_rx.Instance->NDTR;// 获取DMA中未传输的数据个数,NDTR寄存器分析见下面
                if(dma_rx_last_pt > temp)
                {
            rx_len = dma_rx_last_pt - temp;
            for(uint8_t i=0;i<rx_len;i++)
                    uart1_rx.buffer[i] = uart1_rx_buffer[UART_BUFFER_SIZE-dma_rx_last_pt+i];
                        uart1_rx.rx_flag = 1;
                        uart1_rx.rx_size = rx_len;
                }
        else
        {
            rx_len = UART_BUFFER_SIZE + dma_rx_last_pt - temp;
            for(uint8_t i=0;i<dma_rx_last_pt;i++)
                    uart1_rx.buffer[i] = uart1_rx_buffer[UART_BUFFER_SIZE-dma_rx_last_pt+i];
            for(uint8_t i=0;i<UART_BUFFER_SIZE-temp;i++)
                    uart1_rx.buffer[dma_rx_last_pt+i] = uart1_rx_buffer[i];
                        uart1_rx.rx_flag = 1;
                        uart1_rx.rx_size = rx_len;
        }
                dma_rx_last_pt = temp;
    }
        tmp_flag =__HAL_UART_GET_FLAG(&huart1,USART_SR_TC);
        if((tmp_flag != RESET))
        {
                __HAL_UART_CLEAR_FLAG(&huart1, UART_IT_TC);
                huart1.gState = HAL_UART_STATE_READY;
        }
}


使用特权

评论回复
5
杨寅辉|  楼主 | 2020-6-28 11:27 | 只看该作者
STM32F767单片机串口中断
void UART4_IRQHandler(void)
{
        uint32_t temp;
    static uint8_t dma_rx_last_pt=0;
    uint8_t rx_len=0;
        uint32_t tmp_flag =__HAL_UART_GET_FLAG(&huart4,UART_FLAG_IDLE); //获取IDLE标志
        if((tmp_flag != RESET))//idle标志被置
        {
                __HAL_UART_CLEAR_IDLEFLAG(&huart4);//清除标志
                temp  = hdma_uart4_rx.Instance->NDTR;// 获取DMA中未传输的数据个数,NDTR寄存器分析见下面
                if(dma_rx_last_pt > temp)
                {
            rx_len = dma_rx_last_pt - temp;
            for(uint8_t i=0;i<rx_len;i++)
                    uart4_rx.buffer[i] = uart4_rx_buffer[UART_BUFFER_SIZE-dma_rx_last_pt+i];
            uart4_rx.rx_flag = 1;
            uart4_rx.rx_size = rx_len;
                }
        else
        {
            rx_len = UART_BUFFER_SIZE + dma_rx_last_pt - temp;
            for(uint8_t i=0;i<dma_rx_last_pt;i++)
                    uart4_rx.buffer[i] = uart4_rx_buffer[UART_BUFFER_SIZE-dma_rx_last_pt+i];
            for(uint8_t i=0;i<UART_BUFFER_SIZE-temp;i++)
                    uart4_rx.buffer[dma_rx_last_pt+i] = uart4_rx_buffer[i];
            uart4_rx.rx_flag = 1;
            uart4_rx.rx_size = rx_len;
        }
                dma_rx_last_pt = temp;
        }
        tmp_flag =__HAL_UART_GET_FLAG(&huart4,USART_ISR_TC);
        if((tmp_flag != RESET))
        {
                __HAL_UART_CLEAR_FLAG(&huart1, UART_IT_TC);
                huart4.gState = HAL_UART_STATE_READY;
        }

}


使用特权

评论回复
6
杨寅辉|  楼主 | 2020-6-28 11:28 | 只看该作者
void user_Uart1Handler()
{
        if((__HAL_UART_GET_FLAG(&huart1,UART_FLAG_RXNE)!=RESET))
        {
                        if(uart1RxState==UART_RX_STATE_READY)   //接收到一帧中的第一个字节
                        {
                                   uart1RxState=UART_RX_STATE_START;
                                  __HAL_UART_ENABLE_IT(&huart1,UART_IT_IDLE);   //打开空闲中断
                                  uart1RxCounter=0;                             //计数清零
                                  uart1RxBuf[uart1RxCounter]=(uint8_t)(huart1.Instance->DR & (uint8_t)0x00FF);
                                  uart1RxCounter++;
                        }
                        else if(uart1RxState==UART_RX_STATE_START)  
                        {
                                  uart1RxBuf[uart1RxCounter]=(uint8_t)(huart1.Instance->DR & (uint8_t)0x00FF);
                                  uart1RxCounter++;
                        }
                        __HAL_UART_CLEAR_FLAG(&huart1,UART_FLAG_RXNE);
                  
        }
        if((__HAL_UART_GET_FLAG(&huart1,UART_FLAG_IDLE)!=RESET))  //进入空闲中断
        {         
                  __HAL_UART_CLEAR_FLAG(&huart1, UART_FLAG_IDLE);    //关了空闲中断
                  __HAL_UART_DISABLE_IT(&huart1,UART_IT_RXNE);    //关了接收完成中断
                  uart1RxState=UART_RX_STATE_DEAL;                //状态表明一帧数据接收完成了,需要处理。处理完以后再把接收中断打开
        }
}


使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

39

主题

295

帖子

2

粉丝