温馨提示×

温馨提示×

您好,登录后才能下订单哦!

密码登录×
登录注册×
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》

stm32f103串口如何使用DMA+FIFO

发布时间:2022-01-05 19:16:58 来源:亿速云 阅读:716 作者:柒染 栏目:互联网科技

这篇文章给大家介绍stm32f103串口如何使用DMA+FIFO,内容非常详细,感兴趣的小伙伴们可以参考借鉴,希望对大家能有所帮助。

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串口如何使用DMA+FIFO就分享到这里了,希望以上内容可以对大家有一定的帮助,可以学到更多知识。如果觉得文章不错,可以把它分享出去让更多的人看到。

向AI问一下细节

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

AI