将数字映射到 C 中的位位置
Mapping a number to bit position in C
我正在 Atmel AT90CAN128 上开发程序 运行。连接到此控制器的有 40 个设备,每个设备都有一个状态 (on/off)。因为我需要通过串行通信向 PC 报告每个设备的状态,所以我有 40 位,用于定义设备是打开还是关闭。此外,PC 可以打开或关闭这些设备中的任何一个。
因此,我的第一次尝试是创建以下结构:
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;
这个问题是 PC 会发送一个 unsigned char address
告诉我设备转动 on/off,所以访问对应于那个 address
数字的位结果是比较复杂...
所以我开始寻找选项,我偶然发现了 C99 _Bool
类型。我想,太好了,所以现在我将创建一个 _Bool data[40]
并且我可以通过索引我的 data
数组来访问 address
位。事实证明,在 C(或 C++)中,内存映射需要一个完整的字节来对其进行寻址。因此,即使我声明了一个 _Bool
,那个 _Bool
的大小将是 8 位,这是一个问题(它需要尽可能快,所以我发送的位越多,它变得越慢,并且PC 将只能使用 40 位 ),并且通信效率不高。所以我开始研究位域,并尝试了以下方法:
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;
我想知道,这是否会将 data[40]
映射到一个大小为 40 位(5 字节)的后续内存块?
如果没有,我是否缺少任何明显的解决方案?这似乎不是一件非常复杂的事情(如果设备少于 32 个,那么我可以使用 int
并通过位掩码访问)。
假设您返回的地址在 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|
-----------------------------------------------------------------
设置位 i
:
packet.data[i/8] |= (1 << (i%8));
清除位 i
:
packet.data[i/8] &= (1 << (i%8)) ^ 0xff;
读取位 i
:
int flag = (packet.data[i/8] & (1 << (i%8)) != 0;
我正在 Atmel AT90CAN128 上开发程序 运行。连接到此控制器的有 40 个设备,每个设备都有一个状态 (on/off)。因为我需要通过串行通信向 PC 报告每个设备的状态,所以我有 40 位,用于定义设备是打开还是关闭。此外,PC 可以打开或关闭这些设备中的任何一个。
因此,我的第一次尝试是创建以下结构:
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;
这个问题是 PC 会发送一个 unsigned char address
告诉我设备转动 on/off,所以访问对应于那个 address
数字的位结果是比较复杂...
所以我开始寻找选项,我偶然发现了 C99 _Bool
类型。我想,太好了,所以现在我将创建一个 _Bool data[40]
并且我可以通过索引我的 data
数组来访问 address
位。事实证明,在 C(或 C++)中,内存映射需要一个完整的字节来对其进行寻址。因此,即使我声明了一个 _Bool
,那个 _Bool
的大小将是 8 位,这是一个问题(它需要尽可能快,所以我发送的位越多,它变得越慢,并且PC 将只能使用 40 位 ),并且通信效率不高。所以我开始研究位域,并尝试了以下方法:
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;
我想知道,这是否会将 data[40]
映射到一个大小为 40 位(5 字节)的后续内存块?
如果没有,我是否缺少任何明显的解决方案?这似乎不是一件非常复杂的事情(如果设备少于 32 个,那么我可以使用 int
并通过位掩码访问)。
假设您返回的地址在 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|
-----------------------------------------------------------------
设置位 i
:
packet.data[i/8] |= (1 << (i%8));
清除位 i
:
packet.data[i/8] &= (1 << (i%8)) ^ 0xff;
读取位 i
:
int flag = (packet.data[i/8] & (1 << (i%8)) != 0;