[GD32F350]第三弹:USART使用DMA+IDLE中断方式不定长字节数据收发
[复制链接]
本次实现的功能时配置gd32实现usart+dma实现串口收发数据,接收使用IDLE中断来实现接收不定长数据字节。 一、硬件简介 1、1 DMA简介(配图) 1、2 DMA操作简介(配图) 1、3 DMA通道配置(配图) 1、4 DMA请求映射及个通道请求表(配图) 1、5 DMA寄存器(配图) 每个通道有下边一组6个寄存器。 二、功能实现 2.1可以借鉴的例程(配图) 图中usart_printf例程实现了串口使用printf格式化输出,程序包含串口的基本初始化过程;05_USART_HyperTerminal_Interrupt实现了串口收发数据回环测试,使用了TBE和RBNE中断,程序包含串口的初始化过程、中断的使能过程已经中断服务函数的使用;06_USART_DMA实现了串口通过DMA方式发送和接收数据的数据回环测试,包含串口的初始化、DMA通道的配置过程、串口DMA方式发送数据和接收数据的配置过程。 2.2使用GD32官方库的功能实现 串口数据收发保存数据结构定义: - #define RX_LEN 300
- #define TX_LEN 300
- typedef struct
- {
- uint8_t RX_flag:1; //IDLE receive flag
- uint16_t RX_Size; //receive length
- uint8_t RX_pData[RX_LEN]; //DMA receive buffer
- }USART_RECEIVETYPE;
- typedef struct
- {
- uint8_t TX_flag:1; //IDLE tx flag
- uint16_t TX_Size; //tx length
- uint8_t TX_pData[RX_LEN]; //DMA tx buffer
- }USART_TRANSBYTE;
- USART_RECEIVETYPE Usart_ReceiveStruct;
- USART_TRANSBYTE Usart_TransStruct;
复制代码- USART_RECEIVETYPE Usart_ReceiveStruct;
- USART_TRANSBYTE Usart_TransStruct;
复制代码
USART串口DMA发送指定长度数据函数: - void UART_Transmit_DMA(uint8_t *pData, uint16_t Size)
- {
- /***************** DMA_TX_CONFIG ****************/
- dma_parameter_struct dma_init_struct;
- /* enable the DMA clock */
- rcu_periph_clock_enable(RCU_DMA);
- /* configure the USART TX DMA channel */
- dma_deinit(DMA_CH3);
- dma_init_struct.direction = DMA_MEMORY_TO_PERIPHERAL;
- dma_init_struct.memory_addr = (uint32_t)pData;
- dma_init_struct.memory_inc = DMA_MEMORY_INCREASE_ENABLE;
- dma_init_struct.memory_width = DMA_MEMORY_WIDTH_8BIT;
- dma_init_struct.number = Size;
- dma_init_struct.periph_addr = USART1_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_CH3, dma_init_struct);
- /* configure DMA mode */
- dma_circulation_disable(DMA_CH3);
- dma_memory_to_memory_disable(DMA_CH3);
- /***************** END DMA_TX_CONFIG ****************/
- /* enable the DMA channel1 and channel3 */
- dma_channel_enable(DMA_CH3);
- /* USART DMA enable for transmission */
- usart_dma_transmit_config(EVAL_COM1, USART_DENT_ENABLE); //USART配置DMA发送
- }
复制代码
USART串口DMA方式接收数据函数实现: - void UART_Receive_DMA(uint8_t *pData, uint16_t Size)
- {
- /***************** DMA_RX_CONFIG ****************/
- dma_parameter_struct dma_init_struct;
- /* enable the DMA clock */
- rcu_periph_clock_enable(RCU_DMA);
- /* configure the USART RX DMA channel */
- dma_deinit(DMA_CH4);
- dma_init_struct.direction = DMA_PERIPHERAL_TO_MEMORY;
- dma_init_struct.memory_addr = (uint32_t)pData;
- dma_init_struct.memory_inc = DMA_MEMORY_INCREASE_ENABLE;
- dma_init_struct.memory_width = DMA_MEMORY_WIDTH_8BIT;
- dma_init_struct.number = Size;
- dma_init_struct.periph_addr = USART1_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_CH4, dma_init_struct);
- /* configure DMA mode */
- dma_circulation_disable(DMA_CH4);
- dma_memory_to_memory_disable(DMA_CH4);
- /***************** END DMA_RX_CONFIG ****************/
- dma_channel_enable(DMA_CH4);
- usart_dma_receive_config(EVAL_COM1, USART_DENR_ENABLE); //USART配置DMA接收
- }
复制代码
串口中断服务函数实现:
- UsartReceive_IDLE(&Usart_ReceiveStruct);
- }
- void UsartReceive_IDLE(USART_RECEIVETYPE *Usart_ReceiveStruct)
- {
- if(usart_interrupt_flag_get(EVAL_COM1, USART_INT_FLAG_IDLE)) //检测到空闲线
- {
- usart_interrupt_flag_clear(EVAL_COM1, USART_INT_FLAG_IDLE);
- dma_channel_disable(DMA_CH4); //CHEN位为0时才能配置DMA
- Usart_ReceiveStruct->RX_Size = RX_LEN - dma_transfer_number_get(DMA_CH4);
- Usart_ReceiveStruct->RX_flag = 1;
- UART_Transmit_DMA(Usart_ReceiveStruct->RX_pData, Usart_ReceiveStruct->RX_Size);
- UART_Receive_DMA(Usart_ReceiveStruct->RX_pData, RX_LEN);
- }
- }
复制代码
功能,把串口dma接收到的数据保存后,获取接收到的数据长度,然后再原样发送出去。
结果见图: 图中为自定义10组数据,GD32接收后,返回上位机接收到的字符个数,带有时间戳。 图中为自定义10组数据,数据长度不一,接收到数据后原样通过串口再发送给上位机。
|