IoT - Modular - I2C.cpp
Jump to navigation
Jump to search
#includes, Defines, etc...
1 #include "libraries.h"
2 #include "functions.h"
I2C_Test()
1 bool I2C_Test(int SDA, int SCL)
2 {
3 debug_SectionTitle("I2C Test &/or repair...");
4
5 bool SCL_state = (digitalRead(SCL) == HIGH);
6 bool SDA_state = (digitalRead(SDA) == HIGH);
7
8 if (SCL_state && SDA_state)
9 {
10 debug_LineOut("I2C is good.");
11 return (true);
12 }
13 else
14 {
15 if (!SCL_state)
16 debug_Trouble("SCL is LOW.");
17 if (!SDA_state)
18 debug_Trouble("SDA is LOW.");
19 debug_Action("Clearing I2C");
20
21 switch (I2C_ClearBus(SDA, SCL))
22 {
23 case 0:
24 debug_LineOut("I2C is clear.");
25 return (true);
26 break;
27 case 1:
28 debug_Trouble("I2C bus error. Could not clear");
29 debug_Trouble("SCL clock line held low");
30 break;
31 case 2:
32 debug_Trouble("I2C bus error. Could not clear SCL clock");
33 debug_Trouble("line held low by slave clock stretch");
34 break;
35 case 3:
36 debug_Trouble("I2C bus error. Could not clear");
37 debug_Trouble("SDA data line held low");
38 break;
39 }
40 debug_Trouble("++++++++++++++++ STOPPING!!! +++++++++++++++++");
41 while (true) // Slam on da brakes!
42 blinkLED(100);
43 return (false);
44 }
45 }
I2C_ClearBus()
1 /**
2 * This routine turns off the I2C bus and clears it
3 * on return SCA and SCL pins are tri-state inputs.
4 * You need to call Wire.begin() after this to re-enable I2C
5 * This routine does NOT use the Wire library at all.
6 *
7 * returns 0 if bus cleared
8 * 1 if SCL held low.
9 * 2 if SDA held low by slave clock stretch for > 2sec
10 * 3 if SDA held low after 20 clocks.
11 *
12 * Source: http://www.forward.com.au/pfod/ArduinoProgramming/I2C_ClearBus/index.html
13 */
14
15 int I2C_ClearBus(int SDA, int SCL)
16 {
17 #if defined(TWCR) && defined(TWEN)
18 TWCR &= ~(_BV(TWEN)); // Disable the Atmel 2-Wire interface
19 // so we can control the SDA and SCL pins directly
20 #endif
21
22 pinMode(SDA, INPUT_PULLUP); // Make SDA (data) and SCL (clock) pins Inputs with pullup.
23 pinMode(SCL, INPUT_PULLUP);
24
25 delay(2500); // Wait 2.5 secs. This is strictly only necessary on the first power
26 // up of the DS3231 module to allow it to initialize properly,
27 // but is also assists in reliable programming of FioV3 boards as it gives the
28 // IDE a chance to start uploaded the program
29 // before existing sketch confuses the IDE by sending Serial data.
30
31 boolean SCL_LOW = (digitalRead(SCL) == LOW); // Check is SCL is Low.
32 if (SCL_LOW)
33 { //If it is held low Arduno cannot become the I2C master.
34 return 1; //I2C bus error. Could not clear SCL clock line held low
35 }
36
37 boolean SDA_LOW = (digitalRead(SDA) == LOW); // vi. Check SDA input.
38 int clockCount = 20; // > 2x9 clock
39
40 while (SDA_LOW && (clockCount > 0))
41 { // vii. If SDA is Low,
42 clockCount--;
43 // Note: I2C bus is open collector so do NOT drive SCL or SDA high.
44 pinMode(SCL, INPUT); // release SCL pullup so that when made output it will be LOW
45 pinMode(SCL, OUTPUT); // then clock SCL Low
46 delayMicroseconds(10); // for >5uS
47 pinMode(SCL, INPUT); // release SCL LOW
48 pinMode(SCL, INPUT_PULLUP); // turn on pullup resistors again
49 // do not force high as slave may be holding it low for clock stretching.
50 delayMicroseconds(10); // for >5uS
51 // The >5uS is so that even the slowest I2C devices are handled.
52 SCL_LOW = (digitalRead(SCL) == LOW); // Check if SCL is Low.
53 int counter = 20;
54 while (SCL_LOW && (counter > 0))
55 { // loop waiting for SCL to become High only wait 2sec.
56 counter--;
57 delay(100);
58 SCL_LOW = (digitalRead(SCL) == LOW);
59 }
60 if (SCL_LOW)
61 { // still low after 2 sec error
62 return 2; // I2C bus error. Could not clear.
63 // SCL clock line held low by slave clock stretch for >2sec
64 }
65 SDA_LOW = (digitalRead(SDA) == LOW); // and check SDA input again and loop
66 }
67 if (SDA_LOW)
68 { // still low
69 return 3; // I2C bus error. Could not clear. SDA data line held low
70 }
71
72 // else pull SDA line low for Start or Repeated Start
73 pinMode(SDA, INPUT); // remove pullup.
74 pinMode(SDA, OUTPUT); // and then make it LOW i.e. send an I2C Start or Repeated start control.
75 // When there is only one I2C master a Start or Repeat Start
76 // has the same function as a Stop and clears the bus.
77 // A Repeat Start is a Start occurring after a Start with
78 // no intervening Stop.
79 delayMicroseconds(10); // wait >5uS
80 pinMode(SDA, INPUT); // remove output low
81 pinMode(SDA, INPUT_PULLUP); // and make SDA high i.e. send I2C STOP control.
82 delayMicroseconds(10); // x. wait >5uS
83 pinMode(SDA, INPUT); // and reset pins as tri-state inputs which is the default state on reset
84 pinMode(SCL, INPUT);
85 return 0; // all ok
86 }