4527|0

553

帖子

3

TA的资源

纯净的硅(初级)

楼主
 

【GD32L233C-START评测】4、USART用空闲中断和DMA实现不定长数据的接收 [复制链接]

对于串口的数据接收,很多的场合都需要接收不定长的数据。如果只是通过接收中断的方式来实现接收不定长数据会非常麻烦。

还好,GD32的这款L233 MCU的USART提供了idle中断功能。

idle中断结合DMA接收是接收不定长数据非常经典的方法,也是非常基础和常用的方法。

 

基本思路:

1.通过idle中断保证一帧数据接收完成

2.通过DMA获取接收到的数据的长度。

3.从buffer里获取指定长度的数据供应用程序处理

 

关于DMA,可能跟之前我们使用的有点区别,我没有找到外设和DMA通道的对应表。

直接使用DMA通道1作为USART的接收通道,发现可以正常使用。

 

例程里也提供了一个idle中的结合DMA的例子,例程使用的是USART1.

稍加改动,就可以改动到其它USART上面去。

本次我将使用USART0来实现idle中的和DMA接收功能。

 

USART0在开发板硬件上是直接通过uart转USB接口引出的,只需要一根usb线就可以实现与PC的通讯。

引脚用的是PA9(TX),PA10(RX)

如下:

 

程序上主要分为几个部分:

1.usart0的初始化:引脚配置,使能发送和接收,使能idle中断等;

2.接收DMA配置

3.idle中断的相关配置

4.usart0的中断处理函数实现

 

具体如下:

1.usart0的初始化:

void uart0_init(void)
{
		nvic_irq_enable(USART0_IRQn, 0);
    /* enable GPIO clock */
    rcu_periph_clock_enable(RCU_GPIOA);

    /* enable USART clock */
    rcu_periph_clock_enable(RCU_USART0);

    /* connect port to USART TX */
    gpio_af_set(GPIOA, GPIO_AF_7, GPIO_PIN_9);
    /* connect port to USART RX */
    gpio_af_set(GPIOA, GPIO_AF_7, GPIO_PIN_10);

    /* configure USART TX as alternate function push-pull */
    gpio_mode_set(GPIOA, GPIO_MODE_AF, GPIO_PUPD_PULLUP, GPIO_PIN_9);
    gpio_output_options_set(GPIOA, GPIO_OTYPE_PP, GPIO_OSPEED_10MHZ, GPIO_PIN_9);

    /* configure USART RX as alternate function push-pull */
    gpio_mode_set(GPIOA, GPIO_MODE_AF, GPIO_PUPD_PULLUP, GPIO_PIN_10);
    gpio_output_options_set(GPIOA, GPIO_OTYPE_PP, GPIO_OSPEED_10MHZ, GPIO_PIN_10);

    /* USART configure */
    usart_deinit(USART0);
    usart_baudrate_set(USART0, 115200U);
    usart_receive_config(USART0, USART_RECEIVE_ENABLE);
    usart_transmit_config(USART0, USART_TRANSMIT_ENABLE);
    usart_dma_receive_config(USART0, USART_DENR_ENABLE);
    //usart_dma_transmit_config(USART1, USART_DENT_ENABLE);
    usart_enable(USART0);	
}

2.接收DMA配置:

void uart0_dma_init(void)
{
    dma_parameter_struct dma_init_struct;
    /* enable DMA clock */
    rcu_periph_clock_enable(RCU_DMA);

    /* initialize DMA channel 1 */
    dma_deinit(DMA_CH1);
    dma_struct_para_init(&dma_init_struct);
    dma_init_struct.request      = DMA_REQUEST_USART0_RX;
    dma_init_struct.direction    = DMA_PERIPHERAL_TO_MEMORY;
    dma_init_struct.memory_addr  = (uint32_t)usart0_rec_buf;
    dma_init_struct.memory_inc   = DMA_MEMORY_INCREASE_ENABLE;
    dma_init_struct.memory_width = DMA_MEMORY_WIDTH_8BIT;
    dma_init_struct.number       = UART0_DMA_REC_LEN;
    dma_init_struct.periph_addr  = (uint32_t)&USART_RDATA(USART0);
    dma_init_struct.periph_inc   = DMA_PERIPH_INCREASE_DISABLE;
    dma_init_struct.periph_width = DMA_PERIPHERAL_WIDTH_8BIT;
    dma_init_struct.priority     = DMA_PRIORITY_ULTRA_HIGH;
    dma_init(DMA_CH1, &dma_init_struct);

    /* configure DMA mode */
    dma_circulation_disable(DMA_CH1);
    dma_memory_to_memory_disable(DMA_CH1);
    /* disable the DMAMUX_MUXCH1 synchronization mode */
    dmamux_synchronization_disable(DMAMUX_MUXCH1);

    /* enable DMA channel 1 */
    dma_channel_enable(DMA_CH1);
}

3.idle中断的相关配置:

void uart0_idle_init(void)
{
    /*wait IDLEF set and clear it*/
    while(RESET == usart_flag_get(USART0, USART_FLAG_IDLE)) {
    }
    usart_flag_clear(USART0, USART_FLAG_IDLE);
    usart_interrupt_enable(USART0, USART_INT_IDLE);	
}

4.usart0的中断处理函数实现:

void USART0_IRQHandler(void)
{
    if(RESET != usart_interrupt_flag_get(USART0, USART_INT_FLAG_IDLE)){
        usart_interrupt_flag_clear(USART0, USART_INT_FLAG_IDLE);

        /* number of data received */
        Usart0RecLen = UART0_DMA_REC_LEN - (dma_transfer_number_get(DMA_CH1));
        memcpy(usart0_rec_pro_buf,usart0_rec_buf,Usart0RecLen);
        usart0_rec_comp_flag = 1;

        /* disable DMA and reconfigure */
        dma_channel_disable(DMA_CH1);
        dma_transfer_number_config(DMA_CH1, UART0_DMA_REC_LEN);
        dma_channel_enable(DMA_CH1);
		}
}

 

编译,下载,调试:

串口助手发送1234:

以上测试达到了预期的效果!

源代码如下:

gd_finger.zip (606.14 KB, 下载次数: 81)

 

 

此帖出自GD32 MCU论坛
点赞 关注
 

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

随便看看
查找数据手册?

EEWorld Datasheet 技术支持

相关文章 更多>>
关闭
站长推荐上一条 1/8 下一条

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

About Us 关于我们 客户服务 联系方式 器件索引 网站地图 最新更新 手机版

站点相关: 国产芯 安防电子 汽车电子 手机便携 工业控制 家用电子 医疗电子 测试测量 网络通信 物联网

北京市海淀区中关村大街18号B座15层1530室 电话:(010)82350740 邮编:100190

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2025 EEWORLD.com.cn, Inc. All rights reserved
快速回复 返回顶部 返回列表