找回密码
 立即注册
查看: 105|回复: 9

单片机计时比较导致的BUG

[复制链接]
  • 打卡等级:初来乍到
  • 打卡总天数:3
  • 最近打卡:2025-08-15 09:54:35
已绑定手机

2

主题

12

回帖

46

积分

新手上路

积分
46
发表于 2025-8-15 09:54:35 | 显示全部楼层 |阅读模式
工作中发现一个偶发BUG,经过反复查找,发现是计时变量比较导致的。故写了一个测试程序(主体都是工具生成的)验证。

  1. #include "reg51.h"
  2. #include "intrins.h"
  3. sfr     T2L     =   0xd7;
  4. sfr     T2H     =   0xd6;
  5. sfr     AUXR    =   0x8e;
  6. sfr                        P_SW1                =         0xa2;
  7. sfr     P0M1    =   0x93;
  8. sfr     P0M0    =   0x94;
  9. sfr     P1M1    =   0x91;
  10. sfr     P1M0    =   0x92;
  11. sfr     P2M1    =   0x95;
  12. sfr     P2M0    =   0x96;
  13. sfr     P3M1    =   0xb1;
  14. sfr     P3M0    =   0xb2;
  15. sfr     P4M1    =   0xb3;
  16. sfr     P4M0    =   0xb4;
  17. sfr     P5M1    =   0xc9;
  18. sfr     P5M0    =   0xca;
  19. sbit    P10     =   P1^0;
  20. sbit    P11     =   P1^1;
  21. sbit    P12     =   P1^2;
  22. void UART1_Isr() interrupt 4
  23. {
  24.     if (TI)
  25.     {
  26.         TI = 0;                                 //清中断标志
  27.         P10 = !P10;                             //测试端口
  28.     }
  29.     if (RI)
  30.     {
  31.         RI = 0;                                 //清中断标志
  32.         P11 = !P11;                             //测试端口
  33.     }
  34. }
  35. unsigned long tick=0;
  36. void TM0_Isr() interrupt 1
  37. {
  38.     tick++;                                //测试端口
  39. }
  40. void main()
  41. {
  42.         unsigned long curTime=0;
  43.     P0M0 = 0x00;
  44.     P0M1 = 0x00;
  45.     P1M0 = 0x00;
  46.     P1M1 = 0x00;
  47.     P2M0 = 0x00;
  48.     P2M1 = 0x00;
  49.     P3M0 = 0x00;
  50.     P3M1 = 0x00;
  51.     P4M0 = 0x00;
  52.     P4M1 = 0x00;
  53.     P5M0 = 0x00;
  54.     P5M1 = 0x00;
  55.         // 串口设置
  56.     SCON = 0x50;
  57.                 P_SW1 &= 0x3F;// 使用P30 P31
  58.     T2L = 0xe8;                                 //65536-11059200/115200/4=0FFE8H
  59.     T2H = 0xff;
  60.     AUXR = 0x15;                                //启动定时器
  61.     ES = 1;                                     //使能串口中断
  62.     EA = 1;
  63.     SBUF = 0x5a;                                //发送测试数据
  64. // 定时器设置
  65.     TL0 = 0x66;                                 //65536-11.0592M/12/1000
  66.     TH0 = 0xfc;
  67.     TR0 = 1;                                    //启动定时器
  68.     ET0 = 1;                                    //使能定时器中断
  69.     EA = 1;
  70.                
  71.     while (1)
  72.                 {
  73.                         if((tick/500)%2) P12=0;
  74.                         else P12 = 1;
  75.                         curTime = tick+100;
  76.                         if(tick>curTime)
  77.                         {
  78.                                 SBUF = 0xaa;                                //发送测试数据
  79.                         }
  80.                 }
  81. }
复制代码


上述单文件代码,会偶发出现 if(tick>curTime) 满足的情况,见下面截图:
截图202508150948571200.jpg


以上记录。
1、方便其他人能够规避发现该问题,避免走弯路;
2、有没有好的解决方法?
回复

使用道具 举报 送花

3

主题

2031

回帖

910

积分

等待验证会员

积分
910
发表于 2025-8-15 09:58:00 | 显示全部楼层
针对您提到的STC单片机计时比较导致的BUG问题,我们作为国芯人工智能团队,对相关技术细节进行了深入分析,并结合实际应用场景提出以下专业意见与建议。

首先,从您提供的代码片段来看,程序中使用了STC系列单片机的定时器T2,并在中断服务函数中对P10引脚进行翻转操作。此行为通常用于测试定时器功能或观察系统运行状态。然而,在您的描述中提到“计时变量比较导致的BUG”,这表明在定时器计数过程中,存在因变量比较逻辑不当引发的异常行为。

此类问题常见于以下几种情况:

1. 定时器初始化不规范:若未正确配置定时器模式、分频系数或自动重载值,可能导致计时精度偏差,进而影响比较逻辑的准确性。

2. 中断处理不及时:在多任务环境下,若中断服务函数执行时间过长或未及时清零标志位,可能造成定时器溢出或比较事件被重复触发。

3. 变量类型选择不当:若使用无符号整型(如unsigned int)存储计时值,而实际应用中需要处理负值或大范围计时,可能导致溢出或比较结果错误。

4. 比较逻辑设计缺陷:例如在判断计时是否达到设定值时,未考虑变量更新的同步性,可能导致因读取顺序不同而产生误判。

为验证上述问题,建议您通过以下步骤进一步排查:
检查定时器T2的初始化代码,确认其工作模式、分频设置及自动重载寄存器(T2L/T2H)的配置是否符合预期。
在中断服务函数中添加调试输出(如通过串口打印当前计时值),以观察计时变量的变化趋势。
对比不同环境下的测试结果,确认BUG是否为偶发性,从而判断是否与外部干扰或硬件稳定性有关。

此外,考虑到STC系列单片机广泛应用于工业控制、智能终端等领域,建议在开发过程中遵循以下最佳实践:
采用模块化设计,将定时器、中断等核心功能封装为独立模块,便于维护与调试。
使用可靠的数据类型和运算方式,避免因变量溢出或精度问题引发逻辑错误。
在关键代码段加入必要的保护机制,如临界区锁、状态检查等,提升系统鲁棒性。

综上所述,STC单片机计时比较BUG的根源可能涉及多个层面,需结合具体应用场景进行细致分析。国芯人工智能将持续关注此类技术问题,致力于提供更稳定、高效的嵌入式解决方案。如需进一步技术支持,欢迎随时联系。

[本文内容由国芯人工智能辅助生成,仅供参考]
回复

使用道具 举报 送花

  • 打卡等级:常住居民I
  • 打卡总天数:75
  • 最近打卡:2025-08-23 09:11:23

25

主题

458

回帖

2814

积分

超级版主

积分
2814
发表于 2025-8-15 10:45:38 | 显示全部楼层
您可以先学习
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")或其他

上面是 小李 演示:Ai8051U, printf_usb("Hello World !\r\n")及usb不停电下载@AiCube之图形化程序自动生成


上面是 小赵 演示:Ai8051U, printf_usb("Hello World !\r\n")及usb不停电下载@AiCube之图形化程序自动生成


上面是 小李 演示:STC8H8K64U, printf_usb("Hello World !\r\n")及usb不停电下载@AiCube之图形化程序自动生成


上面是 小赵 演示:STC8H8K64U, printf_usb("Hello World !\r\n")及usb不停电下载@AiCube之图形化程序自动生成




电话:0513-55012946 QQ:2195591714  微信:  19952583740
回复

使用道具 举报 送花

  • 打卡等级:以坛为家II
  • 打卡总天数:467
  • 最近打卡:2025-08-23 00:10:19
已绑定手机

8

主题

156

回帖

1421

积分

金牌会员

积分
1421
发表于 2025-8-15 11:36:20 | 显示全部楼层
EA=0;
                        curTime = tick+100;
                        if(tick>curTime)
                        {
                                SBUF = 0xaa;                                //发送测试数据
                        }
EA=1;
回复

使用道具 举报 送花

  • 打卡等级:初来乍到
  • 打卡总天数:3
  • 最近打卡:2025-08-15 09:54:35
已绑定手机

2

主题

12

回帖

46

积分

新手上路

积分
46
发表于 2025-8-15 13:56:32 | 显示全部楼层
cn*** 发表于 2025-8-15 11:36
EA=0;
                        curTime = tick+100;
                        if(tick>curTime)

这样操作是否会导致tick 不准?
另外这里不好关总的中断,业务可能还需要收发数据,最好关定时器的中断,
回复

使用道具 举报 送花

  • 打卡等级:常住居民III
  • 打卡总天数:115
  • 最近打卡:2025-08-22 08:29:37
已绑定手机

17

主题

479

回帖

1549

积分

金牌会员

积分
1549
发表于 2025-8-15 15:17:56 | 显示全部楼层
可以飞读tick变量
回复

使用道具 举报 送花

  • 打卡等级:以坛为家II
  • 打卡总天数:467
  • 最近打卡:2025-08-23 00:10:19
已绑定手机

8

主题

156

回帖

1421

积分

金牌会员

积分
1421
发表于 2025-8-15 15:25:23 | 显示全部楼层
cd*** 发表于 2025-8-15 13:56
这样操作是否会导致tick 不准?
另外这里不好关总的中断,业务可能还需要收发数据,最好关定时器的中断, ...

原因就是比较到一半的时候发生了中断导致数据出问题。你自己想办法规避就好了。
回复

使用道具 举报 送花

  • 打卡等级:初来乍到
  • 打卡总天数:3
  • 最近打卡:2025-08-15 09:54:35
已绑定手机

2

主题

12

回帖

46

积分

新手上路

积分
46
发表于 2025-8-15 16:45:52 | 显示全部楼层
Ayb_*** 发表于 2025-8-15 15:17
可以飞读tick变量

飞读是怎么操作?
回复

使用道具 举报 送花

  • 打卡等级:常住居民III
  • 打卡总天数:115
  • 最近打卡:2025-08-22 08:29:37
已绑定手机

17

主题

479

回帖

1549

积分

金牌会员

积分
1549
发表于 2025-8-15 17:05:21 | 显示全部楼层
cd*** 发表于 2025-8-15 16:45
飞读是怎么操作?

就是避免读的时候正好产生了进位,从而产生错误,16位的飞读,先读高字节,再读低字节,再读高字节,如果两次高字节相等则成功,否则连续此操作,直到成功
回复

使用道具 举报 送花

  • 打卡等级:以坛为家II
  • 打卡总天数:506
  • 最近打卡:2025-08-23 06:08:39
已绑定手机

17

主题

732

回帖

1681

积分

金牌会员

积分
1681
发表于 7 天前 | 显示全部楼层
回复

使用道具 举报 送花

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|手机版|小黑屋|深圳国芯人工智能有限公司 ( 粤ICP备2022108929号-2 )

GMT+8, 2025-8-23 22:32 , Processed in 0.125174 second(s), 104 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

快速回复 返回顶部 返回列表