Reputation: 911
I am working on an MCU where each GPIO port has 16 pins. I have an interrupt routing where I need to see if the input data registers of pins 14, 13 and 12 are high or low. I created this simple test scenario to see if I can read and store that specific pins in a uint8_t
variable:
#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;
}
This is the output of my test program:
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
What am I doing wrong?
Upvotes: 0
Views: 447
Reputation: 2556
You cannot store your AND
result in an 8 bit integer...
You could try forcing a boolean result (1 or 0) like this:
uint8_t result = (data[i] & maskWithOR)>0;
After reviewing your desired output value from 0 - 7, you could force a bit shift in your 32 bit unsigned number...12 bits to the right and then mask with only the bits that fit into an 8 bit integer to ensure you get an 8 bit result
uint8_t result = ((data[i] & maskWithOR)>>12) & 255;
Although the 255 mask is a bit redundant...You can do it like this and probably get away with it ...
uint8_t result = (data[i] & maskWithOR)>>12;
But as @chux mentioned AND
ing with 255
will quiet or suppress warnings that arise from narrowing the result from uint32_t
to uint8_t
Upvotes: 1
Reputation: 726639
You are storing the result of a 32-bit operation in an 8-bit variable:
uint8_t result = data[i] & maskWithOR;
The result of this operation is that the value is truncated, leaving you with the last eight bits of the original result. Since all three bits of interest to you are above bit 12, the results that you get are always zero.
If you must fit the result in eight bits, shift the value of data[i] & maskWithOR
by the index of the lowest bit, i.e. by 12.
Upvotes: 1