|
雷达应用接收的数据量比较大,因此需要用到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中断来接收不定长数据的话,也可能正合适。
下面通过串口软件发送不同长度的数据进行简单测试:都能正确接收回送。附: