这些小活动你都参加了吗?快来围观一下吧!>>
电子产品世界 » 论坛首页 » 嵌入式开发 » MCU » 如何用DMA的方式读写串口数据?

共2条 1/1 1 跳转至

如何用DMA的方式读写串口数据?

工程师
2024-09-03 19:15:50     打赏

串口接收(或者发送)的数据比较大,如果用中断逐字节从FIFO读数据太耗时了,光盘里的找不到有关DMA读写串口的demo




关键词: 串口     DMA    

助工
2024-09-03 19:16:07     打赏
2楼

使用DMA(直接存储器访问)方式可以显著提高串口数据的读写效率。下面是用DMA方式读写串口数据的一般步骤:

1. 初始化串口设备:设置波特率、数据位、停止位、校验位等串口相关参数。

2. 初始化DMA控制器:配置DMA通道的工作模式、传输方向、数据宽度、内存地址等。

3. 设置串口和DMA之间的关联:将串口的数据寄存器和DMA通道进行关联,以便实现数据的传输。

4. 配置DMA传输长度:设置DMA传输的数据长度,可以通过设定传输字节数或者传输完整的数据包来实现。

5. 启动DMA传输:使能DMA通道,并开始数据的传输。

6. 等待DMA传输完成:等待DMA传输完成的标志位被置位。

7. 处理接收(或发送)的数据:从内存中读取DMA传输的数据,或将要发送的数据写入内存。

下面是一个示例代码片段,演示如何使用DMA方式读取串口数据:

```c
#include

void DMA_init(void) {
    // DMA2 Stream2 配置为串口数据接收
    DMA_Stream_TypeDef *dma_stream = DMA2_Stream2;
    dma_stream->CR &= ~DMA_SxCR_EN;    // 禁用DMA传输

    // 设置DMA通道为串口6的数据接收
    dma_stream->PAR = (uint32_t) &(USART6->DR);
    dma_stream->M0AR = (uint32_t) dma_buffer;    // 数据存储缓冲区地址
    dma_stream->NDTR = BUFFER_SIZE;    // 读取数据的长度
    dma_stream->CR &= ~DMA_SxCR_CHSEL;    // DMA通道6
    dma_stream->CR &= ~DMA_SxCR_PL;    // 优先级低

    dma_stream->CR |= DMA_SxCR_CIRC;    // 循环模式
    dma_stream->CR |= DMA_SxCR_MINC;    // 增量模式
    dma_stream->CR &= ~DMA_SxCR_DIR;    // 外设到存储器模式
    dma_stream->CR |= DMA_SxCR_TCIE;    // 传输完成中断使能

    dma_stream->CR |= DMA_SxCR_EN;    // 启用DMA传输
}

void USART_init(void) {
    // 配置串口6
    USART6->CR1 &= ~USART_CR1_UE;    // 禁用串口
    USART6->CR1 &= ~USART_CR1_M;    // 8位数据位
    USART6->CR2 &= ~USART_CR2_STOP;    // 1位停止位
    USART6->CR1 &= ~USART_CR1_PCE;    // 无校验位

    // 配置通过DMA接收数据
    USART6->CR3 |= USART_CR3_DMAR;
   
    USART6->BRR = 104;    // 波特率为115200

    USART6->CR1 |= USART_CR1_RE;    // 启用接收模式
    USART6->CR1 |= USART_CR1_UE;    // 启用串口
}

int main(void) {
    DMA_init();    // 初始化DMA
    USART_init();    // 初始化串口

    while (1) {
        // 等待DMA接收数据完成的中断
        if (DMA2->LISR & DMA_LISR_TCIF2) {
            DMA2->LIFCR = DMA_LIFCR_CTCIF2;    // 清除传输完成中断标志位
            
            // 处理接收到的数据
            for (int i = 0; i < BUFFER_SIZE - DMA2_Stream2->NDTR; i++) {
                process_received_data(dma_buffer[i]);    // 处理每一个接收到的字节
            }
            
            DMA2_Stream2->NDTR = BUFFER_SIZE;    // 重设传输长度
            DMA2_Stream2->CR |= DMA_SxCR_EN;    // 开始DMA传输
        }
    }
}
```


共2条 1/1 1 跳转至

回复

匿名不能发帖!请先 [ 登陆 注册 ]