首页 > 其他分享 >GD32F470II的UART+DMA方式的使用笔记

GD32F470II的UART+DMA方式的使用笔记

时间:2024-04-10 16:12:18浏览次数:14  
标签:DMA struct usart dma UART init DMA1 GD32F470II

GD32官方给的DEMO真的是屎一样的存在,仅展示最基本简单的应用案例,拿到实际工程中参考性非常低,也就基本的配置过程具有有限的参考性。

在这种环境下,使用UART+DMA的方式完全是瞎用,感觉能用的函数都给用上。

UART & DMA配置如下:

 1 /*!
 2     \brief      configure USART DMA
 3     \param[in]  none
 4     \param[out] none
 5     \retval     none
 6 */
 7 void usart_dma_config(void)
 8 {
 9     dma_single_data_parameter_struct dma_init_struct;
10     /* enable DMA1 */
11     rcu_periph_clock_enable(RCU_DMA1);
12     /* deinitialize DMA channel7(USART0 TX) */
13     dma_deinit(DMA1, DMA_CH7);
14     dma_init_struct.direction = DMA_MEMORY_TO_PERIPH;
15     dma_init_struct.memory0_addr = (uint32_t)Uart0_tx_buffer;
16     dma_init_struct.memory_inc = DMA_MEMORY_INCREASE_ENABLE;
17     dma_init_struct.number = HITPAD_DATA_SEND_NUM;//9/42
18     dma_init_struct.periph_addr = USART0_DATA_ADDRESS;
19     dma_init_struct.periph_inc = DMA_PERIPH_INCREASE_DISABLE;
20     dma_init_struct.periph_memory_width = DMA_PERIPH_WIDTH_8BIT;
21     dma_init_struct.priority = DMA_PRIORITY_ULTRA_HIGH;
22     dma_single_data_mode_init(DMA1, DMA_CH7, &dma_init_struct);
23     dma_channel_subperipheral_select(DMA1, DMA_CH7, DMA_SUBPERI4);
24     /* configure DMA mode */
25     dma_circulation_disable(DMA1, DMA_CH7);
26 
27     dma_interrupt_enable(DMA1, DMA_CH7, DMA_CHXCTL_FTFIE);
28     
29     /* deinitialize DMA channel2(USART0 RX) */
30     dma_deinit(DMA1, DMA_CH5);
31     dma_init_struct.direction = DMA_PERIPH_TO_MEMORY;
32     dma_init_struct.memory0_addr = (uint32_t)Uart0_rx_buffer;
33     dma_single_data_mode_init(DMA1, DMA_CH5, &dma_init_struct);
34     dma_channel_subperipheral_select(DMA1, DMA_CH5, DMA_SUBPERI4);
35     /* configure DMA mode */
36     dma_circulation_disable(DMA1, DMA_CH5);
37 }
38 
39 void Uart0Tx_init_DMA(UINT32 * Addr, UINT32 number)
40 {
41     dma_single_data_parameter_struct dma_init_struct;
42     
43     dma_init_struct.direction = DMA_MEMORY_TO_PERIPH;
44     dma_init_struct.memory0_addr = (uint32_t)Addr;
45     dma_init_struct.memory_inc = DMA_MEMORY_INCREASE_ENABLE;
46     dma_init_struct.number = (uint32_t)number;
47     dma_init_struct.periph_addr = USART0_DATA_ADDRESS;
48     dma_init_struct.periph_inc = DMA_PERIPH_INCREASE_DISABLE;
49     dma_init_struct.periph_memory_width = DMA_PERIPH_WIDTH_8BIT;
50     dma_init_struct.priority = DMA_PRIORITY_ULTRA_HIGH;
51     dma_single_data_mode_init(DMA1, DMA_CH7, &dma_init_struct);
52     dma_channel_subperipheral_select(DMA1, DMA_CH7, DMA_SUBPERI4);
53     /* configure DMA mode */
54     dma_circulation_disable(DMA1, DMA_CH7);
55 }
56 
57 void Usart_init()    //
58 {//c12-tx/d2-rx
59 
60     uint32_t com = USART0;
61         
62     rcu_periph_clock_enable(RCU_GPIOA);
63     rcu_periph_clock_enable(RCU_USART0);
64 
65     UINT32 gpio = GPIO_PIN_9 | GPIO_PIN_10;
66 
67     gpio_mode_set(GPIOA, GPIO_MODE_AF, GPIO_PUPD_PULLUP, gpio);        
68     gpio_output_options_set(GPIOA, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, gpio);
69     gpio_af_set(GPIOA, GPIO_AF_7, gpio);
70 
71     /* USART interrupt configuration */
72     nvic_irq_enable(USART0_IRQn, USART0_IRQ_LEVEL, 0);
73 
74     usart_deinit(com);
75     usart_baudrate_set(com,UART0_BAUDRATE);
76     usart_receive_config(com, USART_RECEIVE_ENABLE);
77     usart_transmit_config(com, USART_TRANSMIT_ENABLE);
78     usart_enable(com);
79 
80     /*enable transmission complete interrupt*/
81     usart_interrupt_enable(com, USART_INT_TC);
82     usart_flag_clear(com,USART_FLAG_TC);
83 
84     usart_dma_config();
85 
86     /* enable USART0 DMA channel transmission and reception */
87     /*TX*/
88     dma_channel_enable(DMA1, DMA_CH7);
89     /*RX*/
90     dma_channel_enable(DMA1, DMA_CH5);
91     
92     /* USART DMA enable for transmission and reception */
93     usart_dma_transmit_config(com, USART_DENT_DISABLE);
94     usart_dma_receive_config(com, USART_DENR_DISABLE);
95 
96     HAL_UART0_Config();
97 
98 }

这里仅用到了串口发送,接收没用,因此发送函数如下:

 1 void Usart0DataSend(UINT8* data, UINT32 len)
 2 {
 3     if(Uart0_Tx_Flag)
 4     {
 5         Uart0_Tx_Flag = FALSE;
 6 
 7         dma_channel_enable(DMA1, DMA_CH7);
 8         
 9         usart_dma_transmit_config(USART0, USART_DENT_ENABLE);
10     }
11 
12 }

上层应用:

 1 void Uart0TransmitFunc(void)
 2 {
 3     if(Uart0_Tx_Flag) 
 4     {
 5         while(GCommon_BufNotEmptyCheck((WR_RD_BUF *)g_HAL_UART_TxBuf))
 6         {
 7             for(UINT32 i=0; i<HITPAD_DATA_SEND_NUM; i++)
 8             {
 9                 Uart0_tx_buffer[i] = GCommon_RdDataFromBuf((WR_RD_BUF *)g_HAL_UART_TxBuf);
10             }
11             
12             Usart0DataSend(Uart0_tx_buffer, HITPAD_DATA_SEND_NUM);
13 
14             break;
15         }
16     }
17 }

串口中断:

 1 void USART0_IRQHandler(void)
 2 {
 3 
 4     if(usart_flag_get(USART0,USART_FLAG_TC)!= RESET)
 5     {
 6         usart_flag_clear(USART0,USART_FLAG_TC);//中断标记清除
 7 
 8         Uart0_Tx_Flag = TRUE;
 9 
10 //        /*disable TX*/
11         usart_dma_transmit_config(USART0, USART_DENT_DISABLE);
12         dma_channel_disable(DMA1, DMA_CH7);         
13         dma_flag_clear(DMA1, DMA_CH7,DMA_INTF_FTFIF);
14     }
15 
16 }

原理也很简单。

DMA配置成DMA_MEMORY_TO_PERIPH,串口发送的时候开启下相应的通道开关,DMA会自动搬运配置好的数据量到串口的发送缓冲,串口全部发送完成后触发中断。中断里再做下相应的FLAG清除工作即可。

坑就坑在上面在开启发送和中断里清理工作上有不需要干的事情。

 

  • 在重新给专用于显示的GD32F470II的其中一个串口增加DMA功能的时候,发现串口运行一段时间后就停止工作了,简单查看DMA + UART寄存器也看不出来哪里有问题。
  • 通过测试发现停止传输的时候执行一下这段话就又正常了
dma_flag_clear(DMA1, DMA_CH7,DMA_INTF_FTFIF);

 不知道为什么,然后查看手册

 这就是原因了。在一次开启DMA传输后,此次DMA传输发生了FIFO错误/总线错误/寄存器访问错误,导致传输停止,串口未进中断清理DMA的FTFIFx标志,DMA就无法继续使用了

正确的(应该说更精炼)使用配置如下:

 1 1、串口初始化里串口DMA开关要直接打开
 2   usart_dma_transmit_config(com, USART_DENT_ENABLE);
3 2、发送接口里只需要使能DMA通道即可 4 void Usart0DataSend(UINT8* data, UINT32 len) 5 { 6 if(Uart0_Tx_Flag) 7 { 8 Uart0_Tx_Flag = FALSE; 9 dma_flag_clear(DMA1, DMA_CH7,DMA_INTF_FTFIF); 10 dma_channel_enable(DMA1, DMA_CH7); 11 } 13 } 14 3、串口中断里仅需清理下DMA通道的发送完成标志 15 void USART0_IRQHandler(void) 16 { 17 if(usart_flag_get(USART0,USART_FLAG_TC)!= RESET) 18 { 19 usart_flag_clear(USART0,USART_FLAG_TC);//中断标记清除 20 21 Uart0_Tx_Flag = TRUE; 24 } 27 }

 

这里解释下为什么这样改可以

用户手册里DMA 的DMA_CHxCTL寄存器0bit CHEN这样介绍

 所以,不需要手动禁止DMA通道,在其传输完成的时候会自动清0,实际仿真查看也的确如此。

串口的DMA发送开关也没必要来回开关,仅控制DMA就够了。

 

标签:DMA,struct,usart,dma,UART,init,DMA1,GD32F470II
From: https://www.cnblogs.com/xjxcxjx/p/18126244

相关文章

  • 3dmax渲染十几个小时怎么办?3dmax怎么多机渲染
    当使用3dsMax进行渲染作业时,如果发现单张图像的渲染时间长达十数小时,这可能是由于计算机硬件配置较低或渲染场景过于复杂所致。为了缩短渲染时间并提高效率,我们可以考虑采用多台计算机进行协同渲染。下面,让我们一起探讨如何通过这种方式优化渲染流程。3dmax渲染十几个小时正常......
  • 使用SPI+DMA控制算法驱动WS2812
    1、ws2812b是一款集控制电路与发光电路于一体的智能外控LED光源,采用单线归0码协议,每个像素点的三基色颜色可实现256级亮度显示。速率能达到1024pixel×30fps/s,故被广泛用于各种需要大量使用RGB灯的场合。2、不同厂商生产的ws2812存在不同的时序要求,下图是一款最常见的ws2812b......
  • 基于FPGA的数据采集、编码、通讯和存储系统设计(即FPGA+RTL8211千兆以太网+SD卡存储+RT
    介绍一个小项目,加强对FPGA相关接口的整体把握。硬件及软件代码梳理:硬件系统的主要功能框图,其中FPGA作为处理单元,实现了包括电流和电压的采集、千兆以太网通讯、SD卡本地数据存储和串口通讯等。已经过板级测试,测试包含:千兆网通讯收发测试、AD采集的数据验证、SD卡存储验证......
  • DMA第四版代码
    描述:我发现并不是所有的任务都有同步信号,这一期版本使用参数来控制是否需要同步信号;Test_Flow_Mode参数为高的时候意味着需要同步,否则不需要,仅检测数据流。不需要同步的情况如果丢包会出现严重后果。参考这篇笔记:https://www.cnblogs.com/VerweileDoch/p/18111545代码:`tim......
  • STM32CubeMX+MDK通过I2S接口进行音频输入输出(全双工读写一个DMA回调)
    一、前言目前有一个关于通过STM32F411CEUx的I2S总线接口控制SSS1700芯片进行音频输入输出的研究。SSS1700是具有片上振荡器的3S高度集成的USB音频控制器芯片。SSS1700功能支持96KHz24位采样率,带外部音频编解码器(24位/96KHzI2S输入和输出)并具有内置立体声16/24......
  • Java Tomcat7中使用Quartz2.2实现定时任务项目代码实例(demo)
    ​ 在Java中使用Quartz2.2结合Tomcat7实现定时任务是一种常见的需求,Quartz是一个强大的定时任务库,能够帮助开发者轻松实现复杂的定时任务调度。以下是一个简单的示例,展示如何在JavaWeb应用中集成Quartz来执行定时任务。 详细文档:JavaTomcat7中使用Quartz2.2实现定时任务......
  • RK3568平台 Uart驱动框架
    一.TTY子系统在Linuxkernel中,tty驱动不像于spi,iic等那么架构简单,它是一个庞大的系统,它的框架大体如下图一。我们作为普通的驱动开发移植人员,不会从零写tty驱动,一般都是厂家根据现有的tty驱动和自家芯片修改,拿到板子按照厂家的配置,串口应该使能直接使用的。但是开发的过程中也......
  • 如何读懂串口通讯波形图(TTL,RS232,UART)
    考考你,这是什么字符串,提示串口通讯,8N1 ......
  • pdmaner-代码生成器的使用
    一、什么是pdmanerPDManer是一款开源免费的数据库模型建模工具,它以其用户友好的界面和简单的操作流程而受到用户的欢迎。以下是一些关于PDManer的特点:多平台支持:支持Windows、Mac和Linux等多种操作系统,甚至包括国产操作系统。高颜值界面:界面设计简洁美观,使得用户上手更为容易......
  • UART协议介绍
    日期版本内容修改2024/04/03V0初版UART协议即UniversalAsynchronousReceiver/Transmitter,是一种串行、异步、全双工通信协议。UART也常常被称作串口。1.信号名称txd:UART发送数据线rxd:UART接收数据线1.1.传输格式UART的传输格式如下图所示(图源[1],有修......