我正在研究stm32f4。我需要读取8引脚并将转换后的值相加,如二进制到十进制。例如,如果8位的值是000000110,我的CardID
必须是6.我使用了这个,但可以有更好的方法:
CardID = (GPIOD->IDR & GPIO_Pin_8) +
(GPIOD->IDR & GPIO_Pin_9)*2 +
(GPIOD->IDR & GPIO_Pin_10)*4 +
(GPIOD->IDR & GPIO_Pin_11)*8 +
(GPIOD->IDR & GPIO_Pin_12)*16 +
(GPIOD->IDR & GPIO_Pin_13)*32 +
(GPIOD->IDR & GPIO_Pin_14)*64 +
(GPIOD->IDR & GPIO_Pin_15)*128;
提示:我知道GPIO_Pin_8,GPIO_Pin_9 ...... GPIO_Pin_15的值。
我们可以使用多种组合进行AND操作吗?
#define GPIO_Pin_8 ((uint16_t)0x0100) /* Pin 8 selected */
#define GPIO_Pin_9 ((uint16_t)0x0200) /* Pin 9 selected */
#define GPIO_Pin_10 ((uint16_t)0x0400) /* Pin 10 selected */
#define GPIO_Pin_11 ((uint16_t)0x0800) /* Pin 11 selected */
#define GPIO_Pin_12 ((uint16_t)0x1000) /* Pin 12 selected */
#define GPIO_Pin_13 ((uint16_t)0x2000) /* Pin 13 selected */
#define GPIO_Pin_14 ((uint16_t)0x4000) /* Pin 14 selected */
#define GPIO_Pin_15 ((uint16_t)0x8000) /* Pin 15 selected */
答案 0 :(得分:3)
这可能是错误的:
volatile
,因此编译器无法优化访问。&
进行屏蔽不会返回0
或1
(布尔结果),但会将该位置于其所具有的位置。乘法将它们移动到15..22的位置,而大概它们应该被移动到位0..7。由于这些是连续的位,正确的方法是:
// must be consecutive bits:
#define GPIO_CARD_ID_MASK 0xFF00U
#define GPIO_CARD_ID_SHIFT 8
CardID = (GPIOD->IDR & GPIO_CARD_ID_MASK) >> GPIO_CARD_ID_SHIFT;
这只能读取寄存器一次,因此可以避免竞争条件,并且 - 在这里可能更重要 - 可以节省许多时钟周期。它也(通常)使用正确命名的宏进行自我解释,从而更好地维护。
注意:对于给定的体系结构/ MCU,实际上不需要掩码(这些是uint16_t
的高8位),但是样式很好。它记录了您正在使用的位。如果该字段不是高位,则无论如何都需要它,因此掩码使其更加通用(它仍然需要连续的位,不连续的编号会使它更不直接)。
答案 1 :(得分:1)
在我看来,你只是想要这样的东西:
#define GPIO_PINS ((uint16_t)0xFF00)
#define GPIO_OFFSET (8)
// ...
CardID = (GPIOD->IDR & GPIO_PINS) >> GPIO_OFFSET;
答案 2 :(得分:1)
只需获取完整的GPIOD->IDR
然后调整它的移位和屏蔽,以获得等于转换值的16位int:
CardID = (GPIOD->IDR >> 8) & 0x00ff;
您的卡ID位于GPIOD-> IDR的高8位。