GD32E103CBT8-空闲中断DMA接收
1)完成GD32E103CBT8的usart0和usart1的串口空闲中断+DMA接收,并验证
代码如下:
#include "gd32e10x.h"
#include <string.h>
#include "systick.h"// 定义接收缓冲区大小
#define RX_BUFFER_SIZE 128// 接收缓冲区和相关标志
uint8_t rx_buffer[RX_BUFFER_SIZE];
uint8_t rx_data_length = 0;
uint8_t rx_complete_flag = 0;// 初始化GPIO
void gpio_config(void)
{// 使能GPIOA时钟rcu_periph_clock_enable(RCU_GPIOA);// 配置PA2为USART1_TX (复用推挽输出)gpio_init(GPIOA, GPIO_MODE_AF_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_2);// 配置PA3为USART1_RX (浮空输入)gpio_init(GPIOA, GPIO_MODE_IN_FLOATING, GPIO_OSPEED_50MHZ, GPIO_PIN_3);
}// 初始化USART1
void usart_config(void)
{// 使能USART1时钟rcu_periph_clock_enable(RCU_USART1);// 配置USART1: 115200 8N1usart_deinit(USART1);usart_baudrate_set(USART1, 115200U);usart_word_length_set(USART1, USART_WL_8BIT);usart_stop_bit_set(USART1, USART_STB_1BIT);usart_parity_config(USART1, USART_PM_NONE);usart_hardware_flow_cts_config(USART1, USART_CTS_DISABLE);usart_hardware_flow_rts_config(USART1, USART_RTS_DISABLE);usart_receive_config(USART1, USART_RECEIVE_ENABLE);usart_transmit_config(USART1, USART_TRANSMIT_ENABLE);// 使能USART1空闲中断usart_interrupt_enable(USART1, USART_INT_IDLE);// 使能USART1usart_enable(USART1);
}// 初始化DMA用于USART1接收
void dma_config(void)
{// 使能DMA0时钟rcu_periph_clock_enable(RCU_DMA0);// 配置DMA0通道5 (USART1_RX)dma_deinit(DMA0, DMA_CH5);dma_parameter_struct dma_init_struct;dma_struct_para_init(&dma_init_struct);dma_init_struct.direction = DMA_PERIPHERAL_TO_MEMORY; // 外设到内存dma_init_struct.memory_addr = (uint32_t)rx_buffer; // 内存地址dma_init_struct.memory_inc = DMA_MEMORY_INCREASE_ENABLE;// 内存地址自增dma_init_struct.memory_width = DMA_MEMORY_WIDTH_8BIT; // 内存数据宽度8位dma_init_struct.number = RX_BUFFER_SIZE; // 传输数量dma_init_struct.periph_addr = (uint32_t)&USART_DATA(USART1); // 外设地址(USART1数据寄存器)dma_init_struct.periph_inc = DMA_PERIPH_INCREASE_DISABLE;// 外设地址不自增dma_init_struct.periph_width = DMA_PERIPHERAL_WIDTH_8BIT;// 外设数据宽度8位dma_init_struct.priority = DMA_PRIORITY_MEDIUM; // 中等优先级dma_init(DMA0, DMA_CH5, &dma_init_struct);// 使能DMA0通道5dma_channel_enable(DMA0, DMA_CH5);// 使能USART1 DMA接收usart_dma_receive_config(USART1, USART_DENR_ENABLE);
}// 初始化NVIC中断
void nvic_config(void)
{nvic_irq_enable(USART1_IRQn, 0, 0); // USART1中断,优先级0
}// 初始化USART1及DMA
void usart1_dma_init(void)
{gpio_config();usart_config();dma_config();nvic_config();
}// 定义USART0接收缓冲区大小
#define USART0_RX_BUFFER_SIZE 256// USART0接收缓冲区和长度变量
uint8_t usart0_rx_buffer[USART0_RX_BUFFER_SIZE];
uint16_t usart0_rx_len = 0;
uint8_t usart0_rx_complete = 0; // 接收完成标志
// GPIO配置
void uart0_gpio_config(void)
{rcu_periph_clock_enable(RCU_GPIOA); rcu_periph_clock_enable(RCU_USART0);gpio_init(GPIOA, GPIO_MODE_AF_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_9); // 将PA9初始化为:复用推挽输出、IO速率最高50MHzgpio_init(GPIOA, GPIO_MODE_IN_FLOATING, GPIO_OSPEED_50MHZ, GPIO_PIN_10); // 将PA10初始化为:浮空输入、IO速率最高50MHz
}
// USART配置
void uart0_usart_config(void)
{// 配置USART0参数usart_deinit(USART0);usart_baudrate_set(USART0, 115200U); // 波特率115200usart_word_length_set(USART0, USART_WL_8BIT); // 8位数据位usart_stop_bit_set(USART0, USART_STB_1BIT); // 1位停止位usart_parity_config(USART0, USART_PM_NONE); // 无奇偶校验usart_hardware_flow_rts_config(USART0, USART_RTS_DISABLE); // 串口0 配置为 不使能RTSusart_hardware_flow_cts_config(USART0, USART_CTS_DISABLE); // 串口0 配置为 不使能CTS usart_receive_config(USART0, USART_RECEIVE_ENABLE); // 使能接收usart_transmit_config(USART0, USART_TRANSMIT_ENABLE); // 使能发送// 使能USART0空闲中断usart_interrupt_enable(USART0, USART_INT_IDLE);// 使能USART0usart_enable(USART0);
}// DMA配置
void uart0_dma_config(void)
{rcu_periph_clock_enable(RCU_DMA0); //使能DMA0时钟dma_deinit(DMA0, DMA_CH4); //复位DMA0通道4// 配置DMA0通道4dma_parameter_struct dma_init_struct;dma_struct_para_init(&dma_init_struct);dma_init_struct.direction = DMA_PERIPHERAL_TO_MEMORY; // 外设到内存dma_init_struct.memory_addr = (uint32_t)usart0_rx_buffer; // 内存地址dma_init_struct.memory_inc = DMA_MEMORY_INCREASE_ENABLE; // 内存地址自增dma_init_struct.memory_width = DMA_MEMORY_WIDTH_8BIT; // 内存数据宽度8位dma_init_struct.number = USART0_RX_BUFFER_SIZE; // 传输数据量dma_init_struct.periph_addr = (uint32_t)&USART_DATA(USART0); // 外设地址(USART0数据寄存器)dma_init_struct.periph_inc = DMA_PERIPH_INCREASE_DISABLE; // 外设地址不自增dma_init_struct.periph_width = DMA_PERIPHERAL_WIDTH_8BIT; // 外设数据宽度8位dma_init_struct.priority = DMA_PRIORITY_MEDIUM; // 中等优先级dma_init(DMA0, DMA_CH4, &dma_init_struct);// 使能DMA0通道4传输完成中断dma_interrupt_enable(DMA0, DMA_CH4, DMA_INT_FTF);// 使能DMA0通道4dma_channel_enable(DMA0, DMA_CH4);// 关联USART0_RX到DMA0通道4usart_dma_receive_config(USART0, USART_DENR_ENABLE);
}// 发送数据函数
void usart0_send_data(uint8_t *data, uint16_t len)
{for(uint16_t i = 0; i < len; i++){// 等待发送缓冲区为空while(usart_flag_get(USART0, USART_FLAG_TBE) == RESET);usart_data_transmit(USART0, data[i]);}// 等待发送完成while(usart_flag_get(USART0, USART_FLAG_TC) == RESET);
}// 初始化NVIC中断
void uart0_nvic_config(void)
{// 配置USART0中断nvic_irq_enable(USART0_IRQn, 1, 0); // USART0中断,优先级0// 配置DMA0通道4中断nvic_irq_enable(DMA0_Channel4_IRQn, 2, 0);
}// 初始化USART0及DMA
void usart0_dma_init(void)
{uart0_gpio_config();uart0_usart_config();uart0_dma_config();uart0_nvic_config();
}// 发送一个字节
void usart_send_byte(uint8_t data)
{while(RESET == usart_flag_get(USART1, USART_FLAG_TBE));usart_data_transmit(USART1, data);
}// 发送字符串
void usart_send_string(uint8_t *str)
{while(*str != '\0'){usart_send_byte(*str++);}
}#include "stdio.h"// 发送指定长度的数据
void usart_send_data(uint8_t *data, uint16_t length)
{//printf("rx_data_length is %d\r\n",rx_data_length);for(uint16_t i = 0; i < length; i++){usart_send_byte(data[i]);}
}// USART0中断服务函数
void USART0_IRQHandler(void)
{// 检查空闲中断标志if(RESET != usart_interrupt_flag_get(USART0, USART_INT_FLAG_IDLE)){// 清除空闲中断标志usart_data_receive(USART0); // 读数据寄存器清除标志usart_interrupt_flag_clear(USART0, USART_INT_FLAG_IDLE);// 禁用DMAdma_channel_disable(DMA0, DMA_CH4);// 计算接收到的数据长度usart0_rx_len = USART0_RX_BUFFER_SIZE - dma_transfer_number_get(DMA0, DMA_CH4);// 设置接收完成标志usart0_rx_complete = 1;// 重新配置DMA,准备下一次接收dma_transfer_number_config(DMA0, DMA_CH4, USART0_RX_BUFFER_SIZE);dma_channel_enable(DMA0, DMA_CH4);}
}// USART1中断服务函数
void USART1_IRQHandler(void)
{if(RESET != usart_interrupt_flag_get(USART1, USART_INT_FLAG_IDLE)){// 清除空闲中断标志usart_data_receive(USART1); // 读数据寄存器清除标志usart_interrupt_flag_clear(USART1, USART_INT_FLAG_IDLE);// 关闭DMA,防止干扰dma_channel_disable(DMA0, DMA_CH5);// 计算接收到的数据长度rx_data_length = RX_BUFFER_SIZE - dma_transfer_number_get(DMA0, DMA_CH5);// 设置接收完成标志rx_complete_flag = 1;// 重新配置DMA,准备下一次接收dma_transfer_number_config(DMA0, DMA_CH5, RX_BUFFER_SIZE);dma_channel_enable(DMA0, DMA_CH5);}
}// 处理UART1接收到的数据
void process_rxcvUart1_data(void)
{if(rx_complete_flag){usart_send_data(rx_buffer, rx_data_length);// 清除标志和缓冲区memset(rx_buffer, 0, RX_BUFFER_SIZE);rx_data_length = 0;rx_complete_flag = 0;}
}// 处理UART0接收到的数据
void process_rxcvUart0_data(void)
{// 检查是否有数据接收完成if(usart0_rx_complete){// 回显接收到的数据usart0_send_data(usart0_rx_buffer, usart0_rx_len);// 清除标志,重新开始接收usart0_rx_complete = 0;usart0_rx_len = 0;}
}// DMA0通道4中断服务函数
void DMA0_Channel4_IRQHandler(void)
{// 检查DMA传输完成标志if(dma_interrupt_flag_get(DMA0, DMA_CH4, DMA_INT_FLAG_FTF) != RESET){// 清除传输完成标志dma_interrupt_flag_clear(DMA0, DMA_CH4, DMA_INT_FLAG_FTF);// 禁用DMAdma_channel_disable(DMA0, DMA_CH4);// 接收到的数据长度等于缓冲区大小usart0_rx_len = USART0_RX_BUFFER_SIZE;// 设置接收完成标志usart0_rx_complete = 1;}
}int fputc(int ch, FILE *f) // 补充stdio.h文件中fputc的具体实现方式
{usart_data_transmit(USART1, (uint8_t)ch);while(RESET == usart_flag_get(USART1, USART_FLAG_TBE));return ch;
}int main(void)
{// 初始化USART1及DMAnvic_priority_group_set(NVIC_PRIGROUP_PRE4_SUB0); //配置中断向量等级为组别4usart0_dma_init();usart1_dma_init();while(1){// 处理接收到的数据process_rxcvUart0_data();process_rxcvUart1_data();}
}
测试如下