在使用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. 【转】实现一个自己的promise

    转, 原文:http://blog.csdn.net/yibingxiong1/article/details/68075416------------------------------------ ...

  2. PHP导入和导出CSV文件

    CREATE TABLE `student` ( `id` ) NOT NULL auto_increment, `name` varchar() NOT NULL, `sex` varchar() ...

  3. Centos下mahout安装与配置

    对于Mahout的安装与配置,须要一个前提.就是hadoop已经安装. 假设没有安装能够參考. http://blog.csdn.net/u012965373/article/details/4533 ...

  4. 2016/1/1 运算符 笔记整理 接2015/12/30 Java 语法

    ④运算符 1,赋值运算符:实现从右向左的赋值,符号= 2,算术运算符:符号 + - * / %(求余或求模),结果自动转成最大的                      类型,自动升级. 3, 比较 ...

  5. 关于编译(javac),import,package的再理解

    1.若我们在A.java中用到了类B,当我们仅仅用 javac A.java 编译A时,编译器也会去寻找B,若类B依然是源文件,也会自动编译它.在使用javac和java命令时,有一个参数选项 -ve ...

  6. BaezaYates 交集python和golang代码

    def bsearch(find, arr, low, high): while low <= high: mid = (low + high) >> 1 if arr[mid] = ...

  7. Codeforces Round #395 (Div. 1)

    比赛链接:http://codeforces.com/contest/763 A题: #include <iostream> #include <cstdio> #includ ...

  8. Wedding(2-SAT)

    传送门 稍微复杂一点的2-SAT. 读题之后发现有以下限制: 1.每一对夫妻(包括新郎和新娘)不能坐在桌子的一侧. 2.对于一些给定的非法(自行脑补)的关系,这两个人不能坐在新娘的同一侧. 因为每个人 ...

  9. 20. Extjs学习笔记——Ext.data.JsonStore使用说明

    Ext.data.JsonStore继承于Ext.data.Store,使得从远程JSON数据创建stores更为方便的简单辅助类.JsonStore合成了Ext.data.HttpProxy与Ext ...

  10. 05_锅炉压力案例_java实现

    最开始是有机顶盒,后来电视里面都带着一个安卓的设备.现在空调.冰箱.洗衣机都跃跃欲试地想把这个东西加上.海尔出了一款智能冰箱,就是在冰箱门上嵌了一个12寸的屏幕.这个屏幕实际上就是一个安卓的平板似的. ...