Keil/MDK平台 - 变量中断与后台调用注意事项


【全文大纲】 : https://blog.csdn.net/Engineer_LU/article/details/135149485


1 . 前言总结

当中断中操作了变量,回到后台判断变量时有时候会判断不过是因为编译器优化在判断时不从ram区域地址取值判断,而是从寄存器变量中取值判断

2 . 问题现象

timer_Interrupt() 定时器中断里会一直执行,value会执行到100,但是有时候后台判断value仍然一直小于50,原因是后台判断中编译器优化,把value变量放到R0,R1这些寄存器变量里,因为寄存器变量运行速度会很快,但也因此,当值已经给R0,R1这些寄存器变量后,判断就只判断R0,R1这些寄存器变量,而此时ram区域的value变量改变了,却仍然在判断R0,R1这些寄存器变量,因此一直判断不到value>=50

unsigned int value = 0;
unsigned int ram = 0;

int main() {
	
	while (1) {
		if (value >= 50) {
			ram = 1}
	}
	return 0;
}

void timer_Interrupt()
{ 
	if (++value >= 100) {
		value = 100;
	}
}

3 . 解决思路

为了解决以上问题,可在需要在中断与后台同时操作的变量定义时加 volatile 修饰,以保证编译不会把变量放到寄存器变量里执行逻辑

volatile unsigned int value = 0;
unsigned int ram = 0;

int main() {
	
	while (1) {
		if (value >= 50) {
			ram = 1}
	}
	return 0;
}

void timer_Interrupt()
{ 
	if (++value >= 100) {
		value = 100;
	}
}

4 . 细节扩展

除了上述变量,还有指针指向中断操作的变量,也应加volatile修饰定义指针,以保证指针取值不会取向寄存器变量,另外MDK平台若开启 O 1 O_1 O1以上优化,此问题暴露的几率比较大

5 . 总结

优秀的代码,在任何优化下,基本很少影响正常运行 (不排除极端优化导致的逻辑问题),其实单片机里中断可以理解为开了一个线程,这就相当于后台为主线程,中断为另一个线程,当多线程交互时,单片机在没有系统加持管理情况下,纯粹靠编译决定行为,因此一般建议在中断后台都有同一变量写入的行为情况下,加响应完成的“互斥锁”,如果不加,系统框架也尽量满足即使中断打断操作了变量也不至于系统崩溃,最后就是优化问题,对寄存器变量深入研究可发现目前编译器是不够完美的,用户尽量避免该问题出现

技术交流群 : 745662457
群内专注 - 问题答疑,技术研究

  • 16
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

极客 - L U

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值