【问题标题】:bit, nibbles and shifting in CC 中的位、半字节和移位
【发布时间】:2014-10-27 08:44:05
【问题描述】:

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

这里是代码: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 值。

我做错了什么?

【问题讨论】:

  • bb[BITBUF_ROWS][BITBUF_COLS] 表示该函数接收一个二维数组作为参数。它有BITBUF_ROWS 行,每行有BITBUF_COLS 列。
  • 是的,但是数组的项目是位还是字节?
  • 元素为uint8_t,无符号8位字节。
  • 但是BITBUF_ROWS的最高索引是6,而BITBUF_COLS的最高索引是3,所以7x4=28字节远比输入10字节多
  • 许多高位半字节似乎被保留(0x500x90)——见第一行if。用肉眼数数,我认为 8 个半字节包含所有这些数据。

标签: c bit-manipulation


【解决方案1】:

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

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] 替换为Aa,将bb[1][1] 替换为Bb 等等。我将把单个 nibbles 称为Aa 等等,没有位移和掩码,这可能会使事情更清楚一些。要获取AB 等,获取字节,屏蔽 4 个最高位 (&amp; 0xF0) 并将其右移 4 位 (&gt;&gt;4)。获取 ab 等。原始字节的最低4位:&amp; 0x0F

按钮是一个简单的位标志:b的位2:0100,所以是1。 (位从右到左计数,从 0 开始。)

电池也是一个简单的位标志:b的第3位,所以是0,表示“Low”

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

湿度(d&lt;&lt;4) | E,或20 | B = 2B,即43

Channelb (00) 的 0-1 位加 1,等于 1

IdA 中的值:9

RID 最后是 (a&lt;&lt;4) | B: 60 | 4 = 64, 100 以十进制表示。 hrid 是相同的值,但用十六进制编写。

【讨论】:

  • 非常感谢您的明确解释。现在一切都清楚了——我已经确定了,temp 应该是 BCD 格式,并且无法摆脱这种固定。几个小时后,一切都混在一起了,我什至不确定 bb[i][j] 是半字节、字节还是位;D
【解决方案2】:

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

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

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

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

【讨论】:

    【解决方案3】:

    数据被打包到数组中。例如,湿度是从 4 l.s. 中提取的。 bb[1][3] 的位和 4 毫秒。 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

    温度相似但更复杂。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2013-01-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-10-26
      • 2023-03-17
      • 2010-11-20
      相关资源
      最近更新 更多