如何使用掩码获取几位的值
How to get value of few bits using a mask
我正在开发一个 MCU,其中每个 GPIO 端口都有 16 个引脚。我有一个中断路由,我需要在其中查看引脚 14、13 和 12 的输入数据寄存器是高电平还是低电平。我创建了这个简单的测试场景,看看我是否可以读取特定的引脚并将其存储在 uint8_t
变量中:
#include <stdio.h>
#include <stdint.h>
#define GPIO_PIN_0 ((uint16_t)0x0001) /* Pin 0 selected */
#define GPIO_PIN_1 ((uint16_t)0x0002) /* Pin 1 selected */
#define GPIO_PIN_2 ((uint16_t)0x0004) /* Pin 2 selected */
#define GPIO_PIN_3 ((uint16_t)0x0008) /* Pin 3 selected */
#define GPIO_PIN_4 ((uint16_t)0x0010) /* Pin 4 selected */
#define GPIO_PIN_5 ((uint16_t)0x0020) /* Pin 5 selected */
#define GPIO_PIN_6 ((uint16_t)0x0040) /* Pin 6 selected */
#define GPIO_PIN_7 ((uint16_t)0x0080) /* Pin 7 selected */
#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 */
#define GPIO_PIN_All ((uint16_t)0xFFFF) /* All pins selected */
int main() {
uint32_t maskWithOR = GPIO_PIN_14 | GPIO_PIN_13 | GPIO_PIN_12;
uint32_t maskInBinary = 0b00000000000000000111000000000000;
uint32_t data[8] = {
//.................XXX............
0b10010000100011110000000011111111, //0 = 000
0b10010000100011110001000011111111, //1 = 001
0b10010000100011110010000011111111, //2 = 010
0b10010000100011110011000011111111, //3 = 011
0b10010000100011110100000011111111, //4 = 100
0b10010000100011110101000011111111, //5 = 101
0b10010000100011110110000011111111, //6 = 110
0b10010000100011110111000011111111, //7 = 111
};
printf("maskWithOR = 0x%x\r\n", maskWithOR);
printf("maskInBinary = 0x%x\r\n", maskInBinary);
printf("\r\nOR MASK:\r\n");
for(int i = 0; i < 8; i++) {
uint8_t result = data[i] & maskWithOR;
printf("result[%d] = %d\r\n", i, result);
}
printf("\r\nBINARY MASK:\r\n");
for(int i = 0; i < 8; i++) {
uint8_t result = data[i] & maskInBinary;
printf("result[%d] = %d\r\n", i, result);
}
return 0;
}
这是我的测试程序的输出:
maskWithOR = 0x7000
maskInBinary = 0x7000
OR MASK:
result[0] = 0
result[1] = 0
result[2] = 0
result[3] = 0
result[4] = 0
result[5] = 0
result[6] = 0
result[7] = 0
BINARY MASK:
result[0] = 0
result[1] = 0
result[2] = 0
result[3] = 0
result[4] = 0
result[5] = 0
result[6] = 0
result[7] = 0
我做错了什么?
您正在将 32 位运算的结果存储在 8 位变量中:
uint8_t result = data[i] & maskWithOR;
此操作的结果是值被截断,只剩下原始结果的最后八位。由于您感兴趣的所有三位都在位 12 以上,因此您得到的结果始终为零。
如果您必须将结果放入八位,请将 data[i] & maskWithOR
的值移动最低位的索引,即移动 12。
您不能将 AND
结果存储为 8 位整数...
您可以尝试像这样强制一个布尔结果(1 或 0):
uint8_t result = (data[i] & maskWithOR)>0;
在从 0 - 7 查看所需的输出值后,您可以强制将 32 位无符号数移位...向右移动 12 位,然后仅使用适合 8 位整数的位进行掩码确保您获得 8 位结果
uint8_t result = ((data[i] & maskWithOR)>>12) & 255;
尽管 255 掩码有点多余...您可以这样做并且可能会侥幸成功...
uint8_t result = (data[i] & maskWithOR)>>12;
但是正如@chux 提到的那样,AND
与 255
结合将消除或抑制因将结果从 uint32_t
缩小到 uint8_t
而产生的警告
我正在开发一个 MCU,其中每个 GPIO 端口都有 16 个引脚。我有一个中断路由,我需要在其中查看引脚 14、13 和 12 的输入数据寄存器是高电平还是低电平。我创建了这个简单的测试场景,看看我是否可以读取特定的引脚并将其存储在 uint8_t
变量中:
#include <stdio.h>
#include <stdint.h>
#define GPIO_PIN_0 ((uint16_t)0x0001) /* Pin 0 selected */
#define GPIO_PIN_1 ((uint16_t)0x0002) /* Pin 1 selected */
#define GPIO_PIN_2 ((uint16_t)0x0004) /* Pin 2 selected */
#define GPIO_PIN_3 ((uint16_t)0x0008) /* Pin 3 selected */
#define GPIO_PIN_4 ((uint16_t)0x0010) /* Pin 4 selected */
#define GPIO_PIN_5 ((uint16_t)0x0020) /* Pin 5 selected */
#define GPIO_PIN_6 ((uint16_t)0x0040) /* Pin 6 selected */
#define GPIO_PIN_7 ((uint16_t)0x0080) /* Pin 7 selected */
#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 */
#define GPIO_PIN_All ((uint16_t)0xFFFF) /* All pins selected */
int main() {
uint32_t maskWithOR = GPIO_PIN_14 | GPIO_PIN_13 | GPIO_PIN_12;
uint32_t maskInBinary = 0b00000000000000000111000000000000;
uint32_t data[8] = {
//.................XXX............
0b10010000100011110000000011111111, //0 = 000
0b10010000100011110001000011111111, //1 = 001
0b10010000100011110010000011111111, //2 = 010
0b10010000100011110011000011111111, //3 = 011
0b10010000100011110100000011111111, //4 = 100
0b10010000100011110101000011111111, //5 = 101
0b10010000100011110110000011111111, //6 = 110
0b10010000100011110111000011111111, //7 = 111
};
printf("maskWithOR = 0x%x\r\n", maskWithOR);
printf("maskInBinary = 0x%x\r\n", maskInBinary);
printf("\r\nOR MASK:\r\n");
for(int i = 0; i < 8; i++) {
uint8_t result = data[i] & maskWithOR;
printf("result[%d] = %d\r\n", i, result);
}
printf("\r\nBINARY MASK:\r\n");
for(int i = 0; i < 8; i++) {
uint8_t result = data[i] & maskInBinary;
printf("result[%d] = %d\r\n", i, result);
}
return 0;
}
这是我的测试程序的输出:
maskWithOR = 0x7000
maskInBinary = 0x7000
OR MASK:
result[0] = 0
result[1] = 0
result[2] = 0
result[3] = 0
result[4] = 0
result[5] = 0
result[6] = 0
result[7] = 0
BINARY MASK:
result[0] = 0
result[1] = 0
result[2] = 0
result[3] = 0
result[4] = 0
result[5] = 0
result[6] = 0
result[7] = 0
我做错了什么?
您正在将 32 位运算的结果存储在 8 位变量中:
uint8_t result = data[i] & maskWithOR;
此操作的结果是值被截断,只剩下原始结果的最后八位。由于您感兴趣的所有三位都在位 12 以上,因此您得到的结果始终为零。
如果您必须将结果放入八位,请将 data[i] & maskWithOR
的值移动最低位的索引,即移动 12。
您不能将 AND
结果存储为 8 位整数...
您可以尝试像这样强制一个布尔结果(1 或 0):
uint8_t result = (data[i] & maskWithOR)>0;
在从 0 - 7 查看所需的输出值后,您可以强制将 32 位无符号数移位...向右移动 12 位,然后仅使用适合 8 位整数的位进行掩码确保您获得 8 位结果
uint8_t result = ((data[i] & maskWithOR)>>12) & 255;
尽管 255 掩码有点多余...您可以这样做并且可能会侥幸成功...
uint8_t result = (data[i] & maskWithOR)>>12;
但是正如@chux 提到的那样,AND
与 255
结合将消除或抑制因将结果从 uint32_t
缩小到 uint8_t