-
Notifications
You must be signed in to change notification settings - Fork 0
/
i2c-test.ino
254 lines (225 loc) · 6.3 KB
/
i2c-test.ino
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
/*
I2C test routine
Sidney McHarg
September 28, 2021
*/
#define VERSION "Vrs 0.1e"
#define MODE_PIN 3 // tie to ground if device is slave
#define SLAVE_ADDRESS 0 // default slave address, if 0 will be assigned dynamically
byte slaveAddress = SLAVE_ADDRESS;
#include "stdio.h"
#include <Wire.h>
// Wire.h includes a define for BUFFER_LENGTH, the size of the buffer, and hence maximum data
// payload which can be handled. MAX_LEN is defined to be twice that in order to test for
// boundary conditions
#define MAX_LEN BUFFER_LENGTH*2
byte buffer[MAX_LEN];
// Wire.endTransmission return values
#define WIRE_NOERROR 0 // no error
#define WIRE_TOOLONG 1 // too much data for buffer
#define WIRE_NAKADDRESS 2 // nak on address transmit
#define WIRE_NAKDATA 3 // nak on data transmit
#define WIRE_OTHER 4 // some other error
boolean mode; // master or slave
//function declarations
void wireRequest(void);
void wireReceive(int len);
void scanBus(void);
void performTest(void);
void printBuffer(byte buffer[],size_t len);
String hexString(byte b);
void flashLED(byte ledstate);
void setup()
{
Serial.begin(115200);
while (!Serial);
Serial.println("\nI2C Test " VERSION);
Serial.println("Wire BUFFER_LENGTH = " + String(BUFFER_LENGTH));
// set activity LED
pinMode(LED_BUILTIN,OUTPUT);
flashLED(LOW);
// determine role
pinMode(MODE_PIN, INPUT_PULLUP);
mode = digitalRead(MODE_PIN);
Serial.print("Operating as ");
Serial.println((mode ? "Master" : "Slave"));
if (!mode)
{
// slave
if (slaveAddress == 0)
{
slaveAddress = random(1,126);
}
Serial.println("Slave address set to 0x" + hexString(slaveAddress));
Wire.begin(slaveAddress);
Wire.onRequest(wireRequest);
Wire.onReceive(wireReceive);
// slave work all performed by call backs
return;
}
else
{
// master
Wire.begin();
scanBus();
performTest();
Serial.println("Tests completed\nReset master node to repeat");
}
}
void loop()
{
// slave will loop here with work being done in the call backs
;
}
void wireRequest()
{
// slave has received a request
flashLED(HIGH);
Serial.print("Request received, replying with ");
/*
size_t reqlen = Wire.available();
Serial.print(reqlen);
Serial.println(" bytes");
if (reqlen > MAX_LEN)
reqlen = MAX_LEN;
size_t rslt = Wire.readBytes(buffer,reqlen);
*/
size_t rslt = Wire.write(buffer, 32);
Serial.println(String(rslt) + " bytes");
if (Wire.getWriteError())
{
Serial.println("WriteError reported");
Wire.clearWriteError();
}
printBuffer(buffer,rslt);
flashLED(LOW);
}
void wireReceive(int len)
{
// slave has received data
flashLED(HIGH);
Serial.print("Data received, ");
Serial.print("length = " + String(len));
size_t reclen = Wire.available();
Serial.print(", available = " + String(reclen));
Serial.println(" bytes");
if (reclen > MAX_LEN)
reclen = MAX_LEN;
size_t rslt = Wire.readBytes(buffer,reclen);
printBuffer(buffer,rslt);
flashLED(LOW);
}
void scanBus()
{
// scans for i2c devices
int deviceCount = 0;
for (byte address = 0x1; address < 0x7f; address++)
{
Wire.beginTransmission(address);
byte error = Wire.endTransmission();
// check status
switch (error)
{
case WIRE_NOERROR:
// found a responsive device
if (deviceCount == 0)
Serial.println("Found devices at addresses:");
Serial.println(hexString(address));
slaveAddress = address;
deviceCount++;
break;
case WIRE_OTHER:
Serial.print("Uknown error at ");
Serial.println(hexString(address));
break;
default:
// not present
break;
}
}
if (deviceCount == 0)
{
Serial.println("No devices found");
}
}
void performTest()
{
size_t sz;
Serial.println("Will use 0x" + hexString(slaveAddress) + " as slave device");
// initialize buffer
for (sz = 0; sz < MAX_LEN; sz++)
buffer[sz] = sz;
// perform transmission tests
Serial.println("\nPerforming transmit to slave tests");
for (sz = 1; sz <= MAX_LEN; sz *= 2)
{
flashLED(HIGH);
Wire.beginTransmission(slaveAddress);
//Wire.write(buffer,sz);
for (size_t i = 0; i < sz; i++)
Wire.write(buffer[i]);
byte error = Wire.endTransmission();
flashLED(LOW);
Serial.print("Write of " + String(sz) + " ");
switch (error)
{
case WIRE_NOERROR:
Serial.println("OK");
break;
case WIRE_TOOLONG:
Serial.println("Write too long");
break;
case WIRE_NAKADDRESS:
Serial.println("NAK on address");
break;
case WIRE_NAKDATA:
Serial.println("NAK on data");
break;
default:
Serial.println("Unknown error: " + hexString(error));
break;
}
if (Wire.getWriteError())
{
Serial.println("WriteError reported");
Wire.clearWriteError();
}
delay(500);
}
// perform requestFrom test
Serial.println("\nPerforming requestFrom slave tests");
for (sz = 1; sz <= MAX_LEN; sz *= 2)
{
flashLED(HIGH);
size_t rslt = Wire.requestFrom(slaveAddress,sz);
Serial.println("Requestfrom for " + String(sz) + " read " + String(rslt));
Wire.readBytes(buffer,rslt);
flashLED(LOW);
printBuffer(buffer,rslt);
delay(500);
}
}
void printBuffer(byte buffer[],size_t len)
{
size_t i;
for (i = 0; i < len; i++)
{
Serial.print(hexString(buffer[i]));
if (((i%16) == 15))
Serial.print("\n");
else
Serial.print(" ");
}
if ((i%16) != 0)
Serial.println();
}
static char hexDigits[] =
{"0123456789abcdef"};
String hexString(byte b)
{
return(String(hexDigits[b>>4]) + String(hexDigits[b&0xf]));
}
inline void flashLED(byte ledstate)
{
digitalWrite(LED_BUILTIN,ledstate);
}