历史上的今天

今天是:2025年12月14日(星期日)

2022年12月14日 | STM32串口通信详解以及通信异常或者卡死常见问题分析

发布者:数字冲浪 来源: zhihu关键字:STM32  串口通信  通信异常  卡死 手机看文章 扫描二维码
随时随地手机看文章

异常一:数据传输中会出现乱码


数据传输中会出现乱码,很有可能是数组溢出,或者定义的数组长度不够。或者中断被打断。


异常二:程序卡在中断函数里面无法跳出执行主函数的逻辑


中断标志位没有被清除,在这里要注意一点,串口中断标志位自动清空的前提是软件需要先读USART_SR寄存器,然后读USART_DR寄存器来自动清除。即串口中断事件发生后,如果使能的接收中断,而中断函数里面什么都不执行的话,接收中断标志位是无法自动清空的,故而,函数会一直卡在中断函数里面。


比如一下这个函数,该函数没有逻辑问题,但会引发以上问题,代码如下


extern unsigned char star_time_led ;  //计时开始变量

unsigned char recv_flag = 0;//定义接受标志位

unsigned long recv_cnt = 0;//串口1接收数据缓存

unsigned char recv_buf[MAX_REV_NUM];//串口1接收数据缓存

extern unsigned char star_time;

extern unsigned char recv_time_cnt;

/*

以下写法有严重问题


如果没有这句函数→USART_ClearFlag(USART1,USART_FLAG_RXNE); //清空中断标志位


串口接收中断标志位将文法被清空,会导致函数卡在中断函数里面一直循环,无法正常运行主函数


原因分析:


中断条件成立后,中断标志位将会标记,程序将会进入中断函数运行,软件自动轻触中断标志位的条件是


先读USART_SR寄存器,再读USART_DR寄存器。


void USART1_IRQHandler(void)                //串口1中断服务程序

{

if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET)  //是否发送中断事件

{

star_time = 1;         //接受到一帧数据的时候,打开软件定时器,去计数

if(recv_cnt < MAX_REV_NUM)//数组长度是否超过缓存区

{

recv_buf[recv_cnt] =USART_ReceiveData(USART1);//将接收到的数据存在数组Usart1RecBuf[RxCounter]里

recv_cnt++;

}

else

{

recv_cnt = MAX_REV_NUM

;//限制数组长度,超过缓存区则不再接收

}

recv_time_cnt = 0; //每接收到一帧数据,把定时计数器清零,相当于喂狗

                   //但是在定时器中断里面会不断的累加

USART_ClearFlag(USART1,USART_FLAG_RXNE); //清空中断标志位

}

*/

上述代码优化后如下

void USART1_IRQHandler(void)                //串口1中断服务程序

{

static char ch;

if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET)  //是否发送中断事件

{

ch = USART_ReceiveData(USART1);//将接收到的数据存在数组Usart1RecBuf[RxCounter]里

star_time = 1;         //接受到一帧数据的时候,打开软件定时器,去计数

if(recv_cnt < MAX_REV_NUM)//数组长度是否超过缓存区

{

recv_buf[recv_cnt] =ch;//将接收到的数据存在数组Usart1RecBuf[RxCounter]里

recv_cnt++;

}

else

{

recv_cnt = MAX_REV_NUM

;//限制数组长度,超过缓存区则不再接收

}

recv_time_cnt = 0; //每接收到一帧数据,把定时计数器清零,相当于喂狗

                   //但是在定时器中断里面会不断的累加

USART_ClearFlag(USART1,USART_FLAG_RXNE); //清空中断标志位

}

异常三:数据发送中间歇性数据异常漏发乱发等

对于这些奇奇怪怪的问题,首先要了解一下发送函数是怎么发送的


USART_DR 包含了已发送的数据或者接收到的数据。USART_DR 实际是包含了两个寄存器,一个专门用于发送的可写 TDR,一个专门用于接收的可读 RDR。当进行发送操作时,往 USART_DR 写入数据会自动存储在 TDR 内;当进行读取操作时,向 USART_DR读取数据会自动提取 RDR 数据。


TDR 和 RDR 都是介于系统总线移位寄存器之间。串行通信是一个位一个位传输的,发送时把 TDR 内容转移到发送移位寄存器,然后把移位寄存器数据每一位发送出去,接收时把接收到的每一位顺序保存在接收移位寄存器内然后才转移到 RDR。


当 TDR 内容转移到发送移位寄存器,还没有发送出去的,就再次把TDR 内容转移到发送移位寄存器里,就会出现少发的现象。


什么时候会有这种情况呢?错误操作代码如下:


void USART2_IRQHandler(void)                //串口2中断服务程序

{

if(USART_GetITStatus(USART2, USART_IT_RXNE) != RESET)  //是否发送中断事件

{

Usart1RecBuf[RxCounter] =USART_ReceiveData(USART2);//将接收到的数据存在数组Usart1RecBuf[RxCounter]里

RxCounter++;//指向数组地址自加

if(RxCounter==2) 

USART_SendData(USART1, Usart1RecBuf[0]);//发送Usart1RecBuf[0]

                USART_SendData(USART1, Usart1RecBuf[1]);//发送Usart1RecBuf[1]

USART_SendData(USART1, Usart1RecBuf[2]);//发送Usart1RecBuf[2]

}

}

}


上述代码连续运行了3次USART_SendData(USART1, Usart1RecBuf);这个函数,这种情况一般都会出现只有最后一个数据发送成功出去。原因可能就是数据还没有发送出去,发送移位寄存器就更新了。


关键字:STM32  串口通信  通信异常  卡死 引用地址:STM32串口通信详解以及通信异常或者卡死常见问题分析

上一篇:基于STM32的六自由度机械臂控制与PID仿真
下一篇:原来STM32单片机的开发如此的简单

推荐阅读

人工智能的出现,摩尔定律的放缓,这些趋势正在影响全球范围内的每个人。作为行业的领导者, 赛灵思积极地拥抱这些趋势, 而且通过不断地突破自我,将赛灵思塑造成指数级变化的技术、商业模式和市场的推动者。为应对这种市场趋势,赛灵思推出了ACAP 平台。ACAP 平台加速AI 及其它所有主流应用的独特优势,将在广泛的产业领域加速中国十三五计划产业转...
网络分析仪是在四端口微波反射计(见驻波与反射测量)的基础上发展起来的。在60年代中期实现自动化,利用计算机按一定误差模型在每一频率点上修正由定向耦合器的定向性不完善、失配和窜漏等而引起的误差,从而使测量精确度大为提高,可达到计量室中最精密的测量线技术的测量精确度,而测量速度提高数十倍。原理一个任意多端口网络的各端口终端均匹配时,由...
工业机器人就是利用现代的电子科技和机械手脚关节制造出来的一种可以模仿人体动作,来从事一一些特殊危险场所工作的智能机器人。工业机器人是机器人应用中的一个分枝,与机器人一样,是一种可反复编程和多功能的用来搬运材料、零件、工具的操作工具。为了执行不同的任务而具有可改变可遍程序的动作的专门系统。工业机器人被广泛应用于电子、物流、化工等各...
2021年12月14日,致力于亚太地区市场的领先半导体元器件分销商---大联大控股宣布,其旗下世平推出基于恩智浦(NXP)S32K144、NJJ29C2、NCF29A1和NCK2912芯片的汽车无钥匙进入及启动系统解决方案。图示1-大联大世平基于NXP产品的PEPS无钥匙进入及启动系统方案的展示板图在各种技术的迭代下,汽车应用正在以超乎想象的速度进行创新。其中汽车无钥匙进入及启...

史海拾趣

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

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

厂商技术中心

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

 
机器人开发圈

电子工程世界版权所有 京ICP证060456号 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2026 EEWORLD.com.cn, Inc. All rights reserved