以下三行代码是使用 1 个 MOV 指令修改位的优化方法,而不是使用中断较少的安全读-修改-写习惯用法。它们彼此相同,并在 GPIO 端口的数据寄存器中设置LED_RED位:
*((volatile unsigned long*)(0x40025000 + (LED_RED << 2))) = LED_RED;
*(GPIO_PORTF_DATA_BITS_R + LED_RED) = LED_RED;
GPIO_PORTF_DATA_BITS_R[LED_RED] = LED_RED;
LED_RED
简直就是(volatile unsigned long) 0x02
.在该微控制器的存储器映射中,该寄存器的前2个LSB(和其他)未使用,因此第一个示例中的左移是有意义的。
GPIO_PORTF_DATA_BITS_R的定义是:
#define GPIO_PORTF_DATA_BITS_R ((volatile unsigned long *)0x40025000)
我的问题是:为什么在使用指针算术或数组索引(分别为第 2 种方法和第 3 种方法)时不需要左移两次?我很难理解。提前谢谢你。
记住 C 指针算法的工作原理:向指针添加偏移量以指向的类型为单位进行操作。 由于GPIO_PORTF_DATA_BITS_R
具有类型unisgned long *
和sizeof(unsigned long) == 4
,因此GPIO_PORTF_DATA_BITS_R + LED_RED
有效地添加2 * 4
= 8 个字节。
请注意,(1) 对0x40025000
进行算术运算,这是一个整数,而不是指针,因此我们需要将 8 相加才能得到相同的结果。 左移 2 与乘以 4 相同,因此LED_RED << 2
再次等于 8。
(3) 完全等同于 (2) 根据[]
运算符的定义。