注册 登录
电子工程世界-论坛 返回首页 EEWORLD首页 频道 EE大学堂 下载中心 Datasheet 专题
lbbook的个人空间 https://home.eeworld.com.cn/space-uid-276713.html [收藏] [复制] [分享] [RSS]
日志

(3)UART之DMA加IDLE中断不定长字节接收

已有 289 次阅读2022-4-17 21:52 |个人分类:GD32L233C-START

雷达应用接收的数据量比较大,因此需要用到DMA来提高速度,降低MCU负载。之前的项目已经在STM32F103芯片上使用了DMA+IDLE中断的方式实现了不定长的UART数据接收,这里也想在GD32L233C实现。

 

GD32L233C-START开发板配套的例程GD32L233K_START_Demo_Suites只有6个例程。关于UART接口的只有04_USART_HyperTerminal_Interrupt这一个例程。也不是我想要的DMA。但是我看到GD32L23x_Demo_Suites_V1.1.0这个例程包里面还有另外一个开发板的配套例程GD32L233R_EVAL_Demo_Suites,里面有多达24个例程。光UART相关就有4个,特别是包含DMA的例程,真是柳暗花明又一村。

 

例程是这样的:启动后,USART将输出“USART DMA interrupt receive and transmit example, please input 10 bytes:”并等待接收由超级终端发送10个字节的数据。MCU接收到数据后,串口将接收到的数据继续输出到超级终端。

 

功能实在是太简单了,好在DMA收发功能都已经初始化完毕,因此只需要进行简单修改就好了。

 

首先是GD32L233C-START开发板使用的是USART0,对应的IO是PA9和PA10,因此需要修改所有相关代码。这里就不展开了。

 

其次是需要添加IDLE中断相关使能代码。

main.c中系统初始化UART后面添加UART中断使能以及IDLE中断使能,

    /* USART interrupt configuration */
    nvic_irq_enable(USART0_IRQn, 0);
    /* enable USART1 IDLE interrupt */
    usart_interrupt_enable(USART0, USART_INT_IDLE);

   特别是前一句,如果未添加的话无法进入中断,也就没有IDLE中断了。我也是看了05_USART_HyperTerminal_Interrupt这个例程才找到原因的。

gd32l23x_it.c中添加IDLE中断调用:

void USART0_IRQHandler(void)
{
    if(RESET != usart_interrupt_flag_get(USART0, USART_INT_FLAG_IDLE)) {
      usart_interrupt_flag_clear(USART0, USART_INT_FLAG_IDLE);  // 清标志
      dma_channel_disable(DMA_CH1);  // 关闭DMA
      //DMA接收到数据后CHCNT是往下减的,因此已经接收到的数据长度=DMA总长-当前CHCNT
      g_receive_count = RX_NUM - DMA_CHCNT(DMA_CH1);  
      /* configure the number of remaining data to be transferred */
      DMA_CHCNT(DMA_CH1) = RX_NUM;  // 复位DMA计数
      dma_channel_enable(DMA_CH1);  // 使能DMA
      g_receive_complete = SET;  // 接收数据标志置高
    }
    // 这里可以添加各种通讯错误处理
}

   这里需要对DMA进行干预,因为发生了IDLE事件,即收到一个短于DMA设置长度的数据段,此时可将数据进行处理,然后重新复位DMA计数,否则DMA会将两个甚至多个数据段拼合,导致错误。当然,如果不是像我一样设置了较大的DMA缓存,主要通过IDLE中断来接收不定长数据的话,也可能正合适。

下面通过串口软件发送不同长度的数据进行简单测试:都能正确接收回送。附:

本文来自论坛,点击查看完整帖子内容。

评论 (0 个评论)

facelist doodle 涂鸦板

您需要登录后才可以评论 登录 | 注册

热门文章