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