Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
i2c.c
00001 // =============================================================================================== 00002 // = UAVXArm Quadrocopter Controller = 00003 // = Copyright (c) 2008 by Prof. Greg Egan = 00004 // = Original V3.15 Copyright (c) 2007 Ing. Wolfgang Mahringer = 00005 // = http://code.google.com/p/uavp-mods/ = 00006 // =============================================================================================== 00007 00008 // This is part of UAVXArm. 00009 00010 // UAVXArm is free software: you can redistribute it and/or modify it under the terms of the GNU 00011 // General Public License as published by the Free Software Foundation, either version 3 of the 00012 // License, or (at your option) any later version. 00013 00014 // UAVXArm is distributed in the hope that it will be useful,but WITHOUT ANY WARRANTY; without 00015 // even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 00016 // See the GNU General Public License for more details. 00017 00018 // You should have received a copy of the GNU General Public License along with this program. 00019 // If not, see http://www.gnu.org/licenses/ 00020 00021 #include "UAVXArm.h" 00022 00023 boolean I2C0AddressResponds(uint8); 00024 #ifdef HAVE_I2C1 00025 boolean I2C1AddressResponds(uint8); 00026 #endif // HAVE_I2C1 00027 void TrackMinI2CRate(uint32); 00028 void ShowI2CDeviceName(uint8); 00029 uint8 ScanI2CBus(void); 00030 boolean ESCWaitClkHi(void); 00031 void ProgramSlaveAddress(uint8); 00032 void ConfigureESCs(void); 00033 00034 uint16 I2CError[256]; 00035 uint8 I2CSpeed = 10; // 100KHz 00036 uint32 MinI2CRate = I2C_MAX_RATE_HZ; 00037 00038 //______________________________________________________________________________________________ 00039 00040 // Software I2C 00041 00042 #ifdef SW_I2C 00043 00044 void SDelay(uint16 d) { // 1.25 + 0.0475 * n uS ~0.05uS per click 00045 00046 volatile int16 v; 00047 00048 for (v = 0; v < d ; v++ ) {}; 00049 00050 } // SDelay 00051 00052 /* 00053 #define SCLLowStartT SDelay(I2CSpeed) 00054 #define DataLowPadT SDelay(I2CSpeed) 00055 #define SCLLowPadT SDelay(I2CSpeed) 00056 #define SCLHighT SDelay(I2CSpeed) 00057 */ 00058 00059 #if ( I2C_MAX_RATE_HZ == 400000 ) 00060 00061 #define SCLLowStartT SDelay(10) 00062 #define DataLowPadT SDelay(16) // 10 00063 #define SCLLowPadT SDelay(6) 00064 #define SCLHighT SDelay(10) 00065 00066 #else 00067 00068 #define SCLLowStartT SDelay(82) 00069 #define DataLowPadT SDelay(82) 00070 #define SCLLowPadT SDelay(82) 00071 #define SCLHighT SDelay(85) 00072 00073 #endif //I2C400KHZ 00074 00075 00076 #define I2CSDALow {I2C0SDA.write(0);I2C0SDA.output();SCLLowPadT;} 00077 #define I2CSDAFloat {I2C0SDA.input();SCLLowPadT;} 00078 #define I2CSCLLow {I2C0SCL.write(0);I2C0SCL.output();} 00079 #define I2CSCLFloat {I2C0SCL.input();SCLHighT;} 00080 00081 void MyI2C::frequency(uint32 f) { 00082 // delay depending on rate 00083 00084 if ( f == 400000 ) 00085 I2CSpeed = 10; 00086 else 00087 I2CSpeed = 80; 00088 } // frequency 00089 00090 void MyI2C::start(void) { 00091 00092 I2CSDAFloat; 00093 r = waitclock(); 00094 I2CSDALow; 00095 SCLLowStartT; 00096 I2CSCLLow; 00097 } // start 00098 00099 void MyI2C::stop(void) { 00100 00101 I2CSDALow; 00102 r = waitclock(); 00103 I2CSDAFloat; 00104 SCLLowStartT; 00105 00106 } // stop 00107 00108 boolean MyI2C::waitclock(void) { 00109 static uint32 s; 00110 00111 I2CSCLFloat; // set SCL to input, output a high 00112 s = 0; 00113 while ( I2C0SCL.read() == 0 ) 00114 if ( ++s > 16000 ) { // ~1mS 00115 I2CError[0]++; 00116 // possible add SCL cycles here to attempt to force device reset 00117 Stats[I2CFailS]++; 00118 return (false); 00119 } 00120 return( true ); 00121 } // waitclock 00122 00123 uint8 MyI2C::read(uint8 ack) { 00124 static uint8 s, d; 00125 00126 I2CSDAFloat; 00127 d = 0; 00128 s = 8; 00129 do { 00130 if ( waitclock() ) { 00131 d <<= 1; 00132 if ( I2C0SDA.read() ) { 00133 d |= 1; 00134 I2CSCLLow; 00135 DataLowPadT; 00136 } else { 00137 I2CSCLLow; 00138 SDelay(10);//DataLowPadT; 00139 } 00140 } else 00141 return( 0 ); 00142 } while ( --s ); 00143 00144 if ( ack == I2C_NACK ) 00145 I2C0SDA.write(0xffff); // Port write with mask selecting SDA - messy 00146 else 00147 I2C0SDA.write(0); 00148 I2C0SDA.output(); 00149 00150 SCLLowPadT; 00151 00152 if ( waitclock() ) { 00153 I2CSCLLow; 00154 return( d ); 00155 } else 00156 return( 0 ); 00157 00158 } // read 00159 00160 uint8 MyI2C::write(uint8 d) { 00161 static uint8 s, r; 00162 00163 for ( s = 0; s < 8; s++) { 00164 if ( d & 0x80 ) { 00165 I2CSDAFloat; 00166 } else { 00167 I2CSDALow; 00168 } 00169 00170 if ( waitclock() ) { 00171 I2CSCLLow; 00172 d <<= 1; 00173 } else 00174 return(I2C_NACK); 00175 } 00176 00177 I2CSDAFloat; 00178 if ( waitclock() ) { 00179 if ( I2C0SDA.read() ) 00180 r = I2C_NACK; 00181 else 00182 r = I2C_ACK; 00183 I2CSDALow;// kill runt pulses 00184 I2CSCLLow; 00185 return ( r ); 00186 } else { 00187 // I2CSCLLow; 00188 return(I2C_NACK); 00189 } 00190 00191 } // write 00192 00193 uint8 MyI2C::blockread(uint8 a, char* S, uint8 l) { 00194 static uint8 b; 00195 static boolean err; 00196 00197 I2C0.start(); 00198 err = I2C0.write(a|1) != I2C_ACK; 00199 for (b = 0; b < (l - 1); b++) 00200 S[b] = I2C0.read(I2C_ACK); 00201 S[l-1] = I2C0.read(I2C_NACK); 00202 I2C0.stop(); 00203 00204 return( err ); 00205 } // blockread 00206 00207 boolean MyI2C::blockwrite(uint8 a, const char* S, uint8 l) { 00208 static uint8 b; 00209 00210 I2C0.start(); 00211 if ( I2C0.write(a) != I2C_ACK ) goto BlockWriteError; // use this? 00212 for ( b = 0; b < l; b++ ) 00213 if ( I2C0.write(S[b]) != I2C_ACK ) goto BlockWriteError; 00214 I2C0.stop(); 00215 00216 return(false); 00217 00218 BlockWriteError: 00219 I2C0.stop(); 00220 00221 return(true); 00222 00223 } // blockwrite 00224 00225 #endif // SW_I2C 00226 00227 //______________________________________________________________________________________________ 00228 00229 void TrackMinI2CRate(uint32 r) { 00230 00231 // CURRENTLY USING DEFINE TO SPECIFY RATE - UAVXArm.h 00232 if ( r < MinI2CRate ) 00233 MinI2CRate = r; 00234 } // TrackMinI2CRate 00235 00236 void ShowI2CDeviceName(uint8 d) { 00237 TxChar(' '); 00238 switch ( d ) { 00239 case ADXL345_ID: 00240 TxString("ADXL345 Acc"); 00241 break; 00242 case ITG3200_ID: 00243 TxString("ITG3200 Gyro"); 00244 break; 00245 case HMC5843_ID: 00246 TxString("HMC5843 Magnetometer"); 00247 break; 00248 case HMC6352_ID: 00249 TxString("HMC6352 Compass"); 00250 break; 00251 case ADS7823_ID: 00252 TxString("ADS7823 ADC"); 00253 break; 00254 case MCP4725_ID_0xCC: 00255 TxString("MCP4725 DAC"); 00256 break; 00257 case MCP4725_ID_0xC8: 00258 TxString("MCP4725 DAC"); 00259 break; 00260 case BOSCH_ID: 00261 TxString("Bosch Baro"); 00262 break; 00263 case TMP100_ID: 00264 TxString("TMP100 Temp"); 00265 break; 00266 case PCA9551_ID: 00267 TxString("PCA9551 LED"); 00268 break; 00269 case LISL_ID: 00270 TxString("LIS3L Acc"); 00271 break; 00272 default: 00273 break; 00274 } // switch 00275 TxChar(' '); 00276 00277 } // ShowI2CDeviceName 00278 00279 boolean I2C0AddressResponds(uint8 s) { 00280 static boolean r; 00281 I2C0.start(); 00282 r = I2C0.write(s) == I2C_ACK; 00283 I2C0.stop(); 00284 return (r); 00285 } // I2C0AddressResponds 00286 00287 #ifdef HAVE_IC1 00288 boolean I2C1AddressResponds(uint8 s) { 00289 static boolean r; 00290 I2C1.start(); 00291 r = I2C1.write(s) == I2C_ACK; 00292 I2C1.stop(); 00293 return (r); 00294 } // I2C1AddressResponds 00295 #endif // HAVE_IC1 00296 00297 uint8 ScanI2CBus(void) { 00298 uint8 s; 00299 uint8 d; 00300 00301 d = 0; 00302 TxString("Buss 0\r\n"); 00303 00304 #ifdef SW_I2C 00305 TxString("I2C Ver.:\tSoftware\r\n"); 00306 #else 00307 TxString("I2C Ver.:\tHardware (CAUTION)\r\n"); 00308 #endif // SW_I2C 00309 00310 #if ( I2C_MAX_RATE_HZ == 400000 ) 00311 TxString("Rate:\t400KHz\r\n"); 00312 #else 00313 TxString("Rate:\t100KHz\r\n"); 00314 #endif 00315 TxString("SCL Hangs:\t"); 00316 TxVal32(I2CError[0], 0, 0); 00317 TxNextLine(); 00318 for ( s = 0x10 ; s <= 0xf6 ; s += 2 ) { 00319 if ( I2C0AddressResponds(s) ) { 00320 d++; 00321 TxString("\t0x"); 00322 TxValH(s); 00323 TxChar(HT); 00324 TxVal32(I2CError[s], 0, HT); 00325 ShowI2CDeviceName( s ); 00326 TxNextLine(); 00327 } 00328 Delay1mS(2); 00329 } 00330 00331 #ifdef HAVE_I2C1 00332 TxString("Buss 1\r\n"); 00333 00334 #ifdef SW_I2C 00335 TxString("I2C Ver.:\tSoftware\r\n"); 00336 #else 00337 TxString("I2C Ver.:\tHardware (CAUTION)\r\n"); 00338 #endif // SW_I2C 00339 00340 #if ( I2C_MAX_RATE_HZ == 400000 ) 00341 TxString("Rate:\t400KHz\r\n"); 00342 #else 00343 TxString("Rate:\t100KHz\r\n"); 00344 #endif 00345 TxString("SCL Hangs:\t"); 00346 TxNextLine(); 00347 for ( s = 0x10 ; s <= 0xf6 ; s += 2 ) { 00348 if ( I2C0AddressResponds(s) ) { 00349 d++; 00350 TxString("\t0x"); 00351 TxValH(s); 00352 TxChar(HT); 00353 TxVal32(I2CError[s], 0, HT); 00354 ShowI2CDeviceName( s ); 00355 TxNextLine(); 00356 } 00357 Delay1mS(2); 00358 } 00359 #endif // HAVE_I2C1 00360 00361 PCA9551Test(); 00362 00363 return(d); 00364 } // ScanI2CBus 00365 00366 void ProgramSlaveAddress(uint8 a) { 00367 static uint8 s; 00368 00369 for (s = 0x10 ; s < 0xf0 ; s += 2 ) { 00370 I2CESC.start(); 00371 if ( I2CESC.read(s) == I2C_ACK ) 00372 if ( s == a ) { // ESC is already programmed OK 00373 I2CESC.stop(); 00374 TxString("\tESC at SLA 0x"); 00375 TxValH(a); 00376 TxString(" is already programmed OK\r\n"); 00377 return; 00378 } else { 00379 if ( I2CESC.read(0x87) == I2C_ACK ) // select register 0x07 00380 if ( I2CESC.write( a ) == I2C_ACK ) { // new slave address 00381 I2CESC.stop(); 00382 TxString("\tESC at SLA 0x"); 00383 TxValH(s); 00384 TxString(" reprogrammed to SLA 0x"); 00385 TxValH(a); 00386 TxNextLine(); 00387 return; 00388 } 00389 } 00390 I2CESC.stop(); 00391 } 00392 TxString("\tESC at SLA 0x"); 00393 TxValH(a); 00394 TxString(" no response - check cabling and pullup resistors!\r\n"); 00395 } // ProgramSlaveAddress 00396 00397 boolean CheckESCBus(void) { 00398 return ( true ); 00399 } // CheckESCBus 00400 00401 void ConfigureESCs(void) { 00402 int8 m; 00403 00404 if ( (int8)P[ESCType] == ESCYGEI2C ) { 00405 TxString("\r\nProgram YGE ESCs\r\n"); 00406 for ( m = 0 ; m < NoOfI2CESCOutputs ; m++ ) { 00407 TxString("Connect ONLY M"); 00408 TxChar('1' + m); 00409 TxString(" ESC, then press any key \r\n"); 00410 while ( PollRxChar() != 'x' ); // UAVPSet uses 'x' for any key button 00411 // TxString("\r\n"); 00412 ProgramSlaveAddress( 0x62 + ( m*2 )); 00413 } 00414 TxString("\r\nConnect ALL ESCs and power-cycle the Quadrocopter\r\n"); 00415 } else 00416 TxString("\r\nYGEI2C not selected as ESC?\r\n"); 00417 } // ConfigureESCs 00418 00419 void InitI2C(void) { 00420 00421 uint8 i; 00422 00423 for ( i = 0; i < 255; i++ ) 00424 I2CError[i] = 0; 00425 00426 } // InitI2C 00427 00428 00429
Generated on Wed Jul 13 2022 01:50:20 by
