stm32-HAL使用usart发送中断判断发送标志库问题
前言:
stm32是嵌入式MCU开发中最多应用的芯片,很早之前我们开发ST芯一般都是标准库开发,标准库简洁好读,现在要配合CubeMX生成代码,所以官方主推HAL库和LL库,但是HAL代码冗杂很绕,因为出来也不久,有些代码使用之后不是那么好用。
这次我就来分享两个实际使用过程中遇到的两个问题,一个是使用uart的发送中断进行数据发送产生的数组访问越界的问题。一个是stop模式下,dma相关的外设休眠唤醒需要注意重新初始化。
这篇是uart使用的介绍:
作者:良知犹存
转载授权以及围观:欢迎关注微信公众号:羽林君
或者添加作者个人微信:become_me
情节介绍:
串口是我们经常是用的一个外设,一般我们为了发送速度变快,会使用DMA或者中断发送接收。而CubeMX配置下,HAL调用了自己的一套函数 HAL_UART_IRQHandler 层层调用。
在官方提供的 stm32f4xx_hal_uart.c 文件中你可以看到如下函数:
void HAL_UART_IRQHandler(UART_HandleTypeDef *huart)
{
.....
/* UART in mode Transmitter ------------------------------------------------*/
if (((isrflags & USART_SR_TXE) != RESET) && ((cr1its & USART_CR1_TXEIE) != RESET))
{
UART_Transmit_IT(huart);
return;
}
......
}
其中在UART_Transmit_IT 函数中 有一段 函数为
if (--huart->TxXferCount == 0U)
{
/* Disable the UART Transmit Complete Interrupt */
__HAL_UART_DISABLE_IT(huart, UART_IT_TXE);
/* Enable the UART Transmit Complete Interrupt */
__HAL_UART_ENABLE_IT(huart, UART_IT_TC);
}
这里会把发送的 TxXferCount 的计数值自减,并判断是否为零。正常工作都没有问题,可是我们的设备实际使用过程中,上层的部分断电之后,会给底层通讯串口带了一个中断,这个时候继续减下去就会出现出现一个很大值,这个是因为 TxXferCount 是一个无符号的16位数据。
__IO uint16_t TxXferCount; /*!< UART Tx Transfer Counter */
debug看到如下数据,原因上文提到。就是我遇到我们Linux核心板掉电之后会产生一个中断,导致这里判断时候自动减一,TxXferCount从 0 变成 -1 因为是无符号数据,所以数据表现为65535。

在全局搜索TxXferCount调用,我们可以看到TxXferSize 是发送buf的长度数据
HAL_StatusTypeDef HAL_UART_Transmit_IT(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size)
{
/* Check that a Tx process is not already ongoing */
if (huart->gState == HAL_UART_STATE_READY)
{
if ((pData == NULL) || (Size == 0U))
{
return HAL_ERROR;
}
/* Process Locked */
__HAL_LOCK(huart);
huart->pTxBuffPtr = pData;
huart->TxXferSize = Size;
huart->TxXferCount = Size;
huart->ErrorCode = HAL_UART_ERROR_NONE;
huart->gState = HAL_UART_STATE_BUSY_TX;
/* Process Unlocked */
__HAL_UNLOCK(huart);
/* Enable the UART Transmit data register empty Interrupt */
__HAL_UART_ENABLE_IT(huart, UART_IT_TXE);
return HAL_OK;
}
else
{
return HAL_BUSY;
}
}
此外我们还会发现一处 huart->TxXferCount 计数 自减 使用。

此处的函数如下, 伴随着一个很大的 TxXferCount开始自减, pdata16bits开始自加。刚开始越界的时候由于该内存被初始化过,所以没有问题,该循环执行一会之后,程序就会进入hardfault。
HAL_StatusTypeDef HAL_UART_Transmit(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size, uint32_t Timeout)
{
......
huart->TxXferSize = Size;
huart->TxXferCount = Size;
while (huart->TxXferCount > 0U)
{
if (UART_WaitOnFlagUntilTimeout(huart, UART_FLAG_TXE, RESET, tickstart, Timeout) != HAL_OK)
{
return HAL_TIMEOUT;
}
if (pdata8bits == NULL)
{
huart->Instance->DR = (uint16_t)(*pdata16bits & 0x01FFU);
pdata16bits++;
}
else
{
huart->Instance->DR = (uint8_t)(*pdata8bits & 0xFFU);
pdata8bits++;
}
huart->TxXferCount--;
}
......
}
修改建议:
和硬件沟通过,他们的掉电机制,就是如此无法修改。所以我们进行软件的一些修改,因为会产生一个中断导致计数值自减,所以我们初步确认进行自减处进行限制,先增加一个零值判断。
huart->TxXferCount == 0U
又考虑到我们单包数据单次不会超过150byte,所以又加上150字节的控制。(此处的数据流控制大家可以按照自己实际使用的情况进行酌情使用)
huart->TxXferCount > 150U
原函数:
static HAL_StatusTypeDef UART_Transmit_IT(UART_HandleTypeDef *huart)
{
......
if (--huart->TxXferCount == 0U)
{
/* Disable the UART Transmit Complete Interrupt */
__HAL_UART_DISABLE_IT(huart, UART_IT_TXE);
/* Enable the UART Transmit Complete Interrupt */
__HAL_UART_ENABLE_IT(huart, UART_IT_TC);
}
......
}
改为:
static HAL_StatusTypeDef UART_Transmit_IT(UART_HandleTypeDef *huart)
{
......
if (huart->TxXferCount == 0U || --huart->TxXferCount == 0U || huart->TxXferCount > 150U )
{
/* Disable the UART Transmit Complete Interrupt */
__HAL_UART_DISABLE_IT(huart, UART_IT_TXE);
/* Enable the UART Transmit Complete Interrupt */
__HAL_UART_ENABLE_IT(huart, UART_IT_TC);
}
......
}
最后代码可以正常的使用。
结语
这就是我分享的项目中遇到一个st官方库使用的问题,如果大家有更好的想法和需求,也欢迎大家加我好友交流分享哈。
作者:良知犹存,白天努力工作,晚上原创公号号主。公众号内容除了技术还有些人生感悟,一个认真输出内容的职场老司机,也是一个技术之外丰富生活的人,摄影、音乐 and 篮球。关注我,与我一起同行。
‧‧‧‧‧‧‧‧‧‧‧‧‧‧‧‧ END ‧‧‧‧‧‧‧‧‧‧‧‧‧‧‧‧
推荐阅读
【3】CPU中的程序是怎么运行起来的 必读
本公众号全部原创干货已整理成一个目录,回复[ 资源 ]即可获得。
stm32-HAL使用usart发送中断判断发送标志库问题的更多相关文章
- A7139 无线通信驱动(STM32) 添加FIFO扩展模式,能够发送超大数据包
A7139 拥有电磁波唤醒以及10mW的发射功率,很easy实现长距离通信,眼下測试有障碍物能够轻松达到300m以上. 通过几天的调试,眼下能够发送随意大小的数据包,大小为1-16KB.所有使用中断收 ...
- STM32学习笔记——USART
STM32的USART组件支持异步.同步.单线半双工.多处理器.IrDA.LIN.SmartCard等模式,本文介绍的是异步即UART模式. 总线通信有三种模型:轮询.中断和DMA.DMA对我来说是陌 ...
- STM32 HAL库之串口详细篇
一.基础认识 (一) 并行通信 原理:数据的各个位同时传输 优点:速度快 缺点:占用引脚资源多,通常工作时有多条数据线进行数据传输 8bit数据传输典型连接图: 传输的数据是二进制:11101010, ...
- STM32 HAL库与标准库的区别_浅谈句柄、MSP函数、Callback函数
最近笔者开始学习STM32的HAL库,由于以前一直用标准库进行开发,于是发现了HAL库几点好玩的地方,在此分享. 1.句柄在STM32的标准库中,假设我们要初始化一个外设(这里以USART为例)我们首 ...
- STM32学习笔记——USART串口
转载自:http://www.cnblogs.com/microxiami/p/3752715.html 一.USART简介 通用同步异步收发器(USART)提供了一种灵活的方法与使用工业标准NRZ异 ...
- STM32学习笔记——USART串口(向原子哥和火哥学习)
一.USART简介 通用同步异步收发器(USART)提供了一种灵活的方法与使用工业标准NRZ异步串行数据格式的外部设备之间进行全双工数据交换.USART利用分数波特率发生器提供宽范围的波特率选择. S ...
- stm32 hal库串口通信资料汇集
串口的发送接收函数:HAL_UART_Transmit();串口轮询模式发送,使用超时管理机制.HAL_UART_Receive();串口轮询模式发送,使用超时管理机制.HAL_UART_Transm ...
- 【有趣的全彩LED | 编程】用STM32 HAL库让WS2812B为你所动
一.效果展示 观看演示效果:https://www.bilibili.com/video/BV1dv411Y7x3 使用STM32 HAL库编程 PWM+DMA控制输出,CubeMX生成初始工程 实现 ...
- 【情人节选帽子】TCS34725颜色传感器和Python图形界面编程(STM32 HAL库)
截图 描述: l STM32 HAL库编程 l 使用模拟IIC通信,方便程序移植 l Python界面编写,蘑菇头的帽子是什么颜色 l STM32 HAL库串口通信 l Python界面使用 ...
随机推荐
- mysql:刚刚知道的冷知识(一)
唯一索引的值可以null 1.创建一张user表,name字段指定为唯一索引 create table user( id int primary key auto_increment, name va ...
- 笔记本+ubuntu18.04 关闭触摸板touchpad
方法1: Settings -> Devices -> Mouse&Touchpad -> Touchpad OFF 方法2: 终端运行如下命令 touchpad off: ...
- MySQL日志系统bin log、redo log和undo log
MySQL日志系统bin log.redo log和undo log 今人不见古时月,今月曾经照古人. 简介:日志是MySQL数据库的重要组成部分,记录着数据库运行期间各种状态信息,主要包括错误日 ...
- Spring系列之事物是如何管理的
前言 我们都知道Spring给我们提供了很多抽象,比如我们在操作数据库的过程中,它为我们提供了事物方面的抽象,让我们可以非常方便的以事物方式操作数据库.不管你用JDBC.Mybatis.Hiberna ...
- cmd(命令行 )的命令
cmd是command的缩写.即命令行 CMD命令锦集 1. gpedit.msc-----组策略 2. sndrec32-------录音机 3. Nslookup-------IP地址侦测器 ,是 ...
- JS 根据文件路径获取名字和后缀名
var fileName = this.from.doc.substring(this.from.doc.lastIndexOf('/')+1); //文件名 var extNam ...
- Linux下查看哪个网口插了网线
场景: 一台服务器有多个网卡,一个网卡有多个网口,当插了一根网线的时候,不知道网线是插在哪一个网口. 1.查看网口信息 2.查看网口是否插了网线(命令ethtool) 命令:ethtool + 网口名 ...
- MySQL——MySQL用户管理
1.MySQL用户定义:用户名+主机域/ip/.. 2.用户作用: 1.登录 2.管理数据库及数据 3.权限: 读和写操作 4.角色: 数据库定义好的一组权限的定义 5.权限范围: 全库:*.* 单库 ...
- FastAPI(1)- 简单介绍
前言 为啥要学它呢,因为学 Flask 的时候发现有人更推荐它代替 Flask,看了下介绍,感觉很强,而且也能拿来做平台,当然学起来!卷起来! 为什么要使用 FastAPI ? 日渐没落的是后端 HT ...
- Element MenuNav刷新后点击菜单保留选中状态
正常情况刷新后选中菜单会失去选中的状态,需要把default-active 当前激活菜单的 index保存下来这样刷新后读取 methods方法中增加 getSess() { this.active ...