Merge pull request #106 from RobTillaart/master

Fix #105 - make I2C setspeed more robust
This commit is contained in:
Limor "Ladyada" Fried 2022-08-12 15:06:06 -04:00 committed by GitHub
commit 4b8f6e312c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
1 changed files with 19 additions and 9 deletions

View File

@ -264,33 +264,43 @@ bool Adafruit_I2CDevice::setSpeed(uint32_t desiredclk) {
#if defined(__AVR_ATmega328__) || \ #if defined(__AVR_ATmega328__) || \
defined(__AVR_ATmega328P__) // fix arduino core set clock defined(__AVR_ATmega328P__) // fix arduino core set clock
// calculate TWBR correctly // calculate TWBR correctly
uint8_t prescaler = 1;
if ((F_CPU / 18) < desiredclk) {
#ifdef DEBUG_SERIAL
Serial.println(F("I2C.setSpeed too high."));
#endif
return false;
}
uint32_t atwbr = ((F_CPU / desiredclk) - 16) / 2; uint32_t atwbr = ((F_CPU / desiredclk) - 16) / 2;
if (atwbr > 16320) {
#ifdef DEBUG_SERIAL
Serial.println(F("I2C.setSpeed too low."));
#endif
return false;
}
if (atwbr <= 255) { if (atwbr <= 255) {
prescaler = 1; atwbr /= 1;
TWSR = 0x0; TWSR = 0x0;
} else if (atwbr <= 1020) { } else if (atwbr <= 1020) {
atwbr /= 4; atwbr /= 4;
prescaler = 4;
TWSR = 0x1; TWSR = 0x1;
} else if (atwbr <= 4080) { } else if (atwbr <= 4080) {
atwbr /= 16; atwbr /= 16;
prescaler = 16;
TWSR = 0x2; TWSR = 0x2;
} else if (atwbr <= 16320) { } else { // if (atwbr <= 16320)
atwbr /= 64; atwbr /= 64;
prescaler = 64;
TWSR = 0x3; TWSR = 0x3;
} }
TWBR = atwbr;
#ifdef DEBUG_SERIAL #ifdef DEBUG_SERIAL
Serial.print(F("TWSR prescaler = ")); Serial.print(F("TWSR prescaler = "));
Serial.println(prescaler); Serial.println(pow(4, TWSR));
Serial.print(F("TWBR = ")); Serial.print(F("TWBR = "));
Serial.println(atwbr); Serial.println(atwbr);
#endif #endif
TWBR = atwbr;
return true; return true;
#elif (ARDUINO >= 157) && !defined(ARDUINO_STM32_FEATHER) && \ #elif (ARDUINO >= 157) && !defined(ARDUINO_STM32_FEATHER) && \
!defined(TinyWireM_h) !defined(TinyWireM_h)
_wire->setClock(desiredclk); _wire->setClock(desiredclk);