我正在尝试在“ c”(用于嵌入式应用程序)中创建一个表,其中每一行都是8位序列,例如:
11010011
01010011
10000000
然后,我需要具有设置/清除/读取任何行中任何位的功能。最有效的方法是什么?
对于位操作,我想使用:
uint8_t msk = 0x01;
row3 |= msk;
但是要做到这一点,我认为我需要将row3(以及每行)定义为uint8_t
,并将其也转换为十六进制,这又引出了我的第二个问题:
如何在uint8_t
中存储8位二进制序列?我已经看到了完成类似任务的不同方法,例如讨论过的here,但没有一种方法适合我。你能帮助我吗?
谢谢。
答案 0 :(得分:0)
C没有用于输入二进制文字的语法,因此您应将它们键入为八进制或十六进制,例如
uint8_t row1 = 0xd3;
uint8_t row2 = 0x53;
uint8_t row3 = 0x80;
有关如何操作特定位的信息,请参见How do you set, clear, and toggle a single bit?。
row3 |= mask;
将设置mask
中设置的位。
答案 1 :(得分:0)
如果我理解正确,则需要一个十六进制数字列表,并且您希望操作列表中任何元素的位。我将通过创建一个无符号整数数组来实现它,该数组的大小由表中需要的元素数定义。
#include <stdio.h>
#include <stdint.h>
#define LIST_SIZE 3
//accepts the array and sets bit_pos bit of the list idx
int set_bit(uint8_t* hex_list, int list_idx, int bit_pos){
hex_list[list_idx] = hex_list[list_idx] | 0x01<<bit_pos; //left shift by the bit position you want to set
}
int clear_bit(uint8_t* hex_list, int list_idx, int bit_pos){
hex_list[list_idx] = hex_list[list_idx] & ~(0x01<<bit_pos); //left shifts and does logical inversion to get the bit to clear
}
int main(void) {
uint8_t hex_list[LIST_SIZE] = {0x00, 0x01, 0x02};
set_bit(hex_list, 0, 1); // will make 0th element 0x00-> 0x02 by seting bit position 1
clear_bit(hex_list, 1,0); //will make 1st element 0x01-> 0x00 by clearing bit position 0
set_bit(hex_list, 2, 0); // will make 2nd element 0x02->0x03 by setting bit at position 1
clear_bit(hex_list, 2 , 0);// will make 2nd element 0x03 ->0x02 by clearing bit at position 0
//print the result and verify
for(int i = 0; i<LIST_SIZE; ++i){
// modified array will be {0x02, 0x00, 0x02}
printf("elem%d = %x \n", i, hex_list[i]);
}
return 0;
}
一个uint8_t
表示一个8位无符号整数,其值可以在0(二进制表示= 00000000)到255(二进制表示= 11111111)之间变化。
答案 2 :(得分:0)
要在C中表示二进制位模式,通常使用十六进制表示法。十六进制的用途是单个十六进制数字与4个二进制数字完全重合,因此根据经验,您可以在16个十六进制数字和头部中的相应二进制值之间快速转换,对于较长的整数,只需转换每个整数即可数字依次-一次4位。快速地用二进制表示长整数变得不切实际。
因此您的表可能表示为:
uint8_t row[] = { 0xd3, // 11010011
0x53, // 01010011
0x80 // 10000000
} ;
然后按以下方式设置/清除位:
row[2] |= mask ; // Set mask bits
row[0] &= mask ; // Clear mask bits
要创建指定编号位的掩码而不对十六进制值进行硬编码,可以使用以下表达式:
uint8_t mask = 1<<7 | 1<<5 | 1<<0 ; // 10100001 mask bits 0, 5 & 7
有时候需要“可视”二进制表示形式-例如,对于字符位图,当用二进制表示时,字符A更容易可视化:
00000000
00011000
00100100
01000010
01111110
01000010
01000010
00000000
通过为每个二进制值穷举定义一个宏,可以在保持“可视化”的同时有效地编码此类表;例如:
#define B_00000000 0x00
#define B_00000001 0x01
#define B_00000010 0x02
#define B_00000011 0x03
#define B_00000100 0x04
...
#define B_11111110 0xfe
#define B_11111111 0xff
请注意,要创建上述宏,最好编写一个代码生成器-即生成代码的程序,然后将这些宏放在头文件中。
鉴于此类宏,您可以将表表示为:
uint8_t row[] = { B_11010011
B_01010011
B_10000000
} ;
或A的字符位图:
uint8_t charA[] = { B_00000000,
B_00011000,
B_00100100,
B_01000010,
B_01111110,
B_01000010,
B_01000010,
B_00000000 } ;
如果在运行时串行接收到这些位,则可以使用顺序掩码和移位来构建相应的uint8_t
:
uint8_t getByte()
{
uint8_t mask = 0x80 ;
uint8_y byte = 0 ;
while( mask != 0 )
{
uint8_t bit = getBit() ;
byte |= bit ? mask : 0 ;
mask >>= 1 ;
}
return byte ;
}
您需要定义getBit()
函数的作用;例如,它可以读取文件,字符串或键盘输入,但必须返回零或非零或分别返回二进制数字0
和1
。如果首先接收到LSB的数据,则掩码从0x01开始,而改用<<
移位。