文档章节

stm32f103串口使用DMA+FIFO

Ice99
 Ice99
发布于 2017/01/04 09:16
字数 719
阅读 73
收藏 0
点赞 0
评论 0

stm32f103若使用普通的串口接收程序,波特率设为115200,由于读取时需要占用CPU资源,所以实际速率非常慢。但如果使用DMA来处理则速度非常快,实测在波特率115200时,并且使用队列,速率可以达到10k以上。当然实际情况可能有些差别,我是用来接收上位机发来的固件,然后当从FIFO读取出的数据长度计满1024字节时,还要去写入FLASH。当然此时如果FIFO大于1024字节的话,DMA还是会继续读取从串口接收到的数据,并存储至FIFO。

 

1.DMA队列

/*

* File : [fifo.h]

*/

#include "stm32f10x.h"

#define RINGQ_MAX 10000 //队列大小

 

typedef struct

{

u32 OldLen;

u32 NewLen;

u32 TotalLen; //数据长度

u8 *BaseAddr; //缓冲区基地址

u8 *EndAddr; //缓冲区尾地址

u8 *ReadAddr; //数据读取地址

}LinkQueue;

 

int InitQueue (LinkQueue *Q, u8 *bufbase, u32 size);

int GetLength (LinkQueue *Q);

int EnQueue (LinkQueue *Q);

int OutQueue (LinkQueue *Q, unsigned char *buf, int len);

 

 

 

/*

* File : [fifo.c]

*/

#include "fifo.h"

#include "usart.h"

 

/*

* 初始化队列

*/

int InitQueue (LinkQueue *Q, u8 *bufbase, u32 size)

{

Q->BaseAddr = bufbase;

Q->EndAddr = bufbase + RINGQ_MAX;

Q->ReadAddr = bufbase;

Q->NewLen = 0;

Q->OldLen = 0;

Q->TotalLen = 0;

return 0;

}

 

/*

* 获取DMA 已传输字节数

*/

int GetLength (LinkQueue *Q)

{

Q->NewLen = RINGQ_MAX - DMA_GetCurrDataCounter(DMA1_Channel3);

return 0;

}

 

/*

* 入队列

*/

int EnQueue (LinkQueue *Q)

{

if (Q->NewLen > Q->OldLen)

{

//正常情况下,

Q->TotalLen += (Q->NewLen - Q->OldLen);

}

else

{

if(Q->NewLen < Q->OldLen)

{

//DMA从新开始计数

Q->TotalLen += (Q->NewLen + RINGQ_MAX - Q->OldLen);

if (Q->TotalLen > RINGQ_MAX)

{

return 1; //溢出

}

}

}

Q->OldLen = Q->NewLen;

return 0;

}

 

/*

* 出队列

*/

int OutQueue (LinkQueue *Q, unsigned char *buf, int len)

{

u32 i;

if(Q->TotalLen > 0)

{

if (len > Q->TotalLen)

{

//请求数大于可读取数

len = Q->TotalLen;

}

// Q->TotalLen -= len;

for (i = 0; i < len; i++)

{

buf[i] = *(Q->ReadAddr++);

Q->TotalLen--;

if(Q->TotalLen == 0)

{

while(0);

}

if (Q->ReadAddr == Q->EndAddr)

{

//读到缓冲区尾部,返回基址

Q->ReadAddr = Q->BaseAddr;

}

 

}

}

else

{

len = 0;

}

return len;

}

 

 

 

 

 

 

2. DMA串口配置程序

/*

* File : [usart.c]

*/

 

#include "stm32f10x.h"

#include "usart.h"

#include "fifo.h"

 

#define USART3_DR_Base 0x40013804

 

u8 TxBuffer1[RINGQ_MAX] ; //发送缓冲区

u8 RxBuffer1[RINGQ_MAX]; //接收缓冲区

 

void DMA_Configuration(void)

{

DMA_InitTypeDef DMA_InitStructure;

 

/* DMA1 Channel4 (triggered by USART3 Tx event) Config */

DMA_DeInit(DMA1_Channel2);

DMA_InitStructure.DMA_PeripheralBaseAddr = USART3_DR_Base;

DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)TxBuffer1;

DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST;

DMA_InitStructure.DMA_BufferSize = 0;

DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;

DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;

DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;

DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;

DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;

DMA_InitStructure.DMA_Priority = DMA_Priority_VeryHigh;

DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;

DMA_Init(DMA1_Channel2, &DMA_InitStructure);

 

DMA_DeInit(DMA1_Channel3);

DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)(&USART3->DR);

DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)RxBuffer1;

DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;

DMA_InitStructure.DMA_BufferSize = RINGQ_MAX;

DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;

DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;

DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;

DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;

DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;

DMA_InitStructure.DMA_Priority = DMA_Priority_VeryHigh;

DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;

DMA_Init(DMA1_Channel3, &DMA_InitStructure);

}

 

void DMA_Send( unsigned char *buf,int len)

{

DMA_InitTypeDef DMA_InitStructure;

 

/* DMA1 Channel4 (triggered by USART3 Tx event) Config */

DMA_DeInit(DMA1_Channel2);

DMA_InitStructure.DMA_PeripheralBaseAddr = USART3_DR_Base;

DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)buf;

DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST;

DMA_InitStructure.DMA_BufferSize = len;

DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;

DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;

DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;

DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;

DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;

DMA_InitStructure.DMA_Priority = DMA_Priority_VeryHigh;

DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;

DMA_Init(DMA1_Channel2, &DMA_InitStructure);

//while (DMA_GetFlagStatus(DMA1_FLAG_TC4) == RESET){} // 等待传输完成

DMA_ClearFlag(DMA1_FLAG_TC2) ;//功能

DMA_Cmd(DMA1_Channel2, DISABLE);

DMA1_Channel2->CNDTR=len; //DMA1,传输数据量

DMA_Cmd(DMA1_Channel2, ENABLE);

DMA_ClearITPendingBit(DMA1_IT_TC2);

DMA_Cmd(DMA1_Channel2, ENABLE);

}

 

/*****************************************************************

USART3 初始化 baud 波特率

*****************************************************************/

void USART3_Init(unsigned int baud)

{

USART_InitTypeDef USART_InitStructure;

 

USART_InitStructure.USART_BaudRate = baud;

USART_InitStructure.USART_WordLength = USART_WordLength_8b;

USART_InitStructure.USART_StopBits = USART_StopBits_1;

USART_InitStructure.USART_Parity = USART_Parity_No;

USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;

USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;

USART_Init(USART3, &USART_InitStructure);

USART_ITConfig(USART3, USART_IT_RXNE, ENABLE);

/* Enable USART3 DMA Rx and TX request */

USART_DMACmd(USART3, USART_DMAReq_Tx, ENABLE);

USART_DMACmd(USART3, USART_DMAReq_Rx, ENABLE);

USART_Cmd(USART3, ENABLE);

/* Enable DMA1 Channel4 */

DMA_Cmd(DMA1_Channel2, ENABLE);

DMA_Cmd(DMA1_Channel3, ENABLE);

}

© 著作权归作者所有

共有 人打赏支持
Ice99
粉丝 0
博文 2
码字总数 719
作品 0
美国
STM32F10x单片机Flash写操作导致中断不响应问题

昨天遇到一个问题,在写入数据到STM32F103单片机的Flash中时会出现串口中断接收数据丢失现象,但是我设置的串口接收中断优先级是最高的,并且没有哪里将全局中断关闭很长时间(除了操作系统部...

tq384998430
05/05
0
0
STM32串口接收不定长数据原理与源程序

转载:http://blog.csdn.net/u014515202/article/details/73293917 http://www.51hei.com/bbs/dpj-39885-1.html 方法1:串口接受数据,定时器来判断超时是否接受数据完成。 方法2:DMA接受+...

u013184273
2017/12/13
0
0
IAR ITM机制调试信息打印

打印调试信息几种途径: 1.串口打印: 将fputc映射到UART,通过USB-TLL转接板打印调试信息。 STM32F103官方提供的代码: /** * @brief Retargets the C library printf function to the USAR...

Jr小王子
2015/02/04
0
0
MQTT 移植STM32+GPRS(串口透传)(三)

昨天,去参观了AWE(中国家电及消费电子博览会),智能家居,智能插座、智能LED灯、智能摄像头、智能橱柜等等,大开眼界,原来这些别的公司的产品都正式投产了。还顺便打听了几家提供云服务的公...

qq_20251069
2017/03/18
0
0
使用arduino开发环境来开发普通单片机开发板

arduino开发板正常情况下是通过在代码中嵌入bootloader代码,利用单片机的IAP功能通过USB口来实现程序下载。其实通过合理的设置产生程序的hex或者bin文件然后用下载器下载到单片机里也可以实...

Okimbin
2014/02/12
0
0
【物联网智能网关-09】CAN总线通信演示(TinyGUI触屏)

CAN 是Controller Area Network 的缩写,ISO国际标准化的串行通信协议。最早应用在汽车上,在欧洲是汽车网络的标准协议,目前已经广泛应用在工业自动化、智能家居、船舶、纺织和医疗设备等领...

yefanqiu
2012/08/18
0
0
基于STM32F103的Max30100心率、血氧检测代码

MAX30100是能够读取心率、血氧的传感器,通信方式是通过IIC进行通信。其工作原理是通过红外led灯照射,能够得到心率的ADC值。 MAX30100的寄存器可以分为五类,状态寄存器、FIFO、控制寄存器、...

tichimi3375
03/24
0
0
STM32 + ucosii +文件系统 能不能加UBOOT方便程序的更新下载?

目前手里有一个项目,想用STM32F103的芯片作为主控芯片,上面跑 ucosii系统,并想在flash里面做一个小的文件系统用来存放数据。 目前的问题是这样的话,更新的软件客户不好下载升级,能不能在...

行者无疆在杭州
2013/09/12
2.4K
3
微控制器硬件板的微型操作系统--Cupkee

cupkee 是一个 C 语言编写的微型操作系统,它专门设计用于微控制器硬件板。 cupkee 建立了一个类似 node 的运行环境,在内部包含一个简化的 JavaScript 解释器作为 shell。 cupkee 为硬件板提...

cupkee
2016/12/09
460
0
ov7725采集图像通过stm32f103显示在LCD12864显示屏上

如何通过ov7725采集图像通过stm32f103显示在LCD128显示屏上

Sueng
05/13
0
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

c++ qt 组播总结

每个人都有不同的认知规律和习惯, 有的人喜欢搞一套严密的大理论, 论述起来滔滔不绝, 不管自己懂不懂, 反正读者/听者是没搞懂。 有的人喜欢从实践出发, 没看到代码, 不运行一下, 不看...

backtrackx
11分钟前
0
0
Sublime text2安装json格式化插件SublimePrettyJson[Windows]

一、下载SublimePrettyJson插件包 https://github.com/dzhibas/SublimePrettyJson 二、将下载的文件解压放到在package目录下面 C:\Users\lucky\AppData\Roaming\Sublime Text 3\Packages 每个......

lazy~
11分钟前
0
0
安装vue-cli 报4058错误

1. 4058是网络代理错误。 安装淘宝源修改一下就可以了: npm --registry https://registry.npm.taobao.org info underscore 改为cnpm执行: cnpm install --global vue-cli 安装成功: 试试版...

MrBoyce
13分钟前
0
0
CPU飙升分析

1、top -----看具体的进程 2、top -H -p pid ------该进程的线程 3、printf 0x%x 15248 ------将线程改为16进制 4、jstack 进程...

北极之北
15分钟前
1
0
新生代Eden与两个Survivor区的解释

聊聊JVM的年轻代 1.为什么会有年轻代 我们先来屡屡,为什么需要把堆分代?不分代不能完成他所做的事情么?其实不分代完全可以,分代的唯一理由就是优化GC性能。你先想想,如果没有分代,那我...

浮躁的码农
17分钟前
0
0
【JVM】JSTATD结合Java VisualVM进行远程监控JVM运行情况(二)

内存泄露指的是程序中动态分配内存给一些临时对象,但是对象不会被GC(java垃圾回收机制gabage collection)所回收,它始终占用内存。即被分配的对象很大但已无用; 内存溢出指的是程序运行过...

大白来袭
20分钟前
2
0
聊聊ribbon的超时时间设置

序 本文主要研究一下ribbon的超时时间设置 配置 实例 ribbon: ReadTimeout: 10000 ConnectTimeout: 10000 MaxAutoRetries: 0 MaxAutoRetriesNextServer: 1 eureka: enabled: ......

go4it
29分钟前
0
0
一行代码结果叹为观止,能做到这么极致的也只有python了

Python 这门语言非常的有趣,不仅可以做高大上的人工智能、大数据、机器学习。还可以用来做 Web、爬虫。还有其它很多的应用。今天我就给大家展示下一行 Python 代码都可以做些什么。 一行打印...

猫咪编程
32分钟前
2
0
KingShard使用

对于kingshard的功能,在git中可以看到明确的功能说明 主要功能: 1. 基础功能 支持SQL读写分离。 支持透明的MySQL连接池,不必每次新建连接。 支持平滑上线DB或下线DB,前端应用无感知。 支...

mickelfeng
34分钟前
0
0
Linux 下 查找某个字符串

如果你想在当前项目下 查找 "test" 这个字符串,可以这样: grep -rn "test" * * : 表示当前目录所有文件,也可以是某个文件名-r 是递归查找-n 是显示行号-R ...

nsns
34分钟前
0
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部