Raspberry Pi I2C
Raspberry Pi I2C
我有多个使用 I2C 来回通信的 arduino。主机写两个字节,然后读回 1 个字节的响应。一切都很好,万岁。但现在我一直在努力将我的 master 切换到 Raspberry Pi。我编写的代码没有问题,但每 200 个中有 1 个 read/write,它 return 偶尔会出现错误读取,这将严重影响系统的可靠性。我附上我的代码,以防万一有人看到我做错了什么,或者如果其他人 运行 之前遇到过类似问题。
RPi C++代码:
#include <iostream>
#include <fstream>
#include <unistd.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <linux/i2c.h>
#include <linux/i2c-dev.h>
#include "../HaMiD_Lib/StopWatch.h"
using namespace std;
int file_i2c;
int length;
uint8_t buffer[2] = {0};
int timingLoopFreq = 500;
int timingLoopMicroSeconds = 1000000 / timingLoopFreq; //500 us
StopWatch loopTime(timingLoopMicroSeconds); // My own stopwatch livrary
uint8_t addr = 0x11;
using namespace std;
int main(void)
{
//-------------- OPEN THE I2C BUS--------------------------
char *filename = (char*)"/dev/i2c-1";
if((file_i2c = open(filename, O_RDWR))< 0 ){
//ERROR HANDLING: you can check errno to see what went wrong;
cout << "Failed to open the i2c bus" << endl;
return 0;
}
while(1){
if (loopTime.check()) {
loopTime.reset();
if (ioctl(file_i2c, I2C_SLAVE, addr) < 0){
cout << "Failed to acquire bus access and/or talk to slave" << endl;
//ERROR HANDLING: you can check errno to see what went wrong;
}
// ------------- WRITE BYTES -------------
buffer[0] = 4;
buffer[1] = 0;
length = 2; //<<<<< Number of bytes to write
if (write(file_i2c, buffer, length) != length){ // write() returns the number of bytes actually written, if it doesn't match then an error occurred (e.g. no response from the device)
// ERROR HANDLING: i2c transaction failed
cout << "Failed to write to the i2c bus " << endl;
} else {
// ------------ READ BYTES -------
length = 1;
if (read(file_i2c, buffer, length) != length){ // read() returns the number of bytes actually read, if it doesn't match then an error occurred (e.g. no response from the device)
//ERROR HANDLING: i2c transaction failed
cout <<"Failed to read from the i2c bus" << endl;
} else {
cout << "Data read:" << buffer[0] << endl;
}
}
}
}
cout << "exiting" << endl;
return 0;
}
Arduino I2C 片段:
//I2C functions
void receiveEvent(int byteCount) {
while (Wire.available()) {
I2C_cmd_1st = Wire.read(); // 1 byte (maximum 256 commands)
I2C_cmd_2nd = Wire.read(); // 1 byte (maximum 256 commands)
}
}
void slavesRespond() {
byte returnValue = 0;
switch (I2C_cmd_1st) {
case status_cmd: // 40
returnValue = module;
if (module == DONE) {
module = STOP; //reset the machine
}
break;
case test_cmd:
returnValue = ID;
break;
}
Wire.write(returnValue); // return response to last command
}
这里是 cout 输出的一小部分。读取的数据应始终 return 2 但有时(100 分之一)它无法从 i2c 总线读取或写入,有时(500 分之一)它 return 是一个错误的值(在下面的示例中它应该 return 2 但有时 return 3 是偶然的,也可能是 97 等)。
Data read:2
Data read:3 //This is wrong!
Data read:2
Failed to read from the i2c bus
Failed to read from the i2c bus
Data read:3 //This is wrong!
Data read:2
如有任何帮助,我们将不胜感激。有没有其他人看到过与 RPi 和 Arduino 类似的东西?接线非常简单,因为 RPi 是主机。
您是否尝试过在接收事件中只读取实际可用的我的数据。代码考虑到 receiveEvent
中的 byteCount
可以被 2 整除。
对于无法读取 i2c 总线的问题尝试
dtoverlay=i2c-gpio,i2c_gpio_sda=2,i2c_gpio_scl=3,i2c_gpio_delay_us=2,bus=1
代替
dtparam=i2c_arm=on
在 /boot/config.txt
我有多个使用 I2C 来回通信的 arduino。主机写两个字节,然后读回 1 个字节的响应。一切都很好,万岁。但现在我一直在努力将我的 master 切换到 Raspberry Pi。我编写的代码没有问题,但每 200 个中有 1 个 read/write,它 return 偶尔会出现错误读取,这将严重影响系统的可靠性。我附上我的代码,以防万一有人看到我做错了什么,或者如果其他人 运行 之前遇到过类似问题。
RPi C++代码:
#include <iostream>
#include <fstream>
#include <unistd.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <linux/i2c.h>
#include <linux/i2c-dev.h>
#include "../HaMiD_Lib/StopWatch.h"
using namespace std;
int file_i2c;
int length;
uint8_t buffer[2] = {0};
int timingLoopFreq = 500;
int timingLoopMicroSeconds = 1000000 / timingLoopFreq; //500 us
StopWatch loopTime(timingLoopMicroSeconds); // My own stopwatch livrary
uint8_t addr = 0x11;
using namespace std;
int main(void)
{
//-------------- OPEN THE I2C BUS--------------------------
char *filename = (char*)"/dev/i2c-1";
if((file_i2c = open(filename, O_RDWR))< 0 ){
//ERROR HANDLING: you can check errno to see what went wrong;
cout << "Failed to open the i2c bus" << endl;
return 0;
}
while(1){
if (loopTime.check()) {
loopTime.reset();
if (ioctl(file_i2c, I2C_SLAVE, addr) < 0){
cout << "Failed to acquire bus access and/or talk to slave" << endl;
//ERROR HANDLING: you can check errno to see what went wrong;
}
// ------------- WRITE BYTES -------------
buffer[0] = 4;
buffer[1] = 0;
length = 2; //<<<<< Number of bytes to write
if (write(file_i2c, buffer, length) != length){ // write() returns the number of bytes actually written, if it doesn't match then an error occurred (e.g. no response from the device)
// ERROR HANDLING: i2c transaction failed
cout << "Failed to write to the i2c bus " << endl;
} else {
// ------------ READ BYTES -------
length = 1;
if (read(file_i2c, buffer, length) != length){ // read() returns the number of bytes actually read, if it doesn't match then an error occurred (e.g. no response from the device)
//ERROR HANDLING: i2c transaction failed
cout <<"Failed to read from the i2c bus" << endl;
} else {
cout << "Data read:" << buffer[0] << endl;
}
}
}
}
cout << "exiting" << endl;
return 0;
}
Arduino I2C 片段:
//I2C functions
void receiveEvent(int byteCount) {
while (Wire.available()) {
I2C_cmd_1st = Wire.read(); // 1 byte (maximum 256 commands)
I2C_cmd_2nd = Wire.read(); // 1 byte (maximum 256 commands)
}
}
void slavesRespond() {
byte returnValue = 0;
switch (I2C_cmd_1st) {
case status_cmd: // 40
returnValue = module;
if (module == DONE) {
module = STOP; //reset the machine
}
break;
case test_cmd:
returnValue = ID;
break;
}
Wire.write(returnValue); // return response to last command
}
这里是 cout 输出的一小部分。读取的数据应始终 return 2 但有时(100 分之一)它无法从 i2c 总线读取或写入,有时(500 分之一)它 return 是一个错误的值(在下面的示例中它应该 return 2 但有时 return 3 是偶然的,也可能是 97 等)。
Data read:2
Data read:3 //This is wrong!
Data read:2
Failed to read from the i2c bus
Failed to read from the i2c bus
Data read:3 //This is wrong!
Data read:2
如有任何帮助,我们将不胜感激。有没有其他人看到过与 RPi 和 Arduino 类似的东西?接线非常简单,因为 RPi 是主机。
您是否尝试过在接收事件中只读取实际可用的我的数据。代码考虑到 receiveEvent
中的 byteCount
可以被 2 整除。
对于无法读取 i2c 总线的问题尝试
dtoverlay=i2c-gpio,i2c_gpio_sda=2,i2c_gpio_scl=3,i2c_gpio_delay_us=2,bus=1
代替
dtparam=i2c_arm=on
在 /boot/config.txt