GD32F4xx系列单片机-串口配合DMA的使用
将初始化、DMA 配置和数据发送/接收部分分成三个函数。
代码:
1. 初始化函数(UartxInit)
该函数用于初始化串口相关硬件设置(GPIO、USART 和 DMA)。
void UartxInit(uarttypedefenum com){
/* 使能GPIO时钟 */ rcuperiphclockenable(COMGPIOCLK[com]);
/* 使能USART时钟 */
rcuperiphclockenable(COMCLK[com]);
/* 配置TX和RX引脚为USART功能 */
gpioafset(COMGPIOPORT[com], COMAF[com], COMTXPIN[com]);
// 连接TX引脚
gpioafset(COMGPIOPORT[com], COMAF[com], COMRXPIN[com]); // 连接RX引脚
/* 配置TX引脚为推挽输出,设置50MHz速度 */ gpiomodeset(COMGPIOPORT[com], GPIOMODEAF, GPIOPUPDPULLUP, COMTXPIN[com]);
gpiooutputoptionsset(COMGPIOPORT[com], GPIOOTYPEPP, GPIOOSPEED50MHZ, COMTXPIN[com]);
/* 配置RX引脚为推挽输入,设置50MHz速度 */
gpiomodeset(COMGPIOPORT[com], GPIOMODEAF, GPIOPUPDPULLUP, COMRXPIN[com]);
gpiooutputoptionsset(COMGPIOPORT[com],GPIOOTYPEPP, GPIOOSPEED50MHZ, COMRXPIN[com]); /* 配置USART */
usartdeinit(COMNUM[com]);
usartbaudrateset(COMNUM[com],COMBUADRATE[com]);
usartreceiveconfig(COMNUM[com],USARTRECEIVEENABLE);
usarttransmitconfig(COMNUM[com],USARTTRANSMITENABLE);
usartenable(COMNUM[com]); /* 配置USART的DMA */
USARTxDMATxInit(COMNUM[com]); /* 使能USART接收中断 */
usartinterruptenable(COMNUM[com],USARTINTRBNE); /* 配置NVIC中断 */
nvicirqenable(COMIRQ[com], COMNVICIRQPRE[com], COMNVICIRQSUB[com]);
}
配置解释:
1.GPIO 配置:设置 TX 和 RX 引脚的功能为 USART,并设置为推挽模式,以保证正确的信号传输。
2.USART 配置:设置波特率和启用发送和接收功能。
3.DMA 配置:启用 USART 的 DMA 功能。
4.中断配置:使能 USART 的接收中断,以便接收数据。
2. DMA 配置函数(UartxDmaConfig)
该函数用于配置 DMA 以支持数据的发送。
void UartxDmaConfig(uarttypedefenum com, uint32_t *data, uint16_t len)
{
dmasingledataparameterstruct dmainitstruct; /* 使能DMA时钟 */
rcuperiphclockenable(RCUDMA1); /* 反初始化DMA通道 */
dmadeinit(DMA0, DMACH1); /* 配置DMA传输参数 */
dmainitstruct.direction = DMAMEMORYTOPERIPH; // 从内存到外设
dmainitstruct.memory0addr = (uint32_t)data; // 内存地址
dmainitstruct.memoryinc = DMAMEMORYINCREASEENABLE; // 启用内存地址递增
dmainitstruct.periphmemorywidth = DMAPERIPHWIDTH8BIT; // 外设宽度:8位
dmainitstruct.number = len; // 传输的数据长度
dmainitstruct.periphaddr = UART6DATAADDRESS; // 外设地址(UART6数据寄存器地址)
dmainitstruct.periphinc = DMAPERIPHINCREASEDISABLE; // 禁用外设地址递增
dmainitstruct.priority = DMAPRIORITYULTRAHIGH; // 高优先级 /* 初始化DMA传输模式 */
dmasingledatamodeinit(DMA0, DMACH1, &dmainitstruct); /* 配置DMA模式,禁用循环模式 */
dmacirculationdisable(DMA0, DMACH1); /* 配置DMA通道外设选择 */
dmachannelsubperipheralselect(DMA0, DMACH1, DMASUBPERI5); /* 启用DMA传输 */
usartdmatransmitconfig(UART6, USARTDENTENABLE);
dmachannelenable(DMA0, DMACH1);
}
配置解释:
5.DMA 通道配置:配置 DMA 通道参数,设置内存地址、外设地址以及数据传输方向。
6.优先级配置:为 DMA 传输设置超高优先级。
7.DMA 启动:启用 DMA 通道和 USART 的 DMA 发送功能。
3. 数据发送函数(UartxSendData)
该函数用于发送数据并等待发送完成。
int UartxSendData(uarttypedefenum com, uint32_t *data, uint16_t len)
{
/* 清除USART标志,确保没有之前的传输干扰 */
usart_flag_clear(COMNUM[com], USART_FLAG_TC); /* 禁用DMA通道 */
dma_channel_disable(DMA0, DMACH1); /* 清除DMA标志 */
dma_flag_clear(DMA0, DMA_CH1, DMA_FLAG_FTF); /* 配置DMA传输地址 */
dma_memory_address_config(DMA0, DMA_CH1, (uint32_t)data); /* 配置DMA传输的字节数 */
dma_transfer_number_config(DMA0, DMA_CH1, len); /* 启动DMA通道 */
dma_channel_enable(DMA0, DMA_CH1); /* 启用USART的DMA传输功能 */
usart_dma_transmit_config(COMNUM[com], USART_DENT_ENABLE); /* 等待DMA完成数据传输 */
while (RESET == dma_flag_get(DMA0, DMA_CH1, DMA_INTF_FTFIF)) {}
return 0; // 传输完成
}
配置解释:
8.DMA 配置:清除任何以前的传输标志,重新配置 DMA 传输参数。
9.DMA 启动:启用 DMA 通道并启动数据传输。
10.等待传输完成:使用 DMA 完成传输的标志来阻塞直到数据传输完成。
4. 数据接收函数(UartxReceiveData)
该函数用于通过 USART 接收数据。
int UartxReceiveData(uarttypedefenum com, uint32_t *buffer, uint16_t len)
{
/* 清除接收标志 */
usart_flag_clear(COMNUM[com], USART_FLAG_RXNE); /* 启动DMA接收 */
dma_channel_disable(DMA0, DMACH1); // 禁用DMA通道
dma_flag_clear(DMA0, DMA_CH1, DMA_FLAG_FTF); // 清除DMA标志
dma_memory_address_config(DMA0, DMA_CH1, (uint32_t)buffer); // 配置接收缓冲区地址
dma_transfer_number_config(DMA0, DMA_CH1, len); // 配置接收数据长度
dma_channel_enable(DMA0, DMA_CH1); // 启动DMA接收通道
/* 启用USART DMA接收功能 */ usart_dmarx_enable(COMNUM[com]); /* 等待接收完成 */
while (RESET == dma_flag_get(DMA0, DMA_CH1, DMA_INTF_FTFIF)) {}
return 0; // 接收完成
}
配置解释:
11.DMA 接收配置:配置接收缓冲区并启动 DMA 接收通道。
12.等待接收完成:通过 DMA 完成标志来检测数据接收是否完成。
总结
代码通过将初始化、DMA 配置、数据发送和接收拆分成了多个函数,使代码结构更加清晰,模块化程度更高。
每个函数负责不同的任务,可以在实际应用中方便地进行维护和扩展。