找回密码
 立即注册
楼主: 小飞侠

发现一个bug不知道是单片机还是Keil的问题 | 是细节问题,大家必须看下,原子操作

[复制链接]
  • 打卡等级:常住居民III
  • 打卡总天数:156
  • 最近打卡:2025-04-29 00:51:09

24

主题

229

回帖

1281

积分

金牌会员

积分
1281
发表于 2024-11-20 13:01:20 | 显示全部楼层
小*** 发表于 2024-11-20 12:25
变量定义时不赋初值,在主程序中赋值,结果就正常了,再请问一下,局部变量也是这样吗? ...

避免声明时赋值
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:偶尔看看III
  • 打卡总天数:38
  • 最近打卡:2025-04-29 08:28:25
已绑定手机

17

主题

446

回帖

1173

积分

金牌会员

积分
1173
发表于 2024-11-20 13:09:22 | 显示全部楼层
没有那么多BUG,这是你的代码 问题,其实就是临界代码的问题,再试试我修改后的工程

STC8H4K32TL.rar

60.91 KB, 下载次数: 35

回复 支持 反对

使用道具 举报 送花

  • 打卡等级:偶尔看看III
  • 打卡总天数:38
  • 最近打卡:2025-04-29 08:28:25
已绑定手机

17

主题

446

回帖

1173

积分

金牌会员

积分
1173
发表于 2024-11-20 13:11:06 | 显示全部楼层
void main(void)
{
        P_SW2 |= 0x80;
        Init_Timer_1ms();
        EA = 1;
        P3M1 = 0;P3M0 = 0x10;
        while(1)
        {
                uint16_t usTmp;

                EA = 0;
                usTmp = timer_ms;
                EA = 1;
                if(usTmp>=500)
                {//500ms任务
                        P34 ^= 1;
                        rf_buf[aa]=usTmp;
                        EA = 0;
                        timer_ms = 0;
                        EA = 1;
                        aa++;
                        if(aa>=28)
                        {
                                aa=0;
                        }
                }
        }
}
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:常住居民III
  • 打卡总天数:123
  • 最近打卡:2025-04-19 16:12:35
已绑定手机

60

主题

777

回帖

4001

积分

论坛元老

自定义头衔

积分
4001
发表于 2024-11-20 13:30:16 来自手机 | 显示全部楼层
bkeuqoaq 发表于 2024-11-20 13:11
void main(void)
{
        P_SW2 |= 0x80;

我虽然没点开楼主的程序,但是结合他的截图,和你的修改,我就知道问题出在哪里了

{:5_278:}

51单片机是8位机,
因此对16位和32位C语言变量的读写并不是原子操作,需要逐个字节提取。

如果在16位数据的读取过程(包含若干条指令),进了中断导致数据变化,
那么将会错误地读到来自不同时刻的高低字节。

比如举个例子,当变量值为511时

高字节为1,低字节为255

此时main函数打算调取这个数据

先调取了低字节 255

突然进了中断,中断对这个变量进行了自增,变为512,也就是
高字节为2,低字节为0

回到main函数

main函数继续调取高字节,读到2

main函数中拼凑得到的高低字节分别为2和255,拼凑也就是767。

已经既不等于511,也不等于512!!!

大相径庭。所以进行16位,32位的volatile变量访问时,一定要关闭中断!确保访问操作的原子性

{:5_361:}

联系我请点击左下角的【回复】按钮,否则我收不到消息提
回复 支持 1 反对 0

使用道具 举报 送花

  • 打卡等级:偶尔看看III
  • 打卡总天数:38
  • 最近打卡:2025-04-29 08:28:25
已绑定手机

17

主题

446

回帖

1173

积分

金牌会员

积分
1173
发表于 2024-11-20 13:32:49 | 显示全部楼层
VC*** 发表于 2024-11-20 13:30
我虽然没点开楼主的程序,但是结合他的截图,和你的修改,我就知道问题出在哪里了

是的,好多菜鸟不明白这点,
甚至有些经验的也不知道这点,
我在现实中碰到做项目的工程师真有这样的,
硬说MCU有问题
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:以坛为家I
  • 打卡总天数:394
  • 最近打卡:2025-05-01 03:26:07

16

主题

702

回帖

2470

积分

金牌会员

积分
2470
发表于 2024-11-20 14:04:04 | 显示全部楼层
bkeu*** 发表于 2024-11-20 13:32
是的,好多菜鸟不明白这点,甚至有些经验的也不知道这点,我在现实中碰到做项目的工程师真有这样的,硬说MCU有 ...

感谢回复,刚刚我又看了一下反汇编,
发现应该就是在主程序中操作该变量时,
又进入中断操作该变量导致的,
我在操作时关中断就没有问题了,
跟变量的赋值确实没有关系,
关键原因应该是单片机速度太快了
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:以坛为家I
  • 打卡总天数:394
  • 最近打卡:2025-05-01 03:26:07

16

主题

702

回帖

2470

积分

金牌会员

积分
2470
发表于 2024-11-20 14:06:45 | 显示全部楼层
我之前就发现,
变量定义为8位时是正常的,
16位就不正常,
没有想到是这个问题导致的
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:偶尔看看III
  • 打卡总天数:38
  • 最近打卡:2025-04-29 08:28:25
已绑定手机

17

主题

446

回帖

1173

积分

金牌会员

积分
1173
发表于 2024-11-20 14:07:19 | 显示全部楼层
小*** 发表于 2024-11-20 14:04
感谢回复,刚刚我又看了一下反汇编,发现应该就是在主程序中操作该变量时,又进入中断操作该变量导致的, ...

不是速度快有原因,具体看14楼,说的很清楚了
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:常住居民III
  • 打卡总天数:123
  • 最近打卡:2025-04-19 16:12:35
已绑定手机

60

主题

777

回帖

4001

积分

论坛元老

自定义头衔

积分
4001
发表于 2024-11-20 14:12:56 来自手机 | 显示全部楼层
本帖最后由 VCC 于 2024-11-20 14:13 编辑
小飞侠 发表于 2024-11-20 14:04
感谢回复,刚刚我又看了一下反汇编,发现应该就是在主程序中操作该变量时,又进入中断操作该变量导致的, ...


再慢也会产生这种巧合。

因为main函数和定时器在同时运行。定时器中断随时可能在main函数的任何位置打断并运行ISR程序

唯一解决办法,就是确保main函数的关键操作时,不会被ISR打断
联系我请点击左下角的【回复】按钮,否则我收不到消息提
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:以坛为家I
  • 打卡总天数:238
  • 最近打卡:2025-05-01 13:11:43

22

主题

283

回帖

901

积分

高级会员

积分
901
发表于 2024-11-20 15:29:52 来自手机 | 显示全部楼层
VCC 发表于 2024-11-20 13:30
我虽然没点开楼主的程序,但是结合他的截图,和你的修改,我就知道问题出在哪里了



REMOVEUNUSED
回复 支持 反对

使用道具 举报 送花

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

本版积分规则

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

GMT+8, 2025-5-1 19:56 , Processed in 0.185293 second(s), 114 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

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