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 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();
    }
}

测试如下
在这里插入图片描述

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值