一个常见的DMA应用场景是从USART接收数据,并将其存储到内存中。
通过DMA,我们可以实现USART接收数据的高效传输,而不需要CPU干预。
以下是具体的应用实例:
配置USART和DMA
初始化USART:
配置USART为接收模式。
启用USART中断和DMA请求。
配置DMA:
配置DMA通道,用于将接收到的USART数据传输到内存中。
配置DMA的源地址为USART的数据寄存器,目标地址为接收缓冲区。
代码实现
以下是一个从USART接收数据并使用DMA存储到内存的实例代码:
c
#include "gd32e230.h"
#define BUFFER_SIZE 100
uint8_t rx_buffer[BUFFER_SIZE]; // 数据接收缓冲区
// 配置USART1
void usart_config(void) {
rcu_periph_clock_enable(RCPU_USART1); // 启用USART1时钟
rcu_periph_clock_enable(RCPU_GPIOA); // 启用GPIOA时钟
// 配置PA9为USART1的TX引脚,PA10为USART1的RX引脚
gpio_init(GPIOA, GPIO_MODE_AF_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_9); // TX
gpio_init(GPIOA, GPIO_MODE_IN_FLOATING, GPIO_OSPEED_50MHZ, GPIO_PIN_10); // RX
// 配置USART1,波特率9600,8数据位,1停止位,无校验
usart_deinit(USART1);
usart_init(USART1, 9600, USART_WL_8BIT, USART_STB_1BIT, USART_PERR_NOPARITY);
// 启用USART1接收DMA请求
usart_dma_enable(USART1, USART_DMA_RECEIVE);
usart_enable(USART1);
}
// 配置DMA
void dma_config(void) {
// 启用DMA时钟
rcu_periph_clock_enable(RCPU_DMA);
// 配置DMA通道:将USART1的数据接收寄存器传输到rx_buffer
dma_channel_struct_init(&dma_init_struct);
dma_init_struct.peripheral_address = (uint32_t)&USART_DATA(USART1); // USART1数据寄存器地址
dma_init_struct.memory_address = (uint32_t)rx_buffer; // 数据存储到rx_buffer
dma_init_struct.direction = DMA_DIR_PERIPHERAL_TO_MEMORY; // 外设到内存
dma_init_struct.number_of_data = BUFFER_SIZE; // 传输100个字节
dma_init_struct.priority = DMA_PRIORITY_HIGH; // 高优先级
dma_channel_init(DMA1, DMA_CHANNEL_4, &dma_init_struct); // 配置DMA1通道4(USART1接收)
// 启用DMA通道
dma_channel_enable(DMA1, DMA_CHANNEL_4);
}
void dma_transfer_complete_irq(void) {
// 处理DMA完成中断,数据接收完成
if (dma_flag_get(DMA1, DMA_FLAG_TC4)) {
// 处理接收到的数据,例如打印接收到的数据
for (int i = 0; i < BUFFER_SIZE; i++) {
printf("Received data[%d]: %c\n", i, rx_buffer[i]);
}
// 清除DMA传输完成标志
dma_flag_clear(DMA1, DMA_FLAG_TC4);
}
}
int main(void) {
usart_config(); // 配置USART1
dma_config(); // 配置DMA
while (1) {
// CPU可以继续执行其他任务,DMA接收数据时,CPU可以不干预
// 当DMA接收完成时,通过中断或标志通知CPU
}
}
说明
USART配置:通过usart_init()函数配置USART的波特率、数据位、停止位和校验方式。usart_dma_enable()函数启用USART的DMA接收请求。
DMA配置:通过dma_channel_init()函数配置DMA通道,指定源地址(USART的接收数据寄存器)和目标地址(接收缓冲区rx_buffer)。
DMA中断:在DMA传输完成后,可以启用DMA中断,通知CPU数据接收已完成。在dma_transfer_complete_irq()中断服务函数中,我们处理接收到的数据。
DMA传输的优势
自动化传输:DMA自动从USART接收数据并存储到内存,无需CPU的干预。
提高效率:数据传输速度比CPU轮询要快得多。
节省CPU资源:在DMA完成数据传输时,CPU可以处理其他任务,只有在传输完成时才需要处理相关数据。
|