c - 是否可以通过 C 变量而不是使用 GPIO_Pin_N 值读取和/或写入端口?

标签 c arm stm32

我能找到的所有示例代码都像这样访问端口:

GPIO_SetBits(GPIOE, GPIO_Pin_9 | GPIO_Pin_13);

起初看起来不错,直到我尝试通过索引 (0-7) 引用 LED(我的端口 E)。 switch 或 LUT 是一种解决方案,但我都不喜欢。是否可以声明e。 G。 uint8_t 并将其映射到某个端口的特定引脚范围?

最佳答案

标准的 Cortex-M3/M4 内存映射允许 CPU 具有所谓的“位带”区域别名,其中写入位带别名中的每个字执行自动读取-修改-写入改变相应区域的目标位。

以STM32F411(Cortex-M4F)手册为例,它显示外围区域0x40000000-0x400FFFFF被区域0x42000000中的位带别名覆盖-0x43FFFFFF。因此,例如在该设备上(如果我的数学没问题的话)0x42420280-0x42420300 中的每个单词都对应于 GPIO 端口 E 数据寄存器 GPIOE_ODR 中的位 0x40021014 ,所以这样:

volatile int *leds = (void *)0x42420280;
leds[x] = 1; /* only bit 0 of the bit-band word actually holds data */

使硬件执行与​​此等效的整洁抽象的操作:

volatile int *leds = (void *)0x40021014;
int val = *leds;
val |= (1 << x);
*leds = val;

如果您有合适的设备,不想一次更新多个位,并且在某些情况下不介意额外的开销与对常规寄存器的单次访问(例如写入设置/清除寄存器)的数据),这是一个非常巧妙的技巧。

关于c - 是否可以通过 C 变量而不是使用 GPIO_Pin_N 值读取和/或写入端口?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33904467/

相关文章:

linux - 无法通过 ARM 板的串行连接写入 GSM 模块

serial-port - 尝试从 SMT32 读取串行端口时没有消息显示

使用指针更改原始字符串的值

c - 从 STM32L476G-DISCO 的闪存读取文件

c - 如何在链表插入函数中插入字符串

gcc - 数据类型与 NEON 内在函数的兼容性

STM32:从SRAM引导和获取向量表

对来自具有两个输入的机械水表的脉冲进行计数

c - 变量在内存中的位置,C

c - linux 中的 C 程序是否获得 PID?