在使用STM32的UART的DMA功能总结如下:

首先上代码,这里采用STM32 的USART1作为Demo,RX的DMA为DMA1_Channel5,TX的DMA为DMA1_Channel4.初始化如下,红色的标记需要注意:

RX-DMA初始化

 // DMA Rx
USART_DMACmd(USART1,USART_DMAReq_Rx,ENABLE);
DMA_Cmd(DMA1_Channel5,DISABLE);
DMA_InitStruct.DMA_PeripheralBaseAddr = (u32)(&USART1->DR);
DMA_InitStruct.DMA_MemoryBaseAddr = (u32)RxBuf0;
DMA_InitStruct.DMA_DIR = DMA_DIR_PeripheralSRC;
DMA_InitStruct.DMA_BufferSize = ;
DMA_InitStruct.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
DMA_InitStruct.DMA_MemoryInc = DMA_MemoryInc_Enable;
DMA_InitStruct.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;
DMA_InitStruct.DMA_MemoryDataSize = DMA_PeripheralDataSize_Byte;
DMA_InitStruct.DMA_Mode = DMA_Mode_Circular;
DMA_InitStruct.DMA_Priority = DMA_Priority_High;
DMA_InitStruct.DMA_M2M = DMA_M2M_Disable;
DMA_Init(DMA1_Channel5,&DMA_InitStruct);
DMA_Cmd(DMA1_Channel5,ENABLE);

中断的初始化如下:

    DMA_ITConfig(DMA1_Channel5,DMA_IT_TC,ENABLE);
NVIC_InitStruct.NVIC_IRQChannel = DMA1_Channel5_IRQn;
NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = ;
NVIC_InitStruct.NVIC_IRQChannelSubPriority = ;
NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStruct); //ENABLE DMA TX ISR
DMA_ITConfig(DMA1_Channel4,DMA_IT_TC,ENABLE);
NVIC_InitStruct.NVIC_IRQChannel = DMA1_Channel4_IRQn;
NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = ;
NVIC_InitStruct.NVIC_IRQChannelSubPriority = ;
NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStruct);

TX发送函数如下:

 void USART1_SendDMA(uint8_t* buf,int len)
{
DMA_InitTypeDef DMA_InitStruct;

DMA_ITConfig(DMA1_Channel4,DMA_IT_TC,ENABLE); DMA_Cmd(DMA1_Channel4,DISABLE);

DMA_InitStruct.DMA_PeripheralBaseAddr = (u32)(&USART1->DR);
DMA_InitStruct.DMA_MemoryBaseAddr = (u32)buf;
DMA_InitStruct.DMA_DIR = DMA_DIR_PeripheralDST;
DMA_InitStruct.DMA_BufferSize = len;
DMA_InitStruct.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
DMA_InitStruct.DMA_MemoryInc = DMA_MemoryInc_Enable;
DMA_InitStruct.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;
DMA_InitStruct.DMA_MemoryDataSize = DMA_PeripheralDataSize_Byte;
DMA_InitStruct.DMA_Mode = DMA_Mode_Normal;
DMA_InitStruct.DMA_Priority = DMA_Priority_VeryHigh;
DMA_InitStruct.DMA_M2M = DMA_M2M_Disable;
DMA_Init(DMA1_Channel4,&DMA_InitStruct); DMA_Cmd(DMA1_Channel4,ENABLE);
}

两个服务函数如下:

RX-DMA中断函数,实现RX的双缓冲区功能。值得注意的是,你的DMA设置成Normal模式的时候,在中断函数中就得设置DMABufferSize,应为Normal模式完成一次传输之后,BufferSize直接清零,设置成Circle模式就不会存在这个问题,下面的中断就是设置成Circle模式的。

void DMA1_Channel5_IRQHandler()
{
if(DMA_GetITStatus(DMA1_IT_TC5))
{
if(using_buf0 ==)
{
     DMA1_Channel5->CMAR = (u32)RxBuf0;
using_buf0 = ;
}
else
{
DMA1_Channel5->CMAR = (u32)RxBuf1;
using_buf0 = ;
}
recv_flag = ;
DMA_ClearITPendingBit(DMA1_IT_TC5);
}
}

TX-DMA中断函数

void DMA1_Channel4_IRQHandler()
{
if(DMA_GetITStatus(DMA1_IT_TC4))
{
//TODO:Add code here
DMA_ClearITPendingBit(DMA1_IT_TC4);
}
}

几点说明

1)这里采用双缓冲区的方式,对于大数据量的时候是很有效的,在处理一个缓冲区数据的时候,另外一个缓冲区能够正常接收数据

2)TX的DMA中断,可以采用类似于操作系统中互斥量的操作,当一个数组还在发送的时候,另外一个数组如果检测到一个在发送,则不能够进行发送,不然这样子数据会乱掉;

3)如果DMA接收想采用循环缓冲区的方式,可以直接将RX-DMA设置成Circle方式,然后数据就会硬件上自动实现环形缓冲区的功能,省了不少时间。

4)DMA在采用Normal模式的时候,当一次任务完成后,DMA->DMA_BufferSize自动清零,并且DMA自动停止。如果想再次设置DMA的BufferSize的话,必须要进行如下操作:

step1:DMA_CMD(DMAx_Channely,DISABLE);

step2: 设置DMA_BufferLen

step3:DMA_CMD(DMAx_Channely,ENABLE)

5)DMA采用Circle模式的时候,在发送或者接受完成之后,仍然保存着BufferSize,并且DMA还处于使能状态,一直连续工作,直到用户停止DMA

STM32的串口DMA收发以及双缓冲区的实现的更多相关文章

  1. STM32 HAL 库实现乒乓缓存加空闲中断的串口 DMA 收发机制,轻松跑上 2M 波特率

    前言 直接储存器访问(Direct Memory Access,DMA),允许一些设备独立地访问数据,而不需要经过 CPU 介入处理.因此在访问大量数据时,使用 DMA 可以节约可观的 CPU 处理时 ...

  2. STM32之串口DMA接收不定长数据

    STM32之串口DMA接收不定长数据 引言 在使用stm32或者其他单片机的时候,会经常使用到串口通讯,那么如何有效地接收数据呢?假如这段数据是不定长的有如何高效接收呢? 同学A:数据来了就会进入串口 ...

  3. Stm32CubeMX5 配置 STM32的串口DMA接受方式 --- 基于 stm32f051k8u6

     实现的功能: 使用MDA方式把串口接受的数据在发送给串口(当然也可以做其他解析控制使用) 1. 先初始化 时钟使用外部的晶振配置系统时钟为48Mhz 2. 串口参数配置 3. 使能中断 4. 配置串 ...

  4. STM32使用串口1配合DMA接收不定长数据,减轻CPU载荷

    STM32使用串口1配合DMA接收不定长数据,减轻CPU载荷 http://www.openedv.com/thread-63849-1-1.html 实现思路:采 用STM32F103的串口1,并配 ...

  5. STM32F407的串口采用DMA收发数据

    源:STM32F407的串口采用DMA收发数据

  6. STM32串口DMA接收数据错位——暴力解决方法

    背景:两片STM32通过串口通信,为了减小CPU负担,采用DMA进行通信,发送端为STM32F103C8T6,接收端为STM32F407VET6.在调试的过程中发现,一直出现数据错位的问题,接收端尝试 ...

  7. STM32CubeMx——串口使用DMA收发

    用到的是DMA发送数据,接收还是普通的串口接收. 一.代码生成 1.按以前的方法设置好时钟和调试方式,这里就不多说了. 2.设置串口1. 3.在DMA Setting里点击Add添加USART1_TX ...

  8. STM32的USART DMA传输(转)

    源:STM32的USART DMA传输 问题描述: 我有一个需求,AD采得一定数目的数据之后,由串口DMA发出,由于AD使用双缓冲,所以每次开始DMA的时候都需要重新设置开始的内存地址以及传输的数目( ...

  9. RT-Thread中的串口DMA分析

    这里分析一下RT-Thread中串口DMA方式的实现,以供做新处理器串口支持时的参考. 背景 在如今的芯片性能和外设强大功能的情况下,串口不实现DMA/中断方式操作,我认为在实际项目中基本是不可接受的 ...

随机推荐

  1. Logstash学习系列之插件介绍

    Logstash插件获取方式 插件获取地址: https://github.com/logstash-plugins  在线安装: /plugin install logstash-input-jdb ...

  2. 014 DNS

    解析主机名 Router>en Password: Router#config t Enter configuration commands, one per line.  End with C ...

  3. Skype for Business七大新功能

    Lync Server 2013的下一版本号.Skype for Business将于2015年4月正式公布,下面是七大新功能. "呼叫监听"(Call Monitor)--假设你 ...

  4. 单一责任原则(SRP)

    1.就一个类而言,应该仅有一个引起它变化的原因. 2.在SRP中定义职责为:“变化的原因”.  如果你想到多个动机去改变这个类,那这个类就有多个职责

  5. 在对象内部尽量直接訪问实例变量 --Effictive Objective-C 抄书

    在对象之外訪问实例变量时,应该总是通过属性来做.在那么在对象内部訪问实例变量的时候,又该怎样呢? 这是 OCer们一直激烈讨论的问题.有人觉得,不管什么情况,都应该通过属性来訪问实例变量;也有人说,& ...

  6. Android处理日期

    近期做一个项目,后台返回的日期是RFC3339格式的.之前没有看到过,当中遇到了几个问题以及解决 1.2015-11-18T14:49:55Z转换 在SimpleDateFormat中给出了几种格式 ...

  7. Oracle高水位线

    Oracle高水位线 https://blog.csdn.net/jx_jy/article/details/50607790 Oracle高水位线的概念 Oracle里面的对象放到存储级别都称为se ...

  8. Flask的闪现(message) 请求扩展 中间件 蓝图

    补充:一个编程思路 需求:做一些邮件短信微信的消息通知,比如账单告警之类的:比如数据库操作,数据库种类繁多:缓存的选择比如redis/memcache,诸如此类需要进行选择配置,如果我们单纯的用函数去 ...

  9. Python不兼容问题

    今天遇到了一个Python2与3不兼容的坑. ride是基于robot框架的python自动化ui,但它只支持python2,而我电脑环境只有python3,想跑别人基于ride编写的测试用例,折腾了 ...

  10. Python 之reduce()函数

    reduce()函数: reduce()函数也是Python内置的一个高阶函数.reduce()函数接收的参数和 map()类似,一个函数 f,一个list,但行为和 map()不同,reduce() ...