3364|2

155

帖子

1

TA的资源

一粒金砂(高级)

楼主
 

五、USART0的printf实现和DMA实现 [复制链接]

本帖最后由 sonicfirr 于 2022-2-9 21:09 编辑

在下的GD32L233C-START专题测评:

一、开箱评测 https://bbs.eeworld.com.cn/thread-1192788-1-1.html

二、GD32L233C-START环境搭建https://bbs.eeworld.com.cn/thread-1193053-1-1.html

三、点灯案例与扩展https://bbs.eeworld.com.cn/thread-1193183-1-1.html

四、Demo工程的分析https://bbs.eeworld.com.cn/thread-1193279-1-1.html


昨天晚上搞了一下Demo,后来睡着了,今晚来发一篇

1、备份一个工程

       本人在做教学工作时,习惯将一门课程的所有案例写在一个工程中,这样用着方便(也是给学生大爷们服务到位吧),这个习惯带到这里。

 

 

        另外,再次提到GD官网的下载链接:http://www.gd32mcu.com/cn/download/0?kw=GD32L2,这里提供的固件库里面包含所有接口的Demo。

 

 

2、案例代码

       1)先建立一个系统头文件,把其它头文件连接和测试函数声明放在这里。

#ifndef _AITA_SYS_H
#define _AITA_SYS_H

#include "gd32l23x.h"
#include "systick.h"
#include "gd32l233c_start.h"
#include <stdio.h>
#include <string.h>

extern uint8_t rx_buffer[256];
extern uint32_t nbr_data_to_read;
extern volatile uint32_t rx_counter;

#define AITA_EASYSHIELD_EN 1  //开启EasySheild扩展板,即增加多个LED的驱动

void aita_InitBSP(void);
void aita_InitLED(void);
void aita_InitUSART(void);
void aita_Flash(void);
void aita_RGB(void);
void aita_TestUSART(void);
void aita_InitDMAForU0(void);

#endif

       2)main.c的代码——这里分成几段来展示,从上到下是完整的。点灯的代码之前测评帖子中有,这里就不在写出了。

//by author. DMA测试的定义和printf重定向

#include "aita_sys.h"

//DMA USART0 发送和接收寄存器地址
#define USART0_RDATA_ADDRESS      (&USART_RDATA(USART0))
#define USART0_TDATA_ADDRESS      (&USART_TDATA(USART0))
#define ARRAYNUM(arr_nanme)       (uint32_t)(sizeof(arr_nanme) / sizeof(*(arr_nanme)))
//DMA USART0 测试用到的内存缓存
__IO FlagStatus g_transfer_complete = RESET;
uint8_t rxbuffer[10];
uint8_t txbuffer[] = "\n\rUSART DMA interrupt receive and transmit example, please input 10 bytes:\n\r";

/* retarget the C library printf function to the USART */
int fputc(int ch, FILE *f)
{
    usart_data_transmit(EVAL_COM, (uint8_t) ch);
    while(RESET == usart_flag_get(EVAL_COM, USART_FLAG_TBE));
    return ch;
}

 

//by author. main函数之前做的功能写成了三个测试函数,aita_TestUSART()是串口收发的测试(非DMA方式)
//现在启用的是DMA收发的过程

/*!
    \brief      main function
    \param[in]  none
    \param[out] none
    \retval     none
*/
int main(void) {
  aita_InitBSP();
//aita_Flash();
//aita_RGB();
//aita_TestUSART();
	/* waiting for the transfer to complete*/
    while(RESET == g_transfer_complete) {
    }

    g_transfer_complete = RESET;

    /* waiting for the transfer to complete*/
    while(RESET == g_transfer_complete) {
    }

    printf("\n\r%s\n\r", rxbuffer);
    while(1) {
    }
}

 

//by author. 初始化部分

void aita_InitBSP(void) {
  systick_config();
  aita_InitLED();
  aita_InitUSART();
  aita_InitDMAForU0();
}

 

//by author. GPIO控制LED初始化和串口初始化(目前开启DMA,所以注释了后两句)
//串口初始化代码gd_eval_com_init(),Demo中写在了gd32l233c_start.c

void aita_InitLED(void) {
  gd_eval_led_init(LED1);
  gd_eval_led_init(LED2);
  gd_eval_led_init(LED3);
  gd_eval_led_init(LED4);
#if AITA_EASYSHIELD_EN
  rcu_periph_clock_enable(RCU_GPIOB);
  gpio_mode_set(GPIOB, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, 
                GPIO_PIN_13 | GPIO_PIN_14 | GPIO_PIN_12 | GPIO_PIN_15 | GPIO_PIN_0);
  gpio_output_options_set(
                GPIOB, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, 
                GPIO_PIN_13 | GPIO_PIN_14 | GPIO_PIN_12 | GPIO_PIN_15 | GPIO_PIN_0);
  gpio_bit_reset(GPIOB, GPIO_PIN_13 | GPIO_PIN_14 | GPIO_PIN_12 | GPIO_PIN_15 | GPIO_PIN_0);
#endif
}

void aita_InitUSART(void) {
  /* configure EVAL_COM */
  gd_eval_com_init(EVAL_COM);
  /* USART interrupt configuration */
//nvic_irq_enable(USART0_IRQn, 0);
  /* enable EVAL_COM receive interrupt */
//usart_interrupt_enable(EVAL_COM, USART_INT_RBNE);
}

 

//by author. 从固件库Demo移植过来,Demo中使用了U1,这里改成板子上的U0
//另外,这里本人分析L233提供了一个DMA矩阵,包含7个通道,应该是外设可以映射到任意通道来使用
//原Demo U1口使用了DMA_CH0和DMA_CH1,我改成U0口也可以使用


void aita_InitDMAForU0(void) {
    dma_parameter_struct dma_init_struct;
    /* enable DMA clock */
    rcu_periph_clock_enable(RCU_DMA);
    /*configure DMA interrupt*/
    nvic_irq_enable(DMA_Channel0_IRQn, 0);
    nvic_irq_enable(DMA_Channel1_IRQn, 0);

    /* initialize DMA channel 0 */
    dma_deinit(DMA_CH0);
    dma_struct_para_init(&dma_init_struct);
    dma_init_struct.request      = DMA_REQUEST_USART0_TX;
    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  = (uint32_t)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_CH0, &dma_init_struct);

    /* configure DMA mode */
    dma_circulation_disable(DMA_CH0);
    dma_memory_to_memory_disable(DMA_CH0);
    /* disable the DMAMUX_MUXCH0 synchronization mode */
    dmamux_synchronization_disable(DMAMUX_MUXCH0);
    /* USART DMA enable for transmission and reception */
    usart_dma_transmit_config(USART0, USART_DENT_ENABLE);
    /* enable DMA channel 0 transfer complete interrupt */
    dma_interrupt_enable(DMA_CH0, DMA_INT_FTF);
    /* enable DMA channel 0 */
    dma_channel_enable(DMA_CH0);

    /* 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)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  = (uint32_t)USART0_RDATA_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);

    /* 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);
    /* USART DMA enable for reception */
    usart_dma_receive_config(USART0, USART_DENR_ENABLE);
    /* enable DMA channel 1 transfer complete interrupt */
    dma_interrupt_enable(DMA_CH1, DMA_INT_FTF);
    /* enable DMA channel 1 */
    dma_channel_enable(DMA_CH1);
}

 

//by author. 非DMA方式的U0收发测试,开启了接收中断

void aita_TestUSART(void) {
  uint16_t i=0;
  while(1) {
    if(rx_counter > 0) {
      printf("get msg: \r\n%s\r\n", rx_buffer);
      rx_counter = 0;
      memset(rx_buffer, 0, 256);
    }
    if(i++ >= 500) {
      i = 0;
      printf("Hello from GD32L233C-START!\r\n");
    }
    delay_1ms(10);
  }
}

       3)中断函数——gd32l23x_it.c

//by author. 以下是文件修改和新增部分
//原U0接收中断,是接收固定数量字节,然后就关闭接收中断(注释掉部分)
//DMA中断暂时从固件库案例粘贴过来,没有做修改,测试功能也是案例中的发送一句话,并接收10个字节


#define BUFFER_SIZE 256
uint8_t rx_buffer[BUFFER_SIZE];
uint32_t nbr_data_to_read = BUFFER_SIZE;
volatile uint32_t rx_counter = 0;
/*!
    \brief      this function handles USART0 exception
    \param[in]  none
    \param[out] none
    \retval     none
*/
void USART0_IRQHandler(void)
{
    if(RESET != usart_interrupt_flag_get(USART0, USART_INT_FLAG_RBNE)) {
        /* read one byte from the receive data register */
        rx_buffer[rx_counter++] = (uint8_t)usart_data_receive(USART0);

//        if(rx_counter >= nbr_data_to_read) {
//            /* disable the USART0 receive interrupt */
//            usart_interrupt_disable(USART0, USART_INT_RBNE);
//        }
    }
}

extern FlagStatus g_transfer_complete;
/*!
    \brief      this function handles DMA_Channel0_IRQHandler interrupt
    \param[in]  none
    \param[out] none
    \retval     none
*/
void DMA_Channel0_IRQHandler(void)
{
    if(RESET != dma_interrupt_flag_get(DMA_CH0, DMA_INT_FLAG_FTF)){
        dma_interrupt_flag_clear(DMA_CH0, DMA_INT_FLAG_G);
        g_transfer_complete = SET;
    }
}

/*!
    \brief      this function handles DMA_Channel1_IRQHandler interrupt
    \param[in]  none
    \param[out] none
    \retval     none
*/
void DMA_Channel1_IRQHandler(void)
{
    if(RESET != dma_interrupt_flag_get(DMA_CH1, DMA_INT_FLAG_FTF)){
        dma_interrupt_flag_clear(DMA_CH1, DMA_INT_FLAG_G);
        g_transfer_complete = SET;
    }
}

 

3、测试效果

 

 

       有需要的朋友可以下载我的案例,放在“..\GD32L233C-START\GD32L233C_START_Demo_Suites\Projects”。

       

AITA_GD32L233C.zip

407.58 KB, 下载次数: 14

Demo

此帖出自GD32 MCU论坛

最新回复

ACK
看了资料,感觉很好,正好是我所需要的,程序测试没问题,不过还可以优化一下程序,那就更好了。程序实际移植到了单片机中,基本没什么问题,总体感觉还不错吧,值得学习交流。   详情 回复 发表于 2022-2-9 22:48
点赞 关注
 

回复
举报

12

帖子

1

TA的资源

一粒金砂(中级)

沙发
 

看了资料,感觉很好,正好是我所需要的,程序测试没问题,不过还可以优化一下程序,那就更好了。程序实际移植到了单片机中,基本没什么问题,总体感觉还不错吧,值得学习交流。

此帖出自GD32 MCU论坛

点评

嗯,咱们想到一起了,等空闲下来做一版更好的案例,计划实现DMA控制AT WiFi的。  详情 回复 发表于 2022-2-11 11:56
 
 
 

回复

155

帖子

1

TA的资源

一粒金砂(高级)

板凳
 
ACK 发表于 2022-2-9 22:48 看了资料,感觉很好,正好是我所需要的,程序测试没问题,不过还可以优化一下程序,那就更好了。程序实际移 ...

嗯,咱们想到一起了,等空闲下来做一版更好的案例,计划实现DMA控制AT WiFi的。

此帖出自GD32 MCU论坛
 
 
 

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

随便看看
查找数据手册?

EEWorld Datasheet 技术支持

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

 
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
快速回复 返回顶部 返回列表