首先,我对这些东西不感兴趣,但是学习并且真的想使它起作用。我买了一个raspberrypi和一个bno055博世加速度计。它带有一个bno055.c,bno055.h和一个bno055_support.c文件。进入编程和c语言并学习/试用之后,似乎我需要以某种方式定义如何进行I2C读写。它需要进行设置,以便您可以定义读/写的字节数。在下面,您可以找到两个预定义的函数:
/* \Brief: The API is used as I2C bus write
* \Return : Status of the I2C write
* \param dev_addr : The device address of the sensor
* \param reg_addr : Address of the first register,
* will data is going to be written
* \param reg_data : It is a value hold in the array,
* will be used for write the value into the register
* \param cnt : The no of byte of data to be write
*/
s8 BNO055_I2C_bus_write(u8 dev_addr, u8 reg_addr, u8 *reg_data, u8 cnt)
{
s32 BNO055_iERROR = BNO055_INIT_VALUE;
u8 array[I2C_BUFFER_LEN];
u8 stringpos = BNO055_INIT_VALUE;
array[BNO055_INIT_VALUE] = reg_addr;
for (stringpos = BNO055_INIT_VALUE; stringpos < cnt; stringpos++)
array[stringpos + BNO055_I2C_BUS_WRITE_ARRAY_INDEX] =
*(reg_data + stringpos);
}
/*
* Please take the below APIs as your reference for
* write the data using I2C communication
* "BNO055_iERROR = I2C_WRITE_STRING(DEV_ADDR, ARRAY, CNT+1)"
* add your I2C write APIs here
* BNO055_iERROR is an return value of I2C read API
* Please select your valid return value
* In the driver BNO055_SUCCESS defined as 0
* and FAILURE defined as -1
* Note :
* This is a full duplex operation,
* The first read data is discarded, for that extra write operation
* have to be initiated. For that cnt+1 operation done
* in the I2C write string function
* For more information please refer data sheet SPI communication:
*/
return (s8)BNO055_iERROR;
}
/* \Brief: The API is used as I2C bus read
* \Return : Status of the I2C read
* \param dev_addr : The device address of the sensor
* \param reg_addr : Address of the first register,
* will data is going to be read
* \param reg_data : This data read from the sensor,
* which is hold in an array
* \param cnt : The no of byte of data to be read
*/
s8 BNO055_I2C_bus_read(u8 dev_addr, u8 reg_addr, u8 *reg_data, u8 cnt)
{
s32 BNO055_iERROR = BNO055_INIT_VALUE;
u8 array[I2C_BUFFER_LEN] = {BNO055_INIT_VALUE};
u8 stringpos = BNO055_INIT_VALUE;
array[BNO055_INIT_VALUE] = reg_addr;
/* Please take the below API as your reference
* for read the data using I2C communication
* add your I2C read API here.
* "BNO055_iERROR = I2C_WRITE_READ_STRING(DEV_ADDR,
* ARRAY, ARRAY, 1, CNT)"
* BNO055_iERROR is an return value of SPI write API
* Please select your valid return value
* In the driver BNO055_SUCCESS defined as 0
* and FAILURE defined as -1
*/
for (stringpos = BNO055_INIT_VALUE; stringpos < cnt; stringpos++)
*(reg_data + stringpos) = array[stringpos];
return (s8)BNO055_iERROR;
}
我的问题是有人可以指导我应对挑战吗? 我正在了解https://www.kernel.org/doc/Documentation/i2c/dev-interface,但暂时停留在这里。事先感谢您的阅读/回复。
答案 0 :(得分:2)
我最近为MMA8451 i2c加速度计写了library similar to what you're describing。
基本上,Linux中的i2c控制器被分配了一个设备节点(例如/dev/i2c-1
)。您将打开该设备节点作为文件like this:
int file = open(path, O_RDWR); //path = /dev/i2c-1
一旦有了文件句柄,就可以使用ioctl's读写i2c寄存器。 i2c内核模块支持I2C_RDWR ioctl,使您可以与i2c寄存器进行交互。
要阅读注册表,请执行something like this:
int mma8451_get_i2c_register(int file, unsigned char addr, unsigned char reg, unsigned char *val) {
unsigned char inbuf, outbuf;
struct i2c_rdwr_ioctl_data packets;
struct i2c_msg messages[2];
outbuf = reg;
messages[0].addr = addr;
messages[0].flags = 0;
messages[0].len = sizeof(outbuf);
messages[0].buf = &outbuf;
messages[1].addr = addr;
messages[1].flags = I2C_M_RD;
messages[1].len = sizeof(inbuf);
messages[1].buf = &inbuf;
packets.msgs = messages;
packets.nmsgs = 2;
if(ioctl(file, I2C_RDWR, &packets) < 0) {
return 0;
}
*val = inbuf;
return 1;
}
要编写寄存器,请执行something like this:
int mma8451_set_i2c_register(int file, unsigned char addr, unsigned char reg, unsigned char value) {
unsigned char outbuf[2];
struct i2c_rdwr_ioctl_data packets;
struct i2c_msg messages[1];
messages[0].addr = addr;
messages[0].flags = 0;
messages[0].len = sizeof(outbuf);
messages[0].buf = outbuf;
outbuf[0] = reg;
outbuf[1] = value;
packets.msgs = messages;
packets.nmsgs = 1;
if(ioctl(file, I2C_RDWR, &packets) < 0) {
return 0;
}
return 1;
}
编辑:I2C_RDWR
ioctl采用i2c_rdwr_ioctl_data
结构作为参数。是described like this:
另一个常见的数据结构是
struct i2c_rdwr_ioctl_data
这是I2C_RDWR ioctl调用中使用的结构
struct i2c_rdwr_ioctl_data { struct i2c_msg __user *msgs; /* pointers to i2c_msgs */ __u32 nmsgs; /* number of i2c_msgs */ };
(在linux / i2c-dev.h中定义) 该结构指向要处理的i2c_msg数组,并定义了数组中i2c_msg的数量。
用法: 如果程序要写入一个字节(例如-索引字节),则后跟 读取一个字节,将需要两个struct i2c_msg数据结构。 一个用于写入,另一个用于读取。这两个数据结构应声明为两个i2c_msg数据结构的数组。它们将按照出现在数组中的顺序进行处理。
i2c_rdwr_ioctl_data
结构包含一个指向i2c_msg
结构数组的指针。这些结构包含您要发送或接收的实际消息。例如,我的加速度计要读取寄存器,我首先需要将要读取的寄存器写入设备,然后才能读取它(因此为什么我的读取功能中有两个i2c_msg
)。如果我只是写一个寄存器,我只需要一个。
您将要参考data sheet for your BNO055来确切地确定哪些寄存器执行了什么操作。
以您的示例为例,它似乎来自bno055_support.c。看起来这只是您要实现的一组存根。看起来基本上是一个真实界面的模拟。因此重要的是接口,而不是实际的代码(因此不必担心cnt
)。重要的地方在这里:
s8 I2C_routine(void)
{
bno055.bus_write = BNO055_I2C_bus_write;
bno055.bus_read = BNO055_I2C_bus_read;
bno055.delay_msec = BNO055_delay_msek;
bno055.dev_addr = BNO055_I2C_ADDR1;
return BNO055_INIT_VALUE;
}
这会将设备结构上的函数指针设置为要定义的写入函数,并设置设备的地址和延迟。从那里,您需要实现与该接口匹配的功能:
#define BNO055_BUS_WRITE_FUNC(dev_addr, reg_addr, reg_data, wr_len)\
bus_write(dev_addr, reg_addr, reg_data, wr_len)
#define BNO055_BUS_READ_FUNC(dev_addr, reg_addr, reg_data, r_len)\
bus_read(dev_addr, reg_addr, reg_data, r_len)
我上面给你的功能应该很接近。祝你好运!
答案 1 :(得分:0)
例如
s8 BNO055_I2C_bus_read(u8 dev_addr, u8 reg_addr, u8 *reg_data, u8 cnt)
{
u8 array[I2C_BUFFER_LEN] = { BNO055_INIT_VALUE };
array[BNO055_INIT_VALUE] = reg_addr;
if (write(file, array, 1) != 1) {
return -1;
}
std::this_thread::sleep_for(std::chrono::milliseconds(50));
s8 res = read(file, reg_data, cnt);
if (res > 0) return 0;
else return -1;
}
s8 BNO055_I2C_bus_write(u8 dev_addr, u8 reg_addr, u8 *reg_data, u8 cnt)
{
char buf[1 + cnt];
buf[0] = reg_addr;
memcpy(&buf[1], reg_data, cnt);
if (write(file, buf, cnt+1) != cnt+1) {
return -1;
}
return 0;
}