Softi2c with pull up enabled
Embed:
(wiki syntax)
Show/hide line numbers
SoftI2C.cpp
00001 #include "SoftI2C.h" 00002 00003 SoftI2C::SoftI2C(PinName sda, PinName scl) : _sda(sda), _scl(scl) { 00004 // Set defaults 00005 _sda.input(); 00006 _scl.input(); 00007 _sda.mode(PullUp); 00008 _scl.mode(PullUp); 00009 00010 frequency(100000); 00011 00012 active = false; 00013 00014 } 00015 00016 void SoftI2C::frequency(int hz) { 00017 delay_us = 1000000 / hz / 4; //delay is a quarter of the total period 00018 } 00019 00020 int SoftI2C::read(int address, char *data, int length, bool repeated) { 00021 start(); 00022 00023 // Write address with LSB to one 00024 if (write(address | 0x01) == 0) { 00025 return 1; 00026 } 00027 00028 // Read the data 00029 for(int i = 0; i<length - 1; i++) { 00030 data[i] = read(1); 00031 } 00032 data[length-1] = read(0); 00033 00034 if (repeated == false) { 00035 stop(); 00036 } 00037 return 0; 00038 } 00039 00040 int SoftI2C::write(int address, const char *data, int length, bool repeated) { 00041 start(); 00042 00043 // Write address with LSB to zero 00044 if (write(address & 0xFE) == 0) { 00045 return 1; 00046 } 00047 00048 // Write the data 00049 for(int i = 0; i<length; i++) { 00050 if(write(data[i]) == 0) { 00051 return 1; 00052 } 00053 } 00054 00055 if (repeated == false) { 00056 stop(); 00057 } 00058 return 0; 00059 } 00060 00061 int SoftI2C::read(int ack) { 00062 int retval = 0; 00063 _scl.output(); 00064 00065 // Shift the bits out, msb first 00066 for (int i = 7; i>=0; i--) { 00067 //SCL low 00068 _scl.write(0); 00069 _sda.input(); 00070 wait_us(delay_us); 00071 00072 //read SDA 00073 retval |= _sda.read() << i; 00074 wait_us(delay_us); 00075 00076 //SCL high again 00077 _scl.write(1); 00078 wait_us(delay_us << 1); //wait two delays 00079 } 00080 00081 // Last cycle to set the ACK 00082 _scl.write(0); 00083 if ( ack ) { 00084 _sda.output(); 00085 _sda.write(0); 00086 } else { 00087 _sda.input(); 00088 } 00089 wait_us(delay_us << 1); 00090 00091 _scl.write(1); 00092 wait_us(delay_us << 1); 00093 00094 00095 return retval; 00096 } 00097 00098 int SoftI2C::write(int data) { 00099 _scl.output(); 00100 00101 // Shift the bits out, msb first 00102 for (int i = 7; i>=0; i--) { 00103 //SCL low 00104 _scl.write(0); 00105 wait_us(delay_us); 00106 00107 //Change SDA depending on the bit 00108 if ( (data >> i) & 0x01 ) { 00109 _sda.input(); 00110 _sda.mode(PullUp); 00111 } else { 00112 _sda.output(); 00113 _sda.write(0); 00114 } 00115 wait_us(delay_us); 00116 00117 //SCL high again 00118 _scl.write(1); 00119 wait_us(delay_us << 1); //wait two delays 00120 } 00121 00122 // Last cycle to get the ACK 00123 _scl.write(0); 00124 wait_us(delay_us); 00125 00126 _sda.input(); 00127 _sda.mode(PullUp); 00128 wait_us(delay_us); 00129 00130 _scl.write(1); 00131 wait_us(delay_us); 00132 int retval = ~_sda.read(); //Read the ack 00133 wait_us(delay_us); 00134 00135 return retval; 00136 } 00137 00138 void SoftI2C::start(void) { 00139 if (active) { //if repeated start 00140 //Set SDA high, toggle scl 00141 _sda.input(); 00142 _sda.mode(PullUp); 00143 _scl.output(); 00144 _scl.write(0); 00145 wait_us(delay_us << 1); 00146 _scl.write(1); 00147 wait_us(delay_us << 1); 00148 } 00149 // Pull SDA low 00150 _sda.output(); 00151 _sda.write(0); 00152 wait_us(delay_us); 00153 active = true; 00154 } 00155 00156 void SoftI2C::stop(void) { 00157 // Float SDA high 00158 _scl.output(); 00159 _scl.write(0); 00160 _sda.output(); 00161 _sda.write(0); 00162 wait_us(delay_us); 00163 _scl.input(); 00164 _scl.mode(PullUp); 00165 wait_us(delay_us); 00166 _sda.input(); 00167 _sda.mode(PullUp); 00168 wait_us(delay_us); 00169 00170 active = false; 00171 }
Generated on Wed Jul 13 2022 04:39:11 by 1.7.2