关于stm32串口不定长数据接收(hal库)的若干问题

发布者:xinyi9008最新更新时间:2018-12-10 来源: eefocus关键字:stm32  串口  数据接收 手机看文章 扫描二维码
随时随地手机看文章

使用串口空闲中断和DMA配合时出现的问题:


问题1.串口接收一旦溢出就会丢数据。

例如串口接收满了,稍等几秒再启动新的DMA接收函数HAL_UART_Receive_DMA时,就丢失数据了,而且是再也收不到串口数据。如果接满后马上启动就没这个问题。

看官方示例代码,停止DMA接收后似乎要DeInit后重新初始化Init和启动DMA接收


解答:


当接收DMA关闭后,此时串口还是激活的,若此时串口来数据,无法触发DMA传输,此时产生上溢错误(ORE),由于串口数据寄存器里的数据不能及时转移走,后面来的数据就进不来。一旦出现这种错误后,就不会再触发DMA请求,即使再开启DMA也不行。要恢复正常的话就只有Deinit后再重新初始化串口,或者直接将数据寄存器中的数据读走后,后面的数据才能正常进入,从而正常产生DMA请求,这个DMA请求是指硬件请求。

其实在STM32官网公众号有文章介绍了该问题,主要是先启动了串口再启动DMA就会容易引起该问题。因此为了防止该问题要不每次开DMA都清ORE寄存器;要不按规矩先开DMA再开串口,不用了先关串口再关DMA


2.接收不完全


空闲中断最大的一个问题,就是发送方的一帧数据不能被打断。不然stm32就会触发空闲中断,只接收到一帧的一部分数据。假如两个单片机通信,任意一个串口发送的过程被其他中断打断之后再回来继续发送就会导致帧被截断.


解答:


没有FIFO 无解

 

3.串口DMA接收不能单独停止。

例如串口同时在DMA发送和DMA接收,DMA接收到一半我要终止DMA的话,只能调用HAL_UART_DMAStop把接收DMA和串口DMA都停止。

换言之,不能单独停止DMA接收。

我理解的接收DMA和发送DMA是两个独立的操作,为什么不能单独停止?


解答:


HAL_UART_DMAStop()是同时关收发DMA,


只关闭接收的函数: HAL_UART_AbortReceive(); 该函数的两个工作内容:


1.先关闭接收DMA,HAL_DMA_Abort(huart->hdmarx);


2.置位RX ready状态,huart->RxState = HAL_UART_STATE_READY;

忽略了错误标志和IT标志处理,最保险的方式还是使用HAL_UART_AbortReceive()函数。

 

一种笨办法::直接利用stm32的RXNE和IDLE中断进行接收不定字节数据。 

基本知识: 

IDLE中断什么时候发生? 

IDLE就是串口收到一帧数据后,发生的中断。什么是一帧数据呢?比如说给单片机一次发来1个字节,或者一次发来8个字节,这些一次发来的数据,就称为一帧数据,也可以叫做一包数据。 

如何判断一帧数据结束,就是我们今天讨论的问题。因为很多项目中都要用到这个,因为只有接收到一帧数据以后,你才可以判断这次收了几个字节和每个字节的内容是否符合协议要求。 

看了前面IDLE中断的定义,你就会明白了,一帧数据结束后,就会产生IDLE中断。


如何配置好IDLE中断? 

下面我们就配置好串口IDLE中断吧。 


USART_CR


Bit4是 : IDLEIE      寄存器                 Bit5是: RXNEIE


对Bit4写1开启IDLE中断,对Bit5写1开启接收数据中断。(注意:不同系列的STM32,对应的寄存器位可能不同)


RXNE中断和IDLE中断的区别? 

当接收到1个字节,就会产生RXNE中断,当接收到一帧数据,就会产生IDLE中断。比如给单片机一次性发送了8个字节,就会产生8次RXNE中断,1次IDLE中断。 


USART_ISR 状态寄存器


Bit4是 : IDLE      寄存器                 Bit5是: RXNE


这是状态寄存器,当串口接收到数据时,bit5就会自动变成1,当接收完一帧数据后,bit4就会变成1. 

需要注意的是,在中断函数里面,需要把对应的位清0,否则会影响下一次数据的接收。


比如RXNE接收数据中断,只要把接收到的一个字节读出来,就会清除这个中断。


IDLE中断,如何是F0系列的单片机,需要用ICR寄存器来清除,如果是F1系列的单片机,清除方法是“先读SR寄存器,再读DR寄存器”。


串口初始化中开启两个中断:


USART_ITConfig(USART1, USART_IT_IDLE, ENABLE);


USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);


中断处理函数如下:


  

当然你也可以先不管各种问题,调试通了再说。


按照以下教程即可正常收发:

https://blog.csdn.net/xukao5671927/article/details/78605022


中断里的
//HAL_UART_DMAStop(&huart2);


更改为:

HAL_UART_AbortReceive(&huart2);


即可修复收取数据的时候关闭了DMA导致不能发送得问题。


关键字:stm32  串口  数据接收 引用地址:关于stm32串口不定长数据接收(hal库)的若干问题

上一篇:STM32F系列USART的IDLE中断要注意了
下一篇:STM32F103RCT6+串口DMA方式接收定长数据

推荐阅读最新更新时间:2024-03-16 16:19

STM32的精确延时
/*---------------------------------------------------------- 文件名称:systick.c 文件描述:sysTick 系统滴答时钟1us中断函数库,中断时间可自由配置 备注:程序默认使用72M时钟,无分频 -----------------------------------------------------------------*/ #include delay.h static __IO u32 TimingDelay; /*---------------------------------------------------------------------
[单片机]
一步步写STM32 OS【三】PendSV与堆栈操作
一、什么是PendSV PendSV是可悬起异常,如果我们把它配置最低优先级,那么如果同时有多个异常被触发,它会在其他异常执行完毕后再执行,而且任何异常都可以中断它。更详细的内容在《Cortex-M3 权威指南》里有介绍,下面我摘抄了一段。 OS 可以利用它“缓期执行”一个异常——直到其它重要的任务完成后才执行动 作。悬起 PendSV 的方法是:手工往 NVIC的 PendSV悬起寄存器中写 1。悬起后,如果优先级不够 高,则将缓期等待执行。 PendSV的典型使用场合是在上下文切换时(在不同任务之间切换)。例如,一个系统中有两个就绪的任务,上下文切换被触发的场合可以是: 1、执行一个系统调用 2、系统滴答定时器(S
[单片机]
一步步写<font color='red'>STM32</font> OS【三】PendSV与堆栈操作
STM32开发笔记76: 初始化RTC后死机的原因
项目开发中只要初始化RTC,则系统死机。其初始化步骤可参考日志:STM32开发笔记44:RTC驱动程序的移植。按照日志STM32开发笔记75: 使用STM32CubeMX点亮一个LED使用STM32CubeMX直接生成程序则运行正常。 分析原因在于,少移植了2个函数:HAL_RTC_MspInit和HAL_RTC_MspDeInit。这两个函数的实现非常简单,可以靠STM32CubeMX直接生成。 void HAL_RTC_MspInit(RTC_HandleTypeDef *hrtc) { __HAL_RCC_RTC_ENABLE(); HAL_NVIC_SetPriority(RTC_IRQn, 0x0, 0)
[单片机]
STM32 Boot模式设置方法
1、模式设置 Boot模式设实际指的就是选择启动的起始地址区域,在STM32F20x和STM32F21x中存在以下三种模式可供选择,分别为片内Flash、系统内存、片内SRAM: 2、BOOT Pin值确认 BOOT引脚值在系统复位的4个系统时钟周期后被锁存,同时BOOT1引脚实际与GPIO引脚共享一外部接口,在4个系统时钟周期后则会被释放可作为GPIO使用。 BOOT引脚值会在待机模式后被重新检测,在待机模式中BOOT引脚状态要保持正确 3、ST Embedded Bootloader 在System Memory中预置了bootloader用于对片内Flash进行IAP, 其使用如下接口: -USART1 -US
[单片机]
STM32单片机串口空闲中断接收不定长数据
在使用单片机的串口通信功能时,常用的接收数据方法是通过固定的字节数来判断一帧数是否发送完成,或者是通过固定的结束标志位来表示一帧数据发送完成。但是有时候会遇到发送的数据长度不固定,也没有固定的结束标志,对于这样的数据通常的做法是每隔一段时间查看一下接收数据的长度是否发生了变化,如果指定的一段时间内接收数据长度没有发生变化,就认为是一帧数据发送完成。在STM32单片机中串口提供了一个更好用的功能,就是空闲中断功能。也就是说当一帧数据发送结束后,就会产生一个空闲中断。这样就可以利用这个空闲中断来判断一帧数据接收是否完成。 关于串口空闲检测可以在STM32参考手册上找到相关介绍 通过这个图可以看出来,当第一组数据Data1、Da
[单片机]
<font color='red'>STM32</font>单片机<font color='red'>串口</font>空闲中断<font color='red'>接收</font>不定长<font color='red'>数据</font>
stm32 pwm 呼吸灯
#include main.h #include stm32f0xx_hal.h /* USER CODE BEGIN Includes */ int i=0; /* USER CODE END Includes */ /* Private variables ---------------------------------------------------------*/ TIM_HandleTypeDef htim3; UART_HandleTypeDef huart1; /* USER CODE BEGIN PV */ /* Private variables --------------------
[单片机]
<font color='red'>stm32</font> pwm 呼吸灯
STM32系列第26篇--电容触摸屏
触摸屏分类: 电阻式:定位准确,单点触摸 电容感应式:电容感应式:支持多点触摸,价格偏贵。工业应用最广泛 红外线式:价格低廉,但其外框易碎,容易产生光干扰,曲面情况下失真 表面声波式:解决各种缺点,但是屏幕表面如果有水滴和尘土会使触摸屏变的迟钝 注:触摸屏本质上与液晶是分离的,触摸屏负责的是检测触摸点,液晶屏负责的是显示。区别开来;电容触摸屏一般都需要一个驱动IC来检测电容触摸,且一般是通过IIC接口输出触摸数据的。 常见的驱动IC: GT9147:采用17*10的驱动结构(10个感应通道,17个驱动通道) OTT2001A:采用13*8的驱动结构(8个感应通道,13个驱动通道) 注:它们与MCU连接通过4根线:
[单片机]
<font color='red'>STM32</font>系列第26篇--电容触摸屏
基于STM32串口通信的实例分析
串口是串行接口(serial port)的简称,也称为串行通信接口或COM接口。串口通信是指采用串行通信协议(serial communication)在一条信号线上将数据一个比特一个比特地逐位进行传输的通信模式。串口按电气标准及协议来划分,包括RS-232-C、RS-422、RS485等。 在串行通信中,数据在1位宽的单条线路上进行传输,一个字节的数据要分为8次,由低位到高位按顺序一位一位的进行传送。串行通信的数据是逐位传输的,发送方发送的每一位都具有固定的时间间隔,这就要求接收方也要按照发送方同样的时间间隔来接收每一位。不仅如此,接收方还必须能够确定一个信息组的开始和结束。 常用的两种基本串行通信方式包括同步通信和异步通信
[单片机]
基于<font color='red'>STM32</font>中<font color='red'>串口</font>通信的实例分析
小广播
添点儿料...
无论热点新闻、行业分析、技术干货……
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件
随便看看
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved