一个与我混淆的按位操作

时间:2015-08-02 13:30:38

标签: c arrays binary decimal stm32f4discovery

我正在研究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 */

3 个答案:

答案 0 :(得分:3)

这可能是错误的:

  • 您不应多次读取输入数据寄存器以获取相应的值。寄存器定义为volatile,因此编译器无法优化访问。
  • 使用&进行屏蔽不会返回01(布尔结果),但会将该位置于其所具有的位置。乘法将它们移动到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位。