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 8N1
usart_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);
// 使能USART1
usart_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通道5
dma_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速率最高50MHz
gpio_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); // 波特率115200
usart_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 配置为 不使能RTS
usart_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);
// 使能USART0
usart_enable(USART0);
}
// DMA配置
void uart0_dma_config(void)
{
rcu_periph_clock_enable(RCU_DMA0); //使能DMA0时钟
dma_deinit(DMA0, DMA_CH4); //复位DMA0通道4
// 配置DMA0通道4
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)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通道4
dma_channel_enable(DMA0, DMA_CH4);
// 关联USART0_RX到DMA0通道4
usart_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);
// 禁用DMA
dma_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);
// 禁用DMA
dma_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及DMA
nvic_priority_group_set(NVIC_PRIGROUP_PRE4_SUB0); //配置中断向量等级为组别4
usart0_dma_init();
usart1_dma_init();
while(1)
{
// 处理接收到的数据
process_rxcvUart0_data();
process_rxcvUart1_data();
}
}
测试如下

648

被折叠的 条评论
为什么被折叠?



