串口接收(或者发送)的数据比较大,如果用中断逐字节从FIFO读数据太耗时了,光盘里的找不到有关DMA读写串口的demo
使用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传输
}
}
}
```
回复
有奖活动 | |
---|---|
【有奖活动——B站互动赢积分】活动开启啦! | |
【有奖活动】分享技术经验,兑换京东卡 | |
话不多说,快进群! | |
请大声喊出:我要开发板! | |
【有奖活动】EEPW网站征稿正在进行时,欢迎踊跃投稿啦 | |
奖!发布技术笔记,技术评测贴换取您心仪的礼品 | |
打赏了!打赏了!打赏了! |