Совместимость с частотой двухпроводного интерфейса (TWI) и SMBus
Правильно ли я понял спецификацию ATmega328P относительно тактовой частоты TWI?
Из §21.5.2 Блока генератора скорости передачи битов тактовая частота TWI рассчитывается следующим образом:
Затем решаем для TWBR
:
Однако в §8.12.2 CLKPR – Регистр предварительной настройки тактовой частоты упоминает, что частота процессора задается CLKPR
. Таким образом, уравнение должно быть:
И решение для TWBR
:
Является ли следующий код правильной реализацией уравнений?
void SetFrequency(uint32_t twi_freq)
{
if (smbus)
{
// SMBus clock frequency is 10 kHz to 100 kHz.
if (twi_freq > 100000u)
{
twi_freq = 100000u;
}
else if twi_freq < 10000u)
{
twi_freq = 10000u;
}
}
else if (twi_freq > 400000u)
{
// Up to 400 kHz data transfer speed.
// §21.1 Features
twi_freq = 400000u;
}
// TWI prescaler of 1.
// Table 21-8. TWI Bit Rate Prescaler
// TWPS1 = 0, TWPS0 = 0
TWSR &= B11111100;
// Achievable maximum TWI frequency with current CPU frequency, CLK prescaler and minimum TWBR with TWI prescaler of 1.
// Rounded down to nearest integer.
const uint32_t TWI_FREQ_MAX = F_CPU / ( ( 1 << CLKPR ) * ( 16 + 2 * 0x00 * 1 ) );
// Achievable minimum TWI frequency with current CPU frequency, CLK prescaler and maximum TWBR with TWI prescaler of 1.
// Rounded up to nearest integer.
const uint32_t DIVISOR = ( ( 1 << CLKPR ) * ( 16 + 2 * 0xFF * 1 ) );
const uint32_t TWI_FREQ_MIN = (F_CPU + (DIVISOR - 1)) / DIVISOR;
if (twi_freq > TWI_FREQ_MAX)
{
twi_freq = TWI_FREQ_MAX;
}
else if (twi_freq < TWI_FREQ_MIN)
{
twi_freq = TWI_FREQ_MIN;
}
// TWI bit rate.
// §21.5.2 Bit Rate Generator Unit
// §8.12.2 CLKPR – Clock Prescale Register
byte bit_rate = (F_CPU / (1 << CLKPR) / twi_freq - 16) / 2
TWBR = bit_rate;
// Check.
const uint32_t twi_freq = F_CPU / ( ( 1 << CLKPR ) * ( 16 + 2 * TWBR * 1 ) );
}
Обратите внимание, что smbus
-это флаг, установленный в другом месте (глобальный или член класса) для указания режима SMBus.
@tim, 👍0
1 ответ
Лучший ответ:
Просто для подтверждения, на случай, если кому-то еще интересно, вторая пара уравнений в моем вопросе является правильной, которая учитывает прескалер тактовой частоты процессора (CLKPR
).
Тактовая частота TWI:
И решение для TWBR
:
- Как обнаружить ошибки I2C с помощью requestFrom()
- Multiple Wire.write() не работает для Arduino Nano I2C
- Проблема с отображением времени Ntp на oled с использованием библиотеки U8G2.
- PCF8583 с задержкой Arduino в одну секунду?
- Хорошие способы подключения нескольких шин I2C?
- Можно ли запрограммировать чип AVR (atmega328p) через i2c?
- Попытка понять узкое место частоты дискретизации датчика
- DS1337 с общим подтягиванием I2C