关于这件事,还是想的太简单了

文章讲述了在单片机开发中遇到的问题,即中断服务程序设置的标志位在中断结束后被意外恢复。通过深入分析发现,编译器对全局变量进行了优化,导致标志位不一致。最终通过添加`volatile`关键字解决了问题,强调了在中断程序中使用volatile的重要性以及volatile的关键作用和适用场景。

中断没进去,还是程序没运行?

在中断函数里设置标志位,主程序里检测标志位,然后执行相应的程序。这种模式用了好几年了,但是突然有问题了。

起因是调试程序时,发现有个功能模块功能异常,通过打印日志发现,该功能模块始终没有得到允许。那就看允许运行的条件喽。是在事件发生时,单片机产生中断,然后在中断服务程序里,设置一个标志位。在中断里打印日志,标志位确实被设置了。

这就奇怪了,中断服务运行了,标志位被设置了,功能程序为什么不运行呢?

变量是双面人?

通过打印日志暂时没找到问题根源,就上仿真大法吧。跟踪到中断服务程序里,单步运行,设置标志位,神奇的事情就出现了,在中断程序里标志位被设置了,离开中断会,标志位竟然被恢复了。难道这个标志位是双面人?

最终还是我错了。

这个编译器有bug,这种伟大想法也仅仅是想想,还是要继续找问题的。通过不断的努力(耗时间),终于在仿真界面的反汇编里发现一点异常。标志位定义成全局变量,而中断服务程序里,是用R寄存器代表这个标志位。(当时没有截图,就不上图了。见谅。)这就有问题了啊。说是迟,那是快,这时一个关键字“volatile”如同一颗流星一般划过我的思维。标志位被优化掉了啊。

赶紧用“volatile”修饰一下标志位,然后运行,OK。这就好了!!!好了!!!为这事忙了两天呢。

收获

在中断程序里使用的变量最好要使用“volatile”来修饰一下,防止被编译器优化。

volatile的介绍(AI创作助手)

volatile是Java中的关键字,用于声明变量。它的作用是告诉编译器该变量将被多个线程访问和修改,因此不应该进行编译器优化,需要每次从内存中读取最新的值。

具体来说,volatile的作用包括以下几个方面:

  1. 禁止指令重排序:编译器和处理器在进行指令优化时,有时会对指令进行重排序,但是对于volatile变量,编译器会保证不会对其指令进行重排序。

  2. 保证可见性:当一个线程修改了volatile变量的值时,其他线程可以立即看到最新的值,不需要等待缓存写回主存。

  3. 不保证原子性:volatile变量只能保证可见性,并不能保证原子性。例如,多个线程同时对同一个volatile变量进行自增操作,可能会导致结果不正确。

因此,volatile适用于以下场景:

  1. 标识状态的变量:如标识一个线程是否继续执行的变量。

  2. 控制停止的变量:如标识一个循环是否结束的变量。

  3. 状态标志变量:如标识一个操作是否完成的变量。

需要注意的是,虽然volatile能够保证可见性,但并不能保证线程安全。在多线程环境下,如果需要保证变量的原子性操作,可以使用synchronized或者Lock进行同步控制。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值