GD32H759 USART 使能IDLE+DMA接受 以及DMA发送

使用GD32H759,处于cortexm7内核,和STM32H7同一个内核,所以配置基本上相同,由于GD32系列更新,所以工艺更高,发热等等控制更好.GD32官方没有提供类似于STM32的HAL库,只有标准库,同时配置方法与STM32有一点不同.

进入正文,工程结构,本次文章的内容主要集中在SYS文件夹,BSP文件夹的内容可以删除.

思路

在USART接收完成以后,也就是数据没有继续发送时,USART会产生一个IDLE 空闲中断,其标志位为USART_FLAG_IDLE,发生IDLE中断以后,我们可以在其中读取缓冲区,通知接受完成等等,结合DMA功能自动将数据搬运到缓冲区,在IDLE中断中获取数据长度,清除中断标志位,DMA传输标志位,以及开始下一次DMA搬运.

所有我们需要先配置USART的IDLE中断,确认能够进入中断以后编写DMA的参数,在IDLE中启动DMA,当再次发生IDLE中断时,可认为本次串口发送完毕,使用DMA再将数据发送到USART_TD发送寄存器发送出去.

串口配置

首先根据基本的示例代码,配置我们的串口基本参数,USART对应端口自行选择修改.

由于我们需要在IDLE中断中完成数据接收,所以配置串口中断的NVIC.

void USART_Init(uint32_t bound)
{
    /* IO 及 时钟配置 */
    rcu_periph_clock_enable(USART_TX_GPIO_CLK);     /* 使能串口TX脚时钟 */
    rcu_periph_clock_enable(USART_RX_GPIO_CLK);     /* 使能串口RX脚时钟 */
    rcu_periph_clock_enable(RCU_USART1);          /* 使能串口时钟 */
    USART_RX_DMA_Config();
    USART_TX_DMA_Config();
    /* 设置USARTx_TX的复用功能选择 */
    gpio_af_set(USART_TX_GPIO_PORT, USART_TX_GPIO_AF, USART_TX_GPIO_PIN);
    /* 设置USARTx_RX的复用功能选择 */
    gpio_af_set(USART_RX_GPIO_PORT, USART_RX_GPIO_AF, USART_RX_GPIO_PIN);
    /* USARTx_TX的模式设置 */
    gpio_mode_set(USART_TX_GPIO_PORT, GPIO_MODE_AF, GPIO_PUPD_PULLUP, USART_TX_GPIO_PIN);
    gpio_output_options_set(USART_TX_GPIO_PORT, GPIO_OTYPE_PP, GPIO_OSPEED_100_220MHZ, USART_TX_GPIO_PIN);
    /* USARTx_RX的模式设置 */
    gpio_mode_set(USART_RX_GPIO_PORT, GPIO_MODE_AF, GPIO_PUPD_PULLUP, USART_RX_GPIO_PIN);
    gpio_output_options_set(USART_RX_GPIO_PORT, GPIO_OTYPE_PP, GPIO_OSPEED_100_220MHZ, USART_RX_GPIO_PIN);
    /* 配置USART的参数 */
    usart_deinit(USART1);                                   /* 复位USARTx */
    usart_baudrate_set(USART1, bound);                      /* 设置波特率 */
    usart_stop_bit_set(USART1, USART_STB_1BIT);             /* 一个停止位 */
    usart_word_length_set(USART1, USART_WL_8BIT);           /* 字长为8位数据格式 */
    usart_parity_config(USART1, USART_PM_NONE);             /* 无奇偶校验位 */
    
    usart_transmit_config(USART1, USART_TRANSMIT_ENABLE);   /* 使能发送 */
    usart_dma_transmit_config(USART1, USART_TRANSMIT_DMA_ENABLE);
    
    usart_receive_config(USART1, USART_RECEIVE_ENABLE);     /* 使能接收 */
    usart_dma_receive_config(USART1, USART_RECEIVE_DMA_ENABLE);
    
    usart_flag_clear(USART1, USART_FLAG_IDLE);              //没啥用
    usart_interrupt_enable(USART1, USART_INT_IDLE);
    /* 配置NVIC,并设置中断优先级 */
    nvic_irq_enable(USART1_IRQn, 3, 3);                     /* 组2,抢占优先级3,子优先级3 */
    usart_enable(USART1);                                    /* 使能串口 */
    usart_flag_clear(USART1, USART_FLAG_IDLE);              //没啥用
}
### GD32 USART DMA 串口通信配置 #### 配置USART模块 为了实现GD32USART通过DMA方式传输数据,首先需要正确设置USART外设参数。这包括波特率、字符长度、停止位以及校验模式等基本属性。 ```c /* 初始化结构体 */ struct gd32_uart { uint32_t baud_rate; /* 波特率 */ uint8_t data_bits; /* 数据位数 */ uint8_t stop_bits; /* 停止位数 */ uint8_t parity; /* 校验类型 */ }; void usart_config(struct gd32_uart *uart) { rcu_periph_clock_enable(RCU_USARTx); // 启用USART时钟 usart_deinit(USARTx); uart->baud_rate = 9600; uart->data_bits = DATA_8BIT; uart->stop_bits = STOP_BIT_1; uart->parity = NO_PARITY; usart_baudrate_set(USARTx, uart->baud_rate); // 设置波特率 usart_word_length_set(USARTx, uart->data_bits); // 设置数据位宽度 usart_stop_bit_set(USARTx, uart->stop_bits); // 设置停止位数量 usart_parity_config(USARTx, uart->parity); // 设置奇偶检验选项 } ``` #### 配置DMA控制器 接着要为USART配置相应的DMA通道用于自动处理数据传送任务。这里假设已知具体的DMA请求映射关系表,并据此选择合适的DMA流/通道来关联到指定的USART设备上[^1]。 ```c static void dma_init(void){ /* 开启DMA时钟 */ rcu_periph_clock_enable(DMA_PERIPH_CLOCK); /* 清除DMA寄存器默认值 */ dma_channel_reset(DMAy_Channelz); /* 配置DMA传输参数 */ struct dma_parameter_struct dma_init_struct={ .peripheral_addr=(uint32_t)&USART_DATA_REG, .memory_addr=buffer_address, .direction=DMA_MEMORY_TO_PERIPHERAL, .size=DMA_SIZE, .priority=DMA_PRIORITY_HIGH, .mode=DMA_CIRCULAR_MODE | DMA_MEMORY_INCREASE, .number_of_data=length_in_bytes }; dma_init(DMAy_Channelz,&dma_init_struct); /* 关联DMAUSART */ usart_dma_transmit_config(USARTx,DMA_TRANSMIT_ENABLE); } ``` #### 中断服务程序设计 当采用空闲线检测机制作为触发条件之一时,则需编写专门针对该事件响应的服务例程(ISR),以便及时捕获并处理接收到的信息片段。 ```c void usart_isr_handler(void){ if (usart_interrupt_flag_get(USARTx, USART_INT_FLAG_IDLE)){ /* 处理接收缓冲区中的有效载荷 */ /* 清除IDLE标志位 */ usart_interrupt_flag_clear(USARTx, USART_INT_FLAG_IDLE); /* 可选操作:通知应用程序层有新消息到达 */ } } ``` #### 应用实例展示 下面给出一段简单的测试代码用来验证上述配置的有效性: ```c int main(){ char send_buffer[]="Hello World!"; int buffer_size=strlen(send_buffer)+1; usart_config(&my_uart_settings); dma_init(); while(1){ /* 发送字符串给另一端 */ memcpy(dma_memory_base_ptr,send_buffer,buffer_size); /* 触发一次完整的DMA事务 */ dma_channel_enable(DMAy_Channelz); delay_ms(DELAY_TIME_BETWEEN_TRANSFERS); } return 0; }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值