文档章节

stm32f103串口使用DMA+FIFO

Ice99
 Ice99
发布于 2017/01/04 09:16
字数 719
阅读 98
收藏 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
美国
私信 提问
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
STM32F10x单片机Flash写操作导致中断不响应问题

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

tq384998430
05/05
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

没有更多内容

加载失败,请刷新页面

加载更多

大数据教程(7.4)HDFS的java客户端API(流处理方式)

博主上一篇博客分享了namenode和datanode的工作原理,本章节将继前面的HDFS的java客户端简单API后深度讲述HDFS流处理API。 场景:博主前面的文章介绍过HDFS上存的大文件会成不同的块存储在不...

em_aaron
昨天
2
0
聊聊storm的window trigger

序 本文主要研究一下storm的window trigger WindowTridentProcessor.prepare storm-core-1.2.2-sources.jar!/org/apache/storm/trident/windowing/WindowTridentProcessor.java public v......

go4it
昨天
6
0
CentOS 生产环境配置

初始配置 对于一般配置来说,不需要安装 epel-release 仓库,本文主要在于希望跟随 RHEL 的配置流程,紧跟红帽公司对于服务器的配置说明。 # yum update 安装 centos-release-scl # yum ins...

clin003
昨天
9
0
GPON网络故障处理手册

导读 为了方便广大网络工作者工作需要,特搜集以下GPON网络处理流程供大家学习参考。开始—初步定为故障—检查光纤状况—检查ONU状态--检查设备运行状态—检查设备数据配置—检查上层设备状态...

问题终结者
昨天
9
0
MariaDB、Apache安装

11月12日任务 11.6 MariaDB安装 11.7/11.8/11.9 Apache安装 1.MariaDB安装 cd /usr/local/src wget https://downloads.mariadb.com/MariaDB/mariadb-10.2.6/bintar-linux-glibc_214-x86_64/......

hhpuppy
昨天
3
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部