我正在运行下面的代码,在Arduino UNO rev3上执行I2C环回接口。 Arduino板充当I2C总线中的从器件,在接收到数据包后,它会引发一条线,触发主器件的读操作。 Arduino只是回答了它首先收到的相同数据。以下代码似乎运作良好:
#include <stdint.h>
#include <Wire.h>
#ifndef cbi
#define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit))
#endif
#define I2C_DATA_SIZE 350
#define I2C_IRQ_PIN 13
typedef struct {
uint8_t data[I2C_DATA_SIZE];
uint16_t count;
uint16_t size;
bool ready;
} i2c_packet_t;
static i2c_packet_t i2c_pkt;
void setup() {
Serial.begin(115200); // start serial for output
Wire.begin(0x29); // join i2c bus with address #8
Wire.onReceive(receiveEvent); // register event
Wire.onRequest(requestEvent);
memset(&i2c_pkt, 0, sizeof(i2c_packet_t));
pinMode(I2C_IRQ_PIN, OUTPUT);
digitalWrite(I2C_IRQ_PIN, false);
/* Disable internall pullups */
#if defined(__AVR_ATmega168__) || defined(__AVR_ATmega8__) || defined(__AVR_ATmega328P__)
// deactivate internal pull-ups for twi
// as per note from atmega8 manual pg167
cbi(PORTC, 4);
cbi(PORTC, 5);
#else
// deactivate internal pull-ups for twi
// as per note from atmega128 manual pg204
cbi(PORTD, 0);
cbi(PORTD, 1);
#endif
}
void loop() {
digitalWrite(I2C_IRQ_PIN, i2c_pkt.ready);
delay(100);
}
void requestEvent(void) {
digitalWrite(I2C_IRQ_PIN, false);
Wire.write(i2c_pkt.data, i2c_pkt.size);
memset(&i2c_pkt, 0, sizeof(i2c_packet_t));
}
void receiveEvent(int howMany) {
if (i2c_pkt.count == I2C_DATA_SIZE) {
Serial.println("I2C packet too large");
}
for (int i = 0; i < howMany; i++) {
i2c_pkt.data[i2c_pkt.count++] = Wire.read();
if (i2c_pkt.count == 2) {
i2c_pkt.size = (i2c_pkt.data[0] << 8) | i2c_pkt.data[1];
i2c_pkt.ready = true;
}
}
}
我知道Wire回调在I2C中断上运行,所以我试图将Wire.write()
位移到loop()
。我只是在i2c_packet_t
中添加了请求,现在loop()
和requestEvent()
看起来像这样:
void loop() {
digitalWrite(I2C_IRQ_PIN, !i2c_pkt.request && i2c_pkt.ready);
if (i2c_pkt.request) {
if (i2c_pkt.ready) {
digitalWrite(I2C_IRQ_PIN, false);
Wire.write(i2c_pkt.data, i2c_pkt.size);
memset(&i2c_pkt, 0, sizeof(i2c_packet_t));
} else {
Serial.println("ERROR: I2C request but no data available");
}
}
}
void requestEvent(void) {
i2c_pkt.request = true;
}
出于某种原因,该解决方案不起作用:主设备始终接收&#34; 0xFF&#34;。我使用Nordic开发板作为主机,它作为SDA和SCL线路上的内部上拉电阻。
这让我很困惑,所以欢迎任何想法。