一、问题描述:
在调试一个电机运转方向切换的工程时,在main()函数中,while(1){}之前,设置一个控制电机转动的子程序,子程序中涉及到了一个电机运转到某位置后,触发光耦(设置的的是外中断,触发后置位一个标志),然后反向运转。
程序设计原理是,先让电机正向运转,同轴旋转的一个挡片,遮挡光耦触发外中断,在外中断服务函数中,置位一个标志(m_flag = 1)。当子程序中检测到这个标志后,控制电机反向运转。这里用到了while(m_flag == 0);的等待函数。
程序编译下载后,无论挡片怎么遮挡光耦,子程序都无法跳出while循环,while进入死循环了,永远无法跳出来(已经反复检查过程序,确保程序语法、运行逻辑、触发条件等都没有任何问题)。
二、问题原因
通过网上查找资料,说是程序死在了汇编代码:CMP r0,#0x00 这里了。
原因是编译器在编译时认为该状态变量只会在main函数中使用,所以只取了一次状态值到r0,然后状态值发生了变化,主函数却未能感知到,所以才出现这个问题。
三、解决方法
解决的方法有三个:
(1)、修改编译器的优化等级,将Options for target’***’->c/c++->optimization从默认的Level3 改为Level0。
(2)、在while的函数体内加一个不影响程序执行结果的delay。那么当调用之后再判断时,就会再取一次状态值进行CMP。
while(m_flag == 0)
{
HAL_Delay(1);
}
(3)、在m_flag变量定义的时候,加上volatile修饰,或者加前缀__IO,指出与volatile变量有关的运算,不要进行编译优化,确保变量不会因编译器的优化而省略。
例如:__IO uint8_t m_flag = 0;