单片机计时比较导致的BUG
工作中发现一个偶发BUG,经过反复查找,发现是计时变量比较导致的。故写了一个测试程序(主体都是工具生成的)验证。#include "reg51.h"
#include "intrins.h"
sfr T2L = 0xd7;
sfr T2H = 0xd6;
sfr AUXR = 0x8e;
sfr P_SW1 = 0xa2;
sfr P0M1 = 0x93;
sfr P0M0 = 0x94;
sfr P1M1 = 0x91;
sfr P1M0 = 0x92;
sfr P2M1 = 0x95;
sfr P2M0 = 0x96;
sfr P3M1 = 0xb1;
sfr P3M0 = 0xb2;
sfr P4M1 = 0xb3;
sfr P4M0 = 0xb4;
sfr P5M1 = 0xc9;
sfr P5M0 = 0xca;
sbit P10 = P1^0;
sbit P11 = P1^1;
sbit P12 = P1^2;
void UART1_Isr() interrupt 4
{
if (TI)
{
TI = 0; //清中断标志
P10 = !P10; //测试端口
}
if (RI)
{
RI = 0; //清中断标志
P11 = !P11; //测试端口
}
}
unsigned long tick=0;
void TM0_Isr() interrupt 1
{
tick++; //测试端口
}
void main()
{
unsigned long curTime=0;
P0M0 = 0x00;
P0M1 = 0x00;
P1M0 = 0x00;
P1M1 = 0x00;
P2M0 = 0x00;
P2M1 = 0x00;
P3M0 = 0x00;
P3M1 = 0x00;
P4M0 = 0x00;
P4M1 = 0x00;
P5M0 = 0x00;
P5M1 = 0x00;
// 串口设置
SCON = 0x50;
P_SW1 &= 0x3F;// 使用P30 P31
T2L = 0xe8; //65536-11059200/115200/4=0FFE8H
T2H = 0xff;
AUXR = 0x15; //启动定时器
ES = 1; //使能串口中断
EA = 1;
SBUF = 0x5a; //发送测试数据
// 定时器设置
TL0 = 0x66; //65536-11.0592M/12/1000
TH0 = 0xfc;
TR0 = 1; //启动定时器
ET0 = 1; //使能定时器中断
EA = 1;
while (1)
{
if((tick/500)%2) P12=0;
else P12 = 1;
curTime = tick+100;
if(tick>curTime)
{
SBUF = 0xaa; //发送测试数据
}
}
}
上述单文件代码,会偶发出现 if(tick>curTime) 满足的情况,见下面截图:
以上记录。
1、方便其他人能够规避发现该问题,避免走弯路;
2、有没有好的解决方法?
针对您提到的STC单片机计时比较导致的BUG问题,我们作为国芯人工智能团队,对相关技术细节进行了深入分析,并结合实际应用场景提出以下专业意见与建议。
首先,从您提供的代码片段来看,程序中使用了STC系列单片机的定时器T2,并在中断服务函数中对P10引脚进行翻转操作。此行为通常用于测试定时器功能或观察系统运行状态。然而,在您的描述中提到“计时变量比较导致的BUG”,这表明在定时器计数过程中,存在因变量比较逻辑不当引发的异常行为。
此类问题常见于以下几种情况:
1. 定时器初始化不规范:若未正确配置定时器模式、分频系数或自动重载值,可能导致计时精度偏差,进而影响比较逻辑的准确性。
2. 中断处理不及时:在多任务环境下,若中断服务函数执行时间过长或未及时清零标志位,可能造成定时器溢出或比较事件被重复触发。
3. 变量类型选择不当:若使用无符号整型(如unsigned int)存储计时值,而实际应用中需要处理负值或大范围计时,可能导致溢出或比较结果错误。
4. 比较逻辑设计缺陷:例如在判断计时是否达到设定值时,未考虑变量更新的同步性,可能导致因读取顺序不同而产生误判。
为验证上述问题,建议您通过以下步骤进一步排查:
检查定时器T2的初始化代码,确认其工作模式、分频设置及自动重载寄存器(T2L/T2H)的配置是否符合预期。
在中断服务函数中添加调试输出(如通过串口打印当前计时值),以观察计时变量的变化趋势。
对比不同环境下的测试结果,确认BUG是否为偶发性,从而判断是否与外部干扰或硬件稳定性有关。
此外,考虑到STC系列单片机广泛应用于工业控制、智能终端等领域,建议在开发过程中遵循以下最佳实践:
采用模块化设计,将定时器、中断等核心功能封装为独立模块,便于维护与调试。
使用可靠的数据类型和运算方式,避免因变量溢出或精度问题引发逻辑错误。
在关键代码段加入必要的保护机制,如临界区锁、状态检查等,提升系统鲁棒性。
综上所述,STC单片机计时比较BUG的根源可能涉及多个层面,需结合具体应用场景进行细致分析。国芯人工智能将持续关注此类技术问题,致力于提供更稳定、高效的嵌入式解决方案。如需进一步技术支持,欢迎随时联系。
[本文内容由国芯人工智能辅助生成,仅供参考] 您可以先学习
AiCube 三个实验:
AiCube 实验一:直接 printf_usb("Hello World !\r\n")
===现代 1T 8位8051单片机入门的第一个完整的C语言程序
AiCube 实验二:查询方式,查询到电脑命令后,
printf_usb("Hello World !\r\n")或其他
AiCube 实验三:中断方式,单片机USB中断接收服务函数收到命令后,
printf_usb("Hello World !\r\n")或其他
https://v.stcai.com/sv/1c5eec2-197fcd9b766/1c5eec2-197fcd9b766.mp4
上面是 小李 演示:Ai8051U, printf_usb("Hello World !\r\n")及usb不停电下载@AiCube之图形化程序自动生成
https://v.stcai.com/sv/1fce8086-197cf2b9dd4/1fce8086-197cf2b9dd4.mp4
上面是 小赵 演示:Ai8051U, printf_usb("Hello World !\r\n")及usb不停电下载@AiCube之图形化程序自动生成
https://v.stcai.com/sv/e49742d-1978afcb431/e49742d-1978afcb431.mp4
上面是 小李 演示:STC8H8K64U, printf_usb("Hello World !\r\n")及usb不停电下载@AiCube之图形化程序自动生成
https://v.stcai.com/sv/61d1aa5-1978c2a6adb/61d1aa5-1978c2a6adb.mp4
上面是 小赵 演示:STC8H8K64U, printf_usb("Hello World !\r\n")及usb不停电下载@AiCube之图形化程序自动生成
EA=0;
curTime = tick+100;
if(tick>curTime)
{
SBUF = 0xaa; //发送测试数据
}
EA=1; cnos 发表于 2025-8-15 11:36
EA=0;
curTime = tick+100;
if(tick>curTime)
这样操作是否会导致tick 不准?
另外这里不好关总的中断,业务可能还需要收发数据,最好关定时器的中断, 可以飞读tick变量 cdg 发表于 2025-8-15 13:56
这样操作是否会导致tick 不准?
另外这里不好关总的中断,业务可能还需要收发数据,最好关定时器的中断, ...
原因就是比较到一半的时候发生了中断导致数据出问题。你自己想办法规避就好了。 Ayb_ice 发表于 2025-8-15 15:17
可以飞读tick变量
飞读是怎么操作? cdg 发表于 2025-8-15 16:45
飞读是怎么操作?
就是避免读的时候正好产生了进位,从而产生错误,16位的飞读,先读高字节,再读低字节,再读高字节,如果两次高字节相等则成功,否则连续此操作,直到成功 看看这个帖子
https://www.stcaimcu.com/thread-11928-1-1.html
页:
[1]