打印

GD32E230F6p6的串口DMA中断收发及printf

[复制链接]
1857|14
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
简介
通过DMA中断的方式实现USART0串口数据收发可以尽量少的占用mcu,提高系统的实时性,同时,printf也可以用DMA方式实现!

一、初始化配置
选择DMA通道
根据GD32的用户手册确定使用DMA-CH1发送USART0-TX数据,DMA-CH2接收USART-RT数据,如下图:、、




使用特权

评论回复
沙发
我爱台妹mmd|  楼主 | 2023-9-30 19:16 | 只看该作者
头文件
#define ARRAYNUM(arr_nanme)      (uint32_t)(sizeof(arr_nanme) / sizeof(*(arr_nanme)))
#define USART0_TDATA_ADDRESS      ((uint32_t)0x40013828)  
#define USART0_RDATA_ADDRESS      ((uint32_t)0x40013824)


/* 串口IO初始化 */
void com_gpio_init(void);
/* 串口初始化 */
void com_usart_init(void);
/* 串口DMA初始化 */
void com_dma_init(void);

/* 串口DMA发送 */
void com_dma_send_data(uint8_t *buffter, uint8_t length);

/* 串口DMA方式printf */
void dma_printf(const char *format,...);

使用特权

评论回复
板凳
我爱台妹mmd|  楼主 | 2023-9-30 19:16 | 只看该作者
串口&DMA初始化
//串口发送buffer
uint8_t txbuffer[128] = {0};
//串口接收buffer
uint8_t rxbuffer[4] = {0};

extern uint8_t com_recv_STA;//串口DMA接收状态                1=数据接收完成
extern uint8_t        com_recv_num;//串口接收字节数               

/* 串口IO初始化 */
void com_gpio_init(void)
{
   
    rcu_periph_clock_enable(RCU_GPIOA);
    gpio_af_set(GPIOA, GPIO_AF_1, GPIO_PIN_9);
        gpio_af_set(GPIOA, GPIO_AF_1, GPIO_PIN_10);
   
    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);
   
    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);
}

/* 串口初始化 */
void com_usart_init(void)
{
    /* enable USART clock */
    rcu_periph_clock_enable(RCU_USART0);

    /* 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_enable(USART0);
}

void com_nvic_config(void)
{
        nvic_irq_enable(DMA_Channel1_2_IRQn, 0);
}

/* 串口DMA初始化 */
void com_dma_init(void)
{
        dma_parameter_struct dma_init_struct;
    /* enable DMA clock */
    rcu_periph_clock_enable(RCU_DMA);

    /* initilize the com */
    com_gpio_init();
    com_usart_init();
        com_nvic_config();
       
       
/* initialize DMA channel1 */
    dma_deinit(DMA_CH1);
    dma_struct_para_init(&dma_init_struct);
    dma_init_struct.direction = DMA_MEMORY_TO_PERIPHERAL;
    dma_init_struct.memory_addr = (uint32_t)txbuffer;
    dma_init_struct.memory_inc = DMA_MEMORY_INCREASE_ENABLE;
    dma_init_struct.memory_width = DMA_MEMORY_WIDTH_8BIT;
    dma_init_struct.number = ARRAYNUM(txbuffer);
    dma_init_struct.periph_addr = USART0_TDATA_ADDRESS;
    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);
    /* initialize DMA channel2 */
    dma_deinit(DMA_CH2);
    dma_init_struct.direction = DMA_PERIPHERAL_TO_MEMORY;
    dma_init_struct.memory_addr = (uint32_t)rxbuffer;
    dma_init_struct.memory_inc = DMA_MEMORY_INCREASE_ENABLE;
    dma_init_struct.memory_width = DMA_MEMORY_WIDTH_8BIT;
    dma_init_struct.number = ARRAYNUM(rxbuffer);
    dma_init_struct.periph_addr = USART0_RDATA_ADDRESS;
    dma_init_struct.periph_inc = DMA_PERIPH_INCREASE_DISABLE;
    dma_init_struct.memory_width = DMA_PERIPHERAL_WIDTH_8BIT;
    dma_init_struct.priority = DMA_PRIORITY_ULTRA_HIGH;
    dma_init(DMA_CH2, &dma_init_struct);
    /* configure DMA mode */
    dma_circulation_disable(DMA_CH1);
    dma_memory_to_memory_disable(DMA_CH1);
    dma_circulation_disable(DMA_CH2);
    dma_memory_to_memory_disable(DMA_CH2);
    /* USART DMA enable for reception */
    usart_dma_receive_config(USART0, USART_DENR_ENABLE);
    /* enable DMA channel2 transfer complete interrupt */
    dma_interrupt_enable(DMA_CH2, DMA_INT_FTF);
    /* enable DMA channel2 */
    dma_channel_enable(DMA_CH2);
    /* USART DMA enable for transmission */
    usart_dma_transmit_config(USART0, USART_DENT_ENABLE);
    /* enable DMA channel1 transfer complete interrupt */
    dma_interrupt_enable(DMA_CH1, DMA_INT_FTF);
    /* enable DMA channel1 */
    dma_channel_enable(DMA_CH1);
}

使用特权

评论回复
地板
我爱台妹mmd|  楼主 | 2023-9-30 19:17 | 只看该作者
串口DMA收发及printf
DMA发送
void com_dma_send_data(uint8_t *buffter, uint8_t length)
{                //串口DMA发送函数
        uint8_t i;//txbuffer[128];
        dma_parameter_struct dma_init_struct;
        for (i = 0; i < length; i ++)
        {
                txbuffer[i] = buffter[i];
        }
        dma_channel_disable(DMA_CH1);
        dma_memory_address_config(DMA_CH1, (uint32_t)txbuffer);

        dma_transfer_number_config(DMA_CH1, (uint32_t)length);
        /* enable DMA channel1 */
        dma_channel_enable(DMA_CH1);
        /* USART DMA enable for transmission */
        usart_dma_transmit_config(USART0, USART_DENT_ENABLE);
}

使用特权

评论回复
5
我爱台妹mmd|  楼主 | 2023-9-30 19:17 | 只看该作者
DMA收发中断处理
void DMA_Channel1_2_IRQHandler(void)//DMA串口发送接收中断
{
    if(RESET != dma_interrupt_flag_get(DMA_CH1, DMA_INT_FLAG_FTF))
        {//DMA串口发送触发中断
        dma_interrupt_flag_clear(DMA_CH1, DMA_INT_FLAG_G);
    }
    if(RESET != dma_interrupt_flag_get(DMA_CH2, DMA_INT_FLAG_FTF))
        {//DMA串口接收触发中断
                dma_channel_disable(DMA_CH2);
        dma_interrupt_flag_clear(DMA_CH2, DMA_INT_FLAG_G);
                dma_flag_clear(DMA_CH2, DMA_FLAG_G);
                com_recv_num = 4;//获取字节数
                com_recv_STA = 1;//接收数据就绪
                dma_transfer_number_config(DMA_CH2,ARRAYNUM(rxbuffer));
                dma_channel_enable(DMA_CH2);
               
    }
}

使用特权

评论回复
6
我爱台妹mmd|  楼主 | 2023-9-30 19:17 | 只看该作者
DMA方式printf

/* DMA方式printf */
void dma_printf(const char *format,...)
{
        uint32_t length;
        va_list args;

        va_start(args, format);
        length = vsnprintf((char*)txbuffer, sizeof(txbuffer), (char*)format, args);
        va_end(args);
        com_dma_send_data(txbuffer,length);

}

使用特权

评论回复
7
我爱台妹mmd|  楼主 | 2023-9-30 19:17 | 只看该作者
实际效果
这里我发送FANR读取转速的命令给mcu,mcu通过串口DMA方式printf当前值(这里我直接将转速检测的IO接的3.3V,实际最高1.1W转,而不是75W)。测试完成,串口DMA中断收发正常,自定义的prinf也可以使用。

使用特权

评论回复
8
我爱台妹mmd|  楼主 | 2023-9-30 19:17 | 只看该作者

使用特权

评论回复
9
uiint| | 2023-10-5 21:30 | 只看该作者
在USART的DMA中断收发及printf的实现中,首先要定义串口接收和发送变量,然后初始化USART1,设置波特率、数据位、停止位、奇偶校验等参数,并使能DMA传输和接收。在主函数中,可以使用printf函数发送数据,然后通过DMA中断接收数据。

使用特权

评论回复
10
hudi008| | 2023-10-5 22:16 | 只看该作者
串口 DMA 中断收发是指通过 DMA 控制器实现串口数据的收发,从而减轻 CPU 的负担。在接收数据时,DMA 控制器会从串口接收数据,并将数据存储到指定的缓冲区。在发送数据时,DMA 控制器会从指定的缓冲区取出数据,并将数据发送到串口。

使用特权

评论回复
11
chenci2013| | 2023-10-8 21:09 | 只看该作者
串口DMA中断收发可以提高系统的数据传输效率和可靠性,降低CPU的负载。

使用特权

评论回复
12
averyleigh| | 2023-10-8 22:58 | 只看该作者
在使用 printf 进行串口输出时,也可以通过 DMA 实现更高效的数据传输。

使用特权

评论回复
13
jkl21| | 2023-10-10 21:15 | 只看该作者
可以使用DMA(直接内存访问)和USART(通用同步和异步接收发送器)来实现串口的中断收发。同时,也可以使用printf函数来进行数据的打印。

使用特权

评论回复
14
pl202| | 2023-10-11 21:47 | 只看该作者
使用 DMA 技术进行中断收发和 printf 输出,可以提高串口通信的效率和性能。

使用特权

评论回复
15
Heelo| | 2023-11-10 12:38 | 只看该作者

使用特权

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

本版积分规则

55

主题

517

帖子

0

粉丝