简体   繁体   English

将数字映射到C中的位位置

[英]Mapping a number to bit position in C

I'm developing an programm running on Atmel AT90CAN128. 我正在开发在Atmel AT90CAN128上运行的程序。 Connected to this controller there are 40 devices, each with a status (on/off). 连接到该控制器的设备有40个,每个设备都有一个状态(开/关)。 As I need to report the status of each of this devices to a PC through Serial Communication, I have 40 bits, which define whether the device is on or off. 因为我需要通过串行通信向PC报告每个设备的状态,所以我有40位,用于定义设备是打开还是关闭。 In addition, the PC can turn any of this devices on or off. 此外,PC可以打开或关闭任何此设备。

So, my first attempt was to create the following struct: 因此,我的第一个尝试是创建以下结构:

typedef struct {
     unsigned char length;      //!< Data Length
     unsigned data_type;        //!< Data type
     unsigned char data[5];     //!< CAN data array 5 * 8 = 40 bits
} SERIAL_packet;

The problem with this was that the PC will send an unsigned char address telling me the device to turn on/off, so accessing the bit corresponding to that address number turned out to be rather complicated... 问题是PC会发送一个unsigned char address告诉我设备打开/关闭,因此访问与该address号对应的位变得相当复杂...

So I started looking for options, and I stumbled upon the C99 _Bool type. 所以我开始寻找选项,偶然发现了C99 _Bool类型。 I thought, great so now I'll just create a _Bool data[40] and I can access the address bit just by indexing my data array. 我以为很好,所以现在我将创建一个_Bool data[40] ,仅通过索引data数组即可访问address位。 Turns out that in C (or C++) memory mapping needs an entire byte for addressing it. 事实证明,在C(或C ++)中,内存映射需要一个完整的字节来对其进行寻址。 So even if I declare a _Bool the size of that _Bool will be 8 bits which is a problem (it needs to be as fast as possible so the more bits I send the slower it gets, and the PC will be specting 40 bits only ) and not very efficient for the communication. 所以,即使我宣布_Bool是大小_Bool将8位这是一个问题(它需要尽可能快地让更多的位我把它变得更慢,而PC将 specting 40位)沟通效率也不高。 So I started looking into Bit Fields, and tried the following: 因此,我开始研究位域,并尝试了以下方法:

typedef struct {
    unsigned char length;   //!< Data Length
    unsigned data_type;     //!< Data type
    arrayData data[40]; //!< Data array 5 bytes == 40 bits
} SERIAL_packet;

typedef struct {
    unsigned char aux : 1;
} arrayData;

And I wonder, is this going to map that data[40] into a consequent memory block with a size of 40 bits (5 bytes)? 我想知道,这是否会将data[40]映射到大小为40位(5个字节)的后续存储块中?

If not, is there any obvious solution I'm missing? 如果没有,我是否有任何明显的解决方案? This doesn't seem like a very complicated thing to do (would be much simpler if there were less than 32 devices so I could use a int and just access through a bit mask). 这似乎不是一件很复杂的事情(如果设备少于32个,将会更简单,因此我可以使用int并通过位掩码进行访问)。

Assuming the addresses you get back are in the range 0 - 39 and that a char has 8 bits, you can treat your data array as an array of bits: 假设您返回的地址在0到39的范围内,并且char具有8位,则可以将data数组视为位数组:

| data[0]                       | data[1]                           ...
-----------------------------------------------------------------
| 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10| 11| 12| 13| 14| 15|
-----------------------------------------------------------------

To set bit i : 设置位i

packet.data[i/8] |= (1 << (i%8));

To clear bit i : 为了清除i

packet.data[i/8] &= (1 << (i%8)) ^ 0xff;

To read bit i : 要阅读i

 int flag = (packet.data[i/8] & (1 << (i%8)) != 0;

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM