stm32f103串口使用DMA+FIFO
博客专区 > Ice99 的博客 > 博客详情
stm32f103串口使用DMA+FIFO
Ice99 发表于1年前
stm32f103串口使用DMA+FIFO
  • 发表于 1年前
  • 阅读 65
  • 收藏 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);

}

标签: stm32f103 uart dma
  • 打赏
  • 点赞
  • 收藏
  • 分享
共有 人打赏支持
粉丝 0
博文 2
码字总数 719
×
Ice99
如果觉得我的文章对您有用,请随意打赏。您的支持将鼓励我继续创作!
* 金额(元)
¥1 ¥5 ¥10 ¥20 其他金额
打赏人
留言
* 支付类型
微信扫码支付
打赏金额:
已支付成功
打赏金额: