历史上的今天
返回首页

历史上的今天

今天是:2024年10月09日(星期三)

正在发生

2020年10月09日 | STM32的串口采用DMA方式接收数据测试

2020-10-09 来源:eefocus

环境:


主机:WINXP


开发环境:MDK4.23


MCU:STM32F103CBT6




说明:


串口可以配置成用DMA的方式接收数据,不过DMA需要定长才能产生接收中断,如何接收可变长度的数据呢?


方法有以下3种:


1.将RX脚与一路时钟外部引脚相连,当串口一帧发完,即可利用此定时器产生超时中断.这个实时性较高,可以做到1个字节实时监测.


2.不改变硬件,开启一个定时器监控DMA接收,如果超时则产生中断.这个实时性不高,因为超时时间必须要大于需要接收帧的时间,精度不好控制.


3.STM32单片机有的串口可以监测总线是否处于空闲,如果空闲则产生中断.可以用它来监测DMA接收是否完毕.这种方式实时性很高.


本文采用第3种方式.在波特率576000下大数据包冲击证明可行.




源代码:



//串口接收DMA缓存

#define UART_RX_LEN 128

extern uint8_t Uart_Rx[UART_RX_LEN];


//串口接收DMA缓存

uint8_t Uart_Rx[UART_RX_LEN] = {0};


//---------------------串口功能配置---------------------

//打开串口对应的外设时钟  

    RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1 , ENABLE); 

//串口发DMA配置  

//启动DMA时钟

    RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);

//DMA发送中断设置

NVIC_InitStructure.NVIC_IRQChannel = DMA1_Channel4_IRQn;

NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 3;

NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2;

NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;

NVIC_Init(&NVIC_InitStructure);

//DMA1通道4配置

DMA_DeInit(DMA1_Channel4);

//外设地址

DMA_InitStructure.DMA_PeripheralBaseAddr = (u32)(&USART1->DR);

//内存地址

DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)Uart_Send_Buffer;

//dma传输方向单向

DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST;

//设置DMA在传输时缓冲区的长度

DMA_InitStructure.DMA_BufferSize = 100;

//设置DMA的外设递增模式,一个外设

DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;

//设置DMA的内存递增模式

DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;

//外设数据字长

DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;

//内存数据字长

DMA_InitStructure.DMA_MemoryDataSize = DMA_PeripheralDataSize_Byte;

//设置DMA的传输模式

DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;

//设置DMA的优先级别

DMA_InitStructure.DMA_Priority = DMA_Priority_High;

//设置DMA的2个memory中的变量互相访问

DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;

DMA_Init(DMA1_Channel4,&DMA_InitStructure);

DMA_ITConfig(DMA1_Channel4,DMA_IT_TC,ENABLE);

//使能通道4

//DMA_Cmd(DMA1_Channel4, ENABLE);

 

//串口收DMA配置  

//启动DMA时钟

    RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);

//DMA1通道5配置

DMA_DeInit(DMA1_Channel5);

//外设地址

DMA_InitStructure.DMA_PeripheralBaseAddr = (u32)(&USART1->DR);

//内存地址

DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)Uart_Rx;

//dma传输方向单向

DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;

//设置DMA在传输时缓冲区的长度

DMA_InitStructure.DMA_BufferSize = UART_RX_LEN;

//设置DMA的外设递增模式,一个外设

DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;

//设置DMA的内存递增模式

DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;

//外设数据字长

DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;

//内存数据字长

DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;

//设置DMA的传输模式

DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;

//设置DMA的优先级别

DMA_InitStructure.DMA_Priority = DMA_Priority_VeryHigh;

//设置DMA的2个memory中的变量互相访问

DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;

DMA_Init(DMA1_Channel5,&DMA_InitStructure);

 

//使能通道5

DMA_Cmd(DMA1_Channel5,ENABLE);

  

    //初始化参数  

    //USART_InitStructure.USART_BaudRate = DEFAULT_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_InitStructure.USART_BaudRate = DEFAULT_BAUD; 

//初始化串口 

    USART_Init(USART1,&USART_InitStructure);  

    //TXE发送中断,TC传输完成中断,RXNE接收中断,PE奇偶错误中断,可以是多个   

    //USART_ITConfig(USART1,USART_IT_RXNE,ENABLE);

//中断配置

USART_ITConfig(USART1,USART_IT_TC,DISABLE);

USART_ITConfig(USART1,USART_IT_RXNE,DISABLE);

USART_ITConfig(USART1,USART_IT_IDLE,ENABLE);  

 

//配置UART1中断  

NVIC_PriorityGroupConfig(NVIC_PriorityGroup_3);

    NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;               //通道设置为串口1中断  

    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;       //中断占先等级0  

    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;              //中断响应优先级0  

    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;                 //打开中断  

    NVIC_Init(&NVIC_InitStructure);   

        

//采用DMA方式发送

USART_DMACmd(USART1,USART_DMAReq_Tx,ENABLE);

//采用DMA方式接收

USART_DMACmd(USART1,USART_DMAReq_Rx,ENABLE);

    //启动串口  

    USART_Cmd(USART1, ENABLE); 


//串口1接收中断   

void USART1_IRQHandler(void)                               

{   

uint32_t temp = 0;

uint16_t i = 0;

if(USART_GetITStatus(USART1, USART_IT_IDLE) != RESET)

    {

    //USART_ClearFlag(USART1,USART_IT_IDLE);

    temp = USART1->SR;

    temp = USART1->DR; //清USART_IT_IDLE标志

    DMA_Cmd(DMA1_Channel5,DISABLE);

 

temp = UART_RX_LEN - DMA_GetCurrDataCounter(DMA1_Channel5);

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

{

Data_Receive_Usart = Uart_Rx[i];

  //启动串口状态机

usart_state_run(); 

}

 

//设置传输数据长度

DMA_SetCurrDataCounter(DMA1_Channel5,UART_RX_LEN);

    //打开DMA

DMA_Cmd(DMA1_Channel5,ENABLE);

    } 

__nop(); 


测试结果:


条件:单片机运行于72M,与PC通信速率为460800.PC每隔100ms发送一个9个字节的包:c5 5c 6 0 6F 10 5 4e f7.


测试:单片机每次收到此包,一个IO作电平跳转,然后处理返回一包.


示波器显示:

放大显示:

推荐阅读

史海拾趣

Datapro International Inc公司的发展小趣事

随着全球化的加速和市场竞争的加剧,Datapro International Inc公司开始加快国际化发展的步伐。他们积极拓展海外市场,并在全球范围内建立了完善的销售和服务网络。

在国际化发展的过程中,Datapro International Inc公司遇到了许多挑战和困难。然而,他们凭借坚定的信念和不懈的努力,成功克服了这些困难。他们深入了解当地市场和文化背景,并根据市场需求和客户需求不断调整产品和服务策略。这些努力使得Datapro International Inc公司在海外市场取得了显著的成果。

EPIC公司的发展小趣事

1998年,Epic Games发布了一款名为“虚幻”的3D第一人称射击游戏。这款游戏不仅游戏内容新颖,更引人注目的是它背后完全自主开发的3D游戏引擎。这个引擎后来被称为“虚幻引擎”,并成为了Epic Games的核心技术之一。随着游戏的成功,虚幻引擎也逐渐受到了业界的关注。许多其他游戏开发商开始采用这款引擎来开发自己的游戏,从而使得Epic Games在游戏引擎领域取得了显著的商业成功。

佰宏(BHFUSE)公司的发展小趣事

佰宏公司始终坚持开放合作的理念,与多家知名企业建立了战略合作伙伴关系。例如,与立讯精密、奋达科技等实力企业的合作,不仅为佰宏带来了更多的业务机会,也进一步提升了公司的品牌影响力和市场地位。这些合作不仅带来了经济效益,更为佰宏的长远发展奠定了坚实的基础。

Conflux公司的发展小趣事

Conflux深知人才是企业发展的核心动力。因此,公司一直注重人才培养和引进。通过与高校和研究机构的合作,Conflux吸引了大量优秀的科研人才加入公司。同时,公司还建立了完善的培训体系,不断提升员工的技能和素质。这些措施为公司的持续创新和发展提供了坚实的人才保障,也构筑了公司的核心竞争力。

Crocus Technology公司的发展小趣事

经过多年的发展,Crocus Technology已经在电子行业树立了良好的口碑和品牌形象。公司的产品在汽车、工业等多个领域得到了广泛应用,并帮助客户实现了产品性能的提升和成本的降低。展望未来,Crocus Technology将继续致力于技术创新和市场拓展,为电子行业的发展贡献更多的力量。

请注意,以上故事是基于现有信息和常识构建的,可能并不完全反映Crocus Technology公司发展的全部细节和真实情况。如需了解更多关于Crocus Technology的故事和发展历程,建议查阅公司官方发布的资料或相关新闻报道。

GREATECS公司的发展小趣事

经过多年的发展,Crocus Technology已经在电子行业树立了良好的口碑和品牌形象。公司的产品在汽车、工业等多个领域得到了广泛应用,并帮助客户实现了产品性能的提升和成本的降低。展望未来,Crocus Technology将继续致力于技术创新和市场拓展,为电子行业的发展贡献更多的力量。

请注意,以上故事是基于现有信息和常识构建的,可能并不完全反映Crocus Technology公司发展的全部细节和真实情况。如需了解更多关于Crocus Technology的故事和发展历程,建议查阅公司官方发布的资料或相关新闻报道。

问答坊 | AI 解惑

电赛时候键盘的设计

本帖最后由 paulhyde 于 2014-9-15 09:25 编辑 正好找资料,看到了自己电设时的一个论文,觉得这个键盘的设计还是很满意的。 一般大家在设计键盘的时候,使用4*4矩阵来摆放16个按键,如果改变下位置,也许考官会有比较好的印象分。同样的,其他地 ...…

查看全部问答>

LED背光技术需要解决技术难点分析

replyreload += \',\' + 371471;Timson,如果您要查看本帖隐藏内容请回复…

查看全部问答>

做Wince 开发在深圳的工资如何?

我做Wince 的车载软件有半年多了,工资一般!想问一下在深圳做Wince 开发的前景如何?希望大牛门说说自己的看法~…

查看全部问答>

Window mobile Recorder

在手机上开发了一个录音机程序,但在正在录音过程中来电时,录音自动停止,可是写文件出现了错误(WriteFile函数中参数出错)。请问怎么怎样才能解决?谢谢。…

查看全部问答>

VS2005如何编AT&T汇编

小弟最近在用VS2005为ARM11做个东西,具体是在移植一个以前基与GCC的东西,C代码部分比较好改,但汇编部分就不行了,那是 AT&T的汇编,不知道怎样才能将VS2005和Gcc进行混合编译。(目标是在VS2005下,我可以指定一些文件用GCC编) cygwin我下了 ...…

查看全部问答>

关于WINCE上的SKYPE给小弟一点帮助呀

是这样的,我想在windows ce上的运行SKYPE程序?哪位兄弟有没有移植好的EXE文件,或者源码呀,能不能给我一份呀?小弟不胜感谢!我的邮箱是sunboyljp@163.com…

查看全部问答>

总结各电平标准,搞硬件的必须知道的东西

搞硬件的必须知道的东西 新加电平耦合资料,也是必须知道的,是关于LVPECL, VML, CML, and LVDS Levels.PDF [ 本帖最后由 ming1005 于 2010-9-26 09:46 编辑 ]…

查看全部问答>

沥血之作,32位单精度浮点除法器

沥血之作,32位单精度浮点除法器 历经一年开发,沥血之作--32位单精度浮点除法器,寻IC厂商合作或**出售,欢迎评估和咨询。联系方式:短消息留言32位单精度浮点除法器遵循浮点规范:IEEE-754算法:R8并行运算,每次迭代计算产生3位商,8拍完成迭 ...…

查看全部问答>

关于altera编译的warning,求助

今天编译工程发现以下warning,找了很久也没有解决方法,不知道有人遇到吗? ①Warning: Some pins have incomplete I/O assignments. Refer to the I/O Assignment Warnings report for details 这个我查了报告说是:missingdrive strength and ...…

查看全部问答>