想知道关于I²C寄存器映射的最佳实践是什么,或者更喜欢其他人使用的。最佳常见问题I2C寄存器映射图
到目前为止,我通常会做很多的定义,每个寄存器一个,所有的位,掩码,移位等。 但是,最近我看到一些驱动程序使用(可能打包)结构的定义。我认为这些是Linux内核模块。
无论如何,他们会
struct i2c_sensor_fuu_registers {
uint8_t id;
uint16_t big_register;
uint8_t another_register;
...
} __attribute__((packed));
然后,他们会使用offsetof(或宏)来获得I2C寄存器和使用sizeof对要读取的字节数。
我发现,这两种方法都有其优点:
结构的方法:
- (+)寄存器的偏移都在逻辑上载,而不必拼出一个定义每个注册了一个结构里面。
- (+)使用适当大小的数据类型明确声明条目大小。 ( - )这没有考虑到广泛使用的位域
- ( - )这不包括没有字节映射的寄存器映射(例如LM75),其中一个从偏移量读取2个字节n + 0x00,而n + 0x01是另一个寄存器,而不是寄存器n的高/低字节0x00
- ( - )这不占地址空间中的大间隙(例如寄存器0x00,0x01,0x80, 0xAA,没有in-betweens ......)和(我认为?)依靠编译器优化来摆脱结构。
定义的方法:
- (+)与其比特沿所述寄存器中的每一个通常是在一个块中定义,使得找到正确的符号容易和依靠的命名约定。
- (+)透明/不知道地址空间差距。
- ( - )即使没有间隙,每个寄存器都必须单独定义
- ( - )因为定义通常是全局性的,所以名称通常很长,有点乱七八糟的源代码长符号名称。
- ( - )要读取的数据的大小通常是硬编码的幻数或(可能长符号名称的(结束 - 开始+ 1)型计算)。
- (o)透明/不知道数据大小与地图中的地址。
基本上,我正在寻找更聪明的方式来处理这些情况。我经常发现自己为每一个寄存器和每一位都输入了很多和很多令人费解的长符号名称,并且可能会掩盖和转换(后两种取决于数据类型),最终只使用其中的一些(但是讨厌稍后重新定义缺失的符号,这就是为什么我在一个会话中输入所有符号的原因)。 不过,我注意到要读取/写入的字节大小主要是幻数,通常需要并排读取数据表和源代码才能理解最基本的交互。
我想知道别人怎么处理这种情况?我在网上找到了一些例子,其中人们还艰苦地输入每一个单一的寄存器,等等在一个大头,但没有什么非常明确的......但是,上面的两个选项都不是太聪明在这一点:(
警告:http://stackoverflow.com/questions/6043483/why-bit-endianness-is-an-issue-in-bitfields和http://stackoverflow.com/questions/1490092/cc-force-bit字段顺序和对齐 –
ouch。这是杀手。我会在答案的最上面写一张便条。 – engineerC
感谢您的警告。我在想我自己:D – FRob