在《如何对STM32的GPIO管脚位值进行取反设置?》中有朋友提出的对于管脚取反设置的方法,我认为有一定的风险,在那里我说了下原因,但是没有引起大家的重视我认为有必要再发一个帖子来讨论下。
http://www.amobbs.com/thread-4580994-1-1.html
有朋友提出,对引脚取反的方法
“GPIOx->ODR ^= (1<<n);
如果要将PC7取反,则为GPIOC->ODR ^= (1<<7);”
让我们分析下 GPIOC->ODR ^= (1<<7); 这种方式吧,其实是有一定的风险的。
看下反汇编如下:
55: GPIOC->ODR ^= (1<<7);
//读取 GPIOC->ODR 的值,放到R0中
1. 0x0800B868 4807 LDR r0,[pc,#28] ; @0x0800B888
2. 0x0800B86A 68C0 LDR r0,[r0,#0x0C]
//将读取的在R0中的值进行改写
3. 0x0800B86C F0800002 EOR r0,r0,#0x80
//写回GPIOC->ODR
4. 0x0800B870 4905 LDR r1,[pc,#20] ; @0x0800B888
5. 0x0800B872 60C8 STR r0,[r1,#0x0C]
……
//GPIOC地址
6. 0x0800B888 1000 DCW 0x1000
……
如果在2~5步之间有中断程序,改写了GPIOC->ODR的值,那么这个程序执行结果可能不是我们所希望的。
个人推荐没有副作用的方法有两个,
一. 位带操作
二.((GPIOC->ODR & GPIO_Pin_7) ? (GPIOC->BRR = GPIO_Pin_7): (GPIOC->BSRR = GPIO_Pin_7))
|