使用 C++ 和 i2c-tools 写入和读取虚拟 i2c
Writing and reading from a virtual i2c using C++ and i2c-tools
我正在尝试使用 C++ 写入和读取 I2C 总线。我的I2C总线是虚拟的,第一件事就是加载内核模块i2c_stub。我可以通过 bash 做所有事情,现在我将它移植到 C++。我可以打开i2c总线,获取特定地址的i2c总线,但是不能读写。
我正在虚拟化 /dev/i2c-3
。这些是我在 bash:
中执行的命令
sudo make -C /lib/modules/$(uname -r)/build M=$(pwd) clean
sudo make -C /lib/modules/$(uname -r)/build M=$(pwd) modules
sudo make -C /lib/modules/$(uname -r)/build M=$(pwd) modules_install
sudo modprobe -r i2c_stub
sudo insmod i2c-stub.ko chip_addr=0x20
sudo i2cset -y 3 0x20 0x00 0x01
sudo i2cget -y 3 0x20 0x00
这是 C++ 代码。写作失败了,如果我把它改成第一,阅读也失败了。当我使用 ioctl
和地址 I2C_SLAVE, 0x20
时,我不确定是不是。我不知道在哪里使用地址 0x00
.
TEST_F(I2CTest, TestReadAndWriteI2C) {
// ------- LOAD i2c_stub KERNEL MODULE -------
char *params;
int fd;
size_t image_size;
struct stat st;
void *image;
// command: sudo insmod /root/i2c-tests/i2c-stub.ko chip_addr=0x20
params = "chip_addr=0x20";
fd = open("/root/i2c-tests/i2c-stub.ko", O_RDONLY);
fstat(fd, &st);
image_size = st.st_size;
image = malloc(image_size);
read(fd, image, image_size);
close(fd);
if (init_module(image, image_size, params) != 0) {
perror("init_module");
std::cout
<< "Please make sure that the following commands were executed " <<
"on the directory [/root/i2c-tests/] before to run the unit test TestAddKernelModule " <<
"and the file [/root/i2c-tests/i2c-stub.ko] exists." << std::endl;
std::cout << "sudo rmmod i2c_stub" << std::endl;
std::cout << "sudo make -C /lib/modules/$(uname -r)/build M=$(pwd) clean" << std::endl;
std::cout << "sudo make -C /lib/modules/$(uname -r)/build M=$(pwd) modules" << std::endl;
std::cout << "sudo make -C /lib/modules/$(uname -r)/build M=$(pwd) modules_install" << std::endl;
GTEST_FAIL();
}
free(image);
GTEST_SUCCESS_("Kernel module loaded.");
//----- OPEN THE I2C BUS -----
int file_i2c = open("/dev/i2c-3", O_RDWR);
ASSERT_GT(file_i2c, 0);
if (file_i2c < 0) {
GTEST_FAIL(); // Failed to open the i2c bus
} else {
// std::cout << "Opened i2c port: /dev/i2c-3" << std::endl;
GTEST_SUCCESS_("Opened i2c port: /dev/i2c-3");
}
// <<<<< The I2C address of the slave
if (ioctl(file_i2c, I2C_SLAVE, 0x20) < 0) {
std::cout << "ioctl error: " << strerror(errno) << std::endl;
GTEST_FAIL(); // Failed to acquire bus access and/or talk to slave
} else {
std::cout << "Acquired bus access to i2c address: " << I2C_ADDR << std::endl;
GTEST_SUCCESS_("Acquired bus access to i2c address: " + I2C_ADDR);
}
//----- WRITE BYTES -----
char bufferToWrite[1];
bufferToWrite[0] = 0x01;
// <<< Number of bytes to write
if (write(file_i2c, bufferToWrite, 1) != 1) {
GTEST_FAIL(); // Failed to write to the i2c bus
} else {
GTEST_SUCCESS_("success writing on i2c");
}
//----- READ BYTES -----
char bufferToRead[1];
int numberOfBytesRead = read(file_i2c, bufferToRead, 1);
std::cout << "Data read: " << bufferToRead[0] << std::endl;
printf("0x%02X\n", bufferToRead[0]);
GTEST_SUCCESS_("Data read: " + bufferToRead[0]);
}
我解决了 wiringPiI2C (https://github.com/WiringPi/WiringPi/blob/master/wiringPi/wiringPiI2C.c) 的工作原理并修改了我的代码中的几个点。
TEST_F(I2CTest, TestReadAndWriteI2C) {
// ------- LOAD i2c_stub KERNEL MODULE -------
char *params;
int fd;
size_t image_size;
struct stat st;
void *image;
// command: sudo insmod /root/i2c-tests/i2c-stub.ko chip_addr=0x20
params = "chip_addr=0x20";
fd = open("/root/i2c-tests/i2c-stub.ko", O_RDONLY);
fstat(fd, &st);
image_size = st.st_size;
image = malloc(image_size);
read(fd, image, image_size);
close(fd);
if (init_module(image, image_size, params) != 0) {
perror("init_module");
std::cout
<< "Please make sure that the following commands were executed " <<
"on the directory [/root/i2c-tests/] before to run the unit test TestAddKernelModule " <<
"and the file [/root/i2c-tests/i2c-stub.ko] exists." << std::endl;
std::cout << "sudo rmmod i2c_stub" << std::endl;
std::cout << "sudo make -C /lib/modules/$(uname -r)/build M=$(pwd) clean" << std::endl;
std::cout << "sudo make -C /lib/modules/$(uname -r)/build M=$(pwd) modules" << std::endl;
std::cout << "sudo make -C /lib/modules/$(uname -r)/build M=$(pwd) modules_install" << std::endl;
GTEST_FAIL();
}
free(image);
GTEST_SUCCESS_("Kernel module loaded.");
// This initialises the I2C system with your given device identifier.
int i2cFileDescriptor;
if ((i2cFileDescriptor = open("/dev/i2c-3", O_RDWR)) < 0) {
GTEST_FAIL();
}
if (ioctl(i2cFileDescriptor, I2C_SLAVE, 0x20) < 0) {
GTEST_FAIL();
}
// Write bytes on I2C bus
union i2c_smbus_data data;
data.byte = 5;
i2c_smbus_access(i2cFileDescriptor, I2C_SMBUS_WRITE, 0x00, I2C_SMBUS_BYTE_DATA, &data);
// Read bytes from I2C bus
union i2c_smbus_data dataRead;
if (i2c_smbus_access(i2cFileDescriptor, I2C_SMBUS_READ, 0x00, I2C_SMBUS_BYTE_DATA, &dataRead)) {
GTEST_FAIL();
} else {
ASSERT_EQ(data.byte, dataRead.byte);
std::cout << "Read: " << std::hex << static_cast<int>(dataRead.byte ) << std::endl;
std::cout << "Read: " << (int) dataRead.byte << std::endl;
GTEST_SUCCESS_("Read bytes from I2C bus.");
}
// Write word on I2C bus
data.word = 556;
i2c_smbus_access(i2cFileDescriptor, I2C_SMBUS_WRITE, 0x00, I2C_SMBUS_WORD_DATA, &data);
// Read word from I2C bus
union i2c_smbus_data wordRead;
if (i2c_smbus_access(fd, I2C_SMBUS_READ, 0x00, I2C_SMBUS_WORD_DATA, &wordRead)) {
GTEST_FAIL();
} else {
ASSERT_EQ(data.word, wordRead.word);
std::cout << "Read: " << std::hex << static_cast<int>(wordRead.word ) << std::endl;
std::cout << "Read: " << (int) wordRead.word << std::endl;
std::cout << "Read: " << wordRead.word << std::endl;
GTEST_SUCCESS_("Read word from I2C bus.");
}
// return data.word & 0xFFFF ;
}
我正在尝试使用 C++ 写入和读取 I2C 总线。我的I2C总线是虚拟的,第一件事就是加载内核模块i2c_stub。我可以通过 bash 做所有事情,现在我将它移植到 C++。我可以打开i2c总线,获取特定地址的i2c总线,但是不能读写。
我正在虚拟化 /dev/i2c-3
。这些是我在 bash:
sudo make -C /lib/modules/$(uname -r)/build M=$(pwd) clean
sudo make -C /lib/modules/$(uname -r)/build M=$(pwd) modules
sudo make -C /lib/modules/$(uname -r)/build M=$(pwd) modules_install
sudo modprobe -r i2c_stub
sudo insmod i2c-stub.ko chip_addr=0x20
sudo i2cset -y 3 0x20 0x00 0x01
sudo i2cget -y 3 0x20 0x00
这是 C++ 代码。写作失败了,如果我把它改成第一,阅读也失败了。当我使用 ioctl
和地址 I2C_SLAVE, 0x20
时,我不确定是不是。我不知道在哪里使用地址 0x00
.
TEST_F(I2CTest, TestReadAndWriteI2C) {
// ------- LOAD i2c_stub KERNEL MODULE -------
char *params;
int fd;
size_t image_size;
struct stat st;
void *image;
// command: sudo insmod /root/i2c-tests/i2c-stub.ko chip_addr=0x20
params = "chip_addr=0x20";
fd = open("/root/i2c-tests/i2c-stub.ko", O_RDONLY);
fstat(fd, &st);
image_size = st.st_size;
image = malloc(image_size);
read(fd, image, image_size);
close(fd);
if (init_module(image, image_size, params) != 0) {
perror("init_module");
std::cout
<< "Please make sure that the following commands were executed " <<
"on the directory [/root/i2c-tests/] before to run the unit test TestAddKernelModule " <<
"and the file [/root/i2c-tests/i2c-stub.ko] exists." << std::endl;
std::cout << "sudo rmmod i2c_stub" << std::endl;
std::cout << "sudo make -C /lib/modules/$(uname -r)/build M=$(pwd) clean" << std::endl;
std::cout << "sudo make -C /lib/modules/$(uname -r)/build M=$(pwd) modules" << std::endl;
std::cout << "sudo make -C /lib/modules/$(uname -r)/build M=$(pwd) modules_install" << std::endl;
GTEST_FAIL();
}
free(image);
GTEST_SUCCESS_("Kernel module loaded.");
//----- OPEN THE I2C BUS -----
int file_i2c = open("/dev/i2c-3", O_RDWR);
ASSERT_GT(file_i2c, 0);
if (file_i2c < 0) {
GTEST_FAIL(); // Failed to open the i2c bus
} else {
// std::cout << "Opened i2c port: /dev/i2c-3" << std::endl;
GTEST_SUCCESS_("Opened i2c port: /dev/i2c-3");
}
// <<<<< The I2C address of the slave
if (ioctl(file_i2c, I2C_SLAVE, 0x20) < 0) {
std::cout << "ioctl error: " << strerror(errno) << std::endl;
GTEST_FAIL(); // Failed to acquire bus access and/or talk to slave
} else {
std::cout << "Acquired bus access to i2c address: " << I2C_ADDR << std::endl;
GTEST_SUCCESS_("Acquired bus access to i2c address: " + I2C_ADDR);
}
//----- WRITE BYTES -----
char bufferToWrite[1];
bufferToWrite[0] = 0x01;
// <<< Number of bytes to write
if (write(file_i2c, bufferToWrite, 1) != 1) {
GTEST_FAIL(); // Failed to write to the i2c bus
} else {
GTEST_SUCCESS_("success writing on i2c");
}
//----- READ BYTES -----
char bufferToRead[1];
int numberOfBytesRead = read(file_i2c, bufferToRead, 1);
std::cout << "Data read: " << bufferToRead[0] << std::endl;
printf("0x%02X\n", bufferToRead[0]);
GTEST_SUCCESS_("Data read: " + bufferToRead[0]);
}
我解决了 wiringPiI2C (https://github.com/WiringPi/WiringPi/blob/master/wiringPi/wiringPiI2C.c) 的工作原理并修改了我的代码中的几个点。
TEST_F(I2CTest, TestReadAndWriteI2C) {
// ------- LOAD i2c_stub KERNEL MODULE -------
char *params;
int fd;
size_t image_size;
struct stat st;
void *image;
// command: sudo insmod /root/i2c-tests/i2c-stub.ko chip_addr=0x20
params = "chip_addr=0x20";
fd = open("/root/i2c-tests/i2c-stub.ko", O_RDONLY);
fstat(fd, &st);
image_size = st.st_size;
image = malloc(image_size);
read(fd, image, image_size);
close(fd);
if (init_module(image, image_size, params) != 0) {
perror("init_module");
std::cout
<< "Please make sure that the following commands were executed " <<
"on the directory [/root/i2c-tests/] before to run the unit test TestAddKernelModule " <<
"and the file [/root/i2c-tests/i2c-stub.ko] exists." << std::endl;
std::cout << "sudo rmmod i2c_stub" << std::endl;
std::cout << "sudo make -C /lib/modules/$(uname -r)/build M=$(pwd) clean" << std::endl;
std::cout << "sudo make -C /lib/modules/$(uname -r)/build M=$(pwd) modules" << std::endl;
std::cout << "sudo make -C /lib/modules/$(uname -r)/build M=$(pwd) modules_install" << std::endl;
GTEST_FAIL();
}
free(image);
GTEST_SUCCESS_("Kernel module loaded.");
// This initialises the I2C system with your given device identifier.
int i2cFileDescriptor;
if ((i2cFileDescriptor = open("/dev/i2c-3", O_RDWR)) < 0) {
GTEST_FAIL();
}
if (ioctl(i2cFileDescriptor, I2C_SLAVE, 0x20) < 0) {
GTEST_FAIL();
}
// Write bytes on I2C bus
union i2c_smbus_data data;
data.byte = 5;
i2c_smbus_access(i2cFileDescriptor, I2C_SMBUS_WRITE, 0x00, I2C_SMBUS_BYTE_DATA, &data);
// Read bytes from I2C bus
union i2c_smbus_data dataRead;
if (i2c_smbus_access(i2cFileDescriptor, I2C_SMBUS_READ, 0x00, I2C_SMBUS_BYTE_DATA, &dataRead)) {
GTEST_FAIL();
} else {
ASSERT_EQ(data.byte, dataRead.byte);
std::cout << "Read: " << std::hex << static_cast<int>(dataRead.byte ) << std::endl;
std::cout << "Read: " << (int) dataRead.byte << std::endl;
GTEST_SUCCESS_("Read bytes from I2C bus.");
}
// Write word on I2C bus
data.word = 556;
i2c_smbus_access(i2cFileDescriptor, I2C_SMBUS_WRITE, 0x00, I2C_SMBUS_WORD_DATA, &data);
// Read word from I2C bus
union i2c_smbus_data wordRead;
if (i2c_smbus_access(fd, I2C_SMBUS_READ, 0x00, I2C_SMBUS_WORD_DATA, &wordRead)) {
GTEST_FAIL();
} else {
ASSERT_EQ(data.word, wordRead.word);
std::cout << "Read: " << std::hex << static_cast<int>(wordRead.word ) << std::endl;
std::cout << "Read: " << (int) wordRead.word << std::endl;
std::cout << "Read: " << wordRead.word << std::endl;
GTEST_SUCCESS_("Read word from I2C bus.");
}
// return data.word & 0xFFFF ;
}