本帖最后由 onemoren 于 2022-3-24 23:12 编辑
#申请原创#
清0一个IO口,一条简单C语言搞定,如:
GPIOD->DOUT&=0XBF;
很多初学者会认为这是一个原子操作,实际用KEIL做汇编,会发现有6条汇编指令来完成,如下面图片所示。
前两行汇编,是取址和算出DOUT寄存器并读出里面的值存在R0中;中间两行汇编,是将R0和0XBF运算后存于R0中;最后两行是用R1寻址DOUT寄存器,并将R0的值回写到DOUT中。
所以C中IO赋值语句不是原子操作,有没有想过,整个赋值过程会被中断打断?如果在这6行汇编中产生中断,要注意:
1.如果中断产生,会立即响应中断函数,中断函数中如果没对相同的端口,如上图的GPIOD的DOUT做操作,那不会产生什么异常;
2.如果中断函数中刚好有对GPIOD的DOUT做操作,那有可能会产生异常现象(因为退出中断后,又做了一次DOUT赋值)。
另外,大家要注意的是,从上面汇编最后两行来看,DOUT寄存器回写是8位同时回写。GPIOD->DOUT&=0XBF的目的本来是对第6位进行清0,但实际上最后回写时还是做了一次8位回写(关于GPIO输出操作,大家可以参考对比一下F103的BRR/BSRR操作,是不用16位同时回写的,但F003没有这两个寄存器)。
GPIO赋值是不是也挺复杂的。有兴趣多看看汇编出来的效果。
|