比特,小吃和C中的移位

时间:2014-10-26 21:23:42

标签: c bit-manipulation

我试图了解位操作,但经过几个小时的分析 - 仍然没有。

以下是代码:https://github.com/merbanan/rtl_433/blob/master/src/rtl_433.c

但最有趣的部分是:

static int prologue_callback(uint8_t bb[BITBUF_ROWS][BITBUF_COLS]) {
    int rid;

    int16_t temp2;

    /* FIXME validate the received message better */
    if (((bb[1][0]&0xF0) == 0x90 && (bb[2][0]&0xF0) == 0x90 && (bb[3][0]&0xF0) == 0x90 && (bb[4][0]&0xF0) == 0x90 &&
        (bb[5][0]&0xF0) == 0x90 && (bb[6][0]&0xF0) == 0x90) ||
        ((bb[1][0]&0xF0) == 0x50 && (bb[2][0]&0xF0) == 0x50 && (bb[3][0]&0xF0) == 0x50 && (bb[4][0]&0xF0) == 0x50)) {

        /* Prologue sensor */
        temp2 = (int16_t)((uint16_t)(bb[1][2] << 8) | (bb[1][3]&0xF0));
        temp2 = temp2 >> 4;
        fprintf(stderr, "Sensor temperature event:\n");
        fprintf(stderr, "protocol      = Prologue\n");
        fprintf(stderr, "button        = %d\n",bb[1][1]&0x04?1:0);
        fprintf(stderr, "battery       = %s\n",bb[1][1]&0x08?"Ok":"Low");
        fprintf(stderr, "temp          = %s%d.%d\n",temp2<0?"-":"",abs((int16_t)temp2/10),abs((int16_t)temp2%10));
        fprintf(stderr, "humidity      = %d\n", ((bb[1][3]&0x0F)<<4)|(bb[1][4]>>4));
        fprintf(stderr, "channel       = %d\n",(bb[1][1]&0x03)+1);
        fprintf(stderr, "id            = %d\n",(bb[1][0]&0xF0)>>4);
        rid = ((bb[1][0]&0x0F)<<4)|(bb[1][1]&0xF0)>>4;
        fprintf(stderr, "rid           = %d\n", rid);
        fprintf(stderr, "hrid          = %02x\n", rid);

        fprintf(stderr, "%02x %02x %02x %02x %02x\n",bb[1][0],bb[1][1],bb[1][2],bb[1][3],bb[1][4]);

        if (debug_output)
            debug_callback(bb);

        return 1;
    }
    return 0;

我不明白什么是bb [BITBUF_ROWS] [BITBUF_COLS]。

算法得到9个半字节,它们被解码成一些变量,例如。温度,湿度等。

取自http://goughlui.com/2013/12/20/rtl-sdr-433-92mhz-askook-decoding-of-various-devices-with-rtl_433/

的例子

输入:10010110 01000100 00010000 00010010 10111000

结果:

button: 1
battery: Low
temp: 25.7
humidity: 43
channel:1 
id: 9
rid :100
hrid: 64

因为我不知道输入是否为负或LSB是否反转我在所有情况下都准备了表格:

bin   dec   neg    neg  rev   rev   neg     neg
            bin    dec        dec   rev     rev dec
1001    9   0110    6   1001    9   0110    6
0110    6   1001    9   0110    6   1001    9
0100    4   1011    11  0010    2   1101    13
0100    4   1011    11  0010    2   1101    13
0001    1   1110    14  1000    8   0111    7
0000    0   1111    15  0000    0   1111    15
0001    1   1110    14  1000    8   0111    7
0010    2   1101    13  0100    4   1011    11
1011    11  0100    4   1101    13  0010    2
1000    8   0111    7   0001    1   1110    14

但我明确地不理解温度是25.7,而根本没有5。湿度id 43但没有3值。

我做错了什么?

3 个答案:

答案 0 :(得分:3)

所有价值都在那里。十六进制的输入是

96 44 10 12 B8

并将其写为半字节,我们得到

A a | B b | C c | D d | E e
9 6 | 4 4 | 1 0 | 1 2 | B 8

使用此表示法,我们可以将bb[1][0]替换为Aabb[1][1]替换为Bb,依此类推。我会将单个半字节称为Aa等,而不需要进行位移和屏蔽,这可能会使事情更加清晰。要获取AB等取字节,屏蔽4个最高位(& 0xF0)并将其右移4位(>>4)。获取{{1 },a等掩码原始字节的最低4位:b

按钮是一个简单的位标志:& 0x0F的第2位:b,因此它是 1 。 (位从右到左计数,从0开始。)

电池也是一个简单的位标志:0100的第3位,所以它是b,表示“低”。< / p>

温度0((Cc<<8)|D)>>4,或十六进制为10<<8 = 1000 + 10 = 1010 >> 4,十进制为257。这似乎是十分之一度,因此除以10: 25.7 (所有额外操作都是正确显示负值)。

湿度101,或(d<<4) | E 43

频道20 | B = 2Bb)的0-1位加1,等于 1

Id 00中的值: 9

RID 最后是小数点A(a<<4) | B 100 hrid 是相同的值,但以十六进制编写。

答案 1 :(得分:2)

温度字节为bb[1][2]bb[1][3] = 0001000000010010

代码附加这些代码,然后向右移动4:0001 0000 0001

从二进制转换为十进制,这是257(十六进制是0x101)。

代码除以10得到温度:25.7。

答案 2 :(得分:1)

数据被打包到数组中。例如,从4升中提取湿度。 bb[1][3]和4 m.s.的位比特bb[1][4]

fprintf(stderr, "humidity      = %d\n", ((bb[1][3]&0x0F)<<4)|(bb[1][4]>>4));

所以如果bb [1] [3] = xxxx0010和bb [1] [4] = 1011xxxx,湿度= 00101011 = 43

温度相似但更复杂。