Обсуждаем контроллеры компании Atmel.
Ответить

Attiny85 проблема с USI I2C

Ср ноя 29, 2023 19:54:01

Прошу помощи в реализации интерфейса I2C на Attiny85 в режиме ведомого.

Проблема в следующем:
При срабатывании прерывания по переполнению счетчика, в регистре данных USIDR оказывается полученный байт сдвинутый влево.

Код тестировал в Proteus. На скриншотах показана ячейка памяти 2F, которой соответствует регистр USIDR.
На первом скриншоте отправляется 0x00, в USIDR оказывается 0x01; на втором скриншоте отправляется 0x01, в USIDR - 0x03.

Думал проблема в симуляции, но нет. Тестировал в железе - то же самое.

Заранее благодарю!

Код:
Код:
// Инициализация I2C интерфейса
void i2c_init()
{
      
   // Настройка интерфейса USI на режим TWI
   USICR |= (1<<USIWM0);
   USICR |= (1<<USIWM1);
   
   // Настройка интерфейса на источник тактирования
   USICR &= ~(1<<USICLK);
   USICR &= ~(1<<USICS0);
   USICR |= (1<<USICS1);
   
   // Выставление пинов интерфейса на вход
   // SDA
   DDRB &= ~(1<<0);   
   PORTB  &= ~(1<<0);   
   // SCL
   DDRB &= ~(1<<2);   
   PORTB  &= ~(1<<2);   
   
   // Включение прерывания по старту и очистка флага прерывания
   USICR |= (1<<USISIE);
   USISR |= (1<<USISIF);
}

// Прерывание по старту
ISR(USI_START_vect){
   
   while( (PINB & (1 << PIN_SCL)) && (!(PINB & (1 << PIN_SDA))) );
         
   // Очистка регистра статуса
   USISR |= (1<<USISIF);

   // Включение прерывания по переполнению
   USICR |= (1<<USIOIE);
   
}

// Прерывание по переполнению счетчика
ISR(USI_OVF_vect){   
   
   uint8_t i2c_byte = USIDR;
   
   *pwm_0 = 0;
      
   if (i2c_byte>=1){
      *pwm_0 = 250;
   }
      
   if (i2c_byte==1){
      *pwm_0 = 100;
   }
   
   USISR |= (1<<USIOIF);      // Сброс флага прерывания по переполнению
   USISR = 0;            // Сброс счетчика
   
}



Добавлено after 5 hours 27 minutes 30 seconds:
Еще заметил, что после отправки байта, регистр 2E находится в значении 0100 0010, что соответствует значению счетчика 2 и выставленному флагу срабатывания прерывания по переполнению. Такое ощущение, что в регистр USIDR попадает бит NACK, который по сути и не должен генерироваться, т.к. USIWM выставлены в 11, что значит что после срабатывания прерывания по переполнению линия SCL притягивается к нулю и в счетчик и регистр USIDR ничего писаться не должно...
Вложения
3.png
(47.04 KiB) Скачиваний: 17
2.png
Отправляется 0x01, в USIDR - 0x03
(34.35 KiB) Скачиваний: 16
1.png
Отправляется 0x00, в USIDR оказывается 0x01
(35.09 KiB) Скачиваний: 16

Re: Attiny85 проблема с USI I2C

Ср ноя 29, 2023 23:17:49

В Си не разбираюсь, только начал литературу читать по нему.. В прерывании по старту заинтересовала конструкция "while( (PINB & (1 << PIN_SCL)) && (!(PINB & (1 << PIN_SDA))) );" Так понимаю, это ожидание нужных уровней на пинах? Если не ждать, а сразу писать в регистры и на выход?
И еще, вспомнил.. С принудительным удержанием scl у меня какие-то непонятки были, сейчас биты USIWM1 = 1 и USIWM0 = 0, так все работает.

Re: Attiny85 проблема с USI I2C

Сб дек 02, 2023 14:20:12

В Си не разбираюсь, только начал литературу читать по нему.. В прерывании по старту заинтересовала конструкция "while( (PINB & (1 << PIN_SCL)) && (!(PINB & (1 << PIN_SDA))) );" Так понимаю, это ожидание нужных уровней на пинах? Если не ждать, а сразу писать в регистры и на выход?
И еще, вспомнил.. С принудительным удержанием scl у меня какие-то непонятки были, сейчас биты USIWM1 = 1 и USIWM0 = 0, так все работает.


Попробовал, результат тот же

Re: Attiny85 проблема с USI I2C

Вс дек 03, 2023 06:34:55

А в роли мастера что? Можешь хекс слейва кинуть? Прогоню в отладчике с анализатором, гляну что к чему..

Re: Attiny85 проблема с USI I2C

Вс дек 03, 2023 18:45:17

А в роли мастера что? Можешь хекс слейва кинуть? Прогоню в отладчике с анализатором, гляну что к чему..


Прикрепил хекс
Немного изменил код что бы понимать что происходит при выполнении в железе. В зависимости от полученного байта будет изменяться скважность ШИМ на ноге PB1

Код:

// Прерывание по старту
ISR(USI_START_vect){

   i2c_flag = 1;
      
   // Очистка регистра статуса
   USISR |= (1<<USISIF);

   // Включение прерывания по переполнению
   USICR |= (1<<USIOIE);
   
   USISR = 0;
   
}

// Прерывание по переполнению счетчика
ISR(USI_OVF_vect){   
   
   uint8_t i2c_byte = USIDR;
   
   // Сверка адреса устройства с адресом во фрейме
   if (i2c_flag==1) {
      
      if (i2c_byte>1){
         *pwm_0 = 250;
      }
      
      if (i2c_byte==0){
         *pwm_0 = 128;
      }
   
   }
   
   USISR |= (1<<USIOIF);      // Сброс флага прерывания по переполнению
   USISR = 0;            // Сброс счетчика
   
}

Вложения
led_driver_attiny85.hex
(1.42 KiB) Скачиваний: 9

Re: Attiny85 проблема с USI I2C

Сб дек 09, 2023 20:32:28

Только что добрался до отладчика. Пробуй читать USIBR. . Прилагаю два скрина, адрес посылал 0x82. (0х41+W).
ЗЫ: Биты USICS в твоем хексе инициализируются USICS1=1 USICS0=1, надо USICS0=0. Тогда можно читать USIDR первой командой при входе в прерывание и там будет актуальное значение.
Добавил скрин инициализации USICR.. Жесть жестяная ))) Может спецы подскажут ТС, как правильно на С написать?
USICR = 1<<USISE|1<<USIWM1|1<<USIWM0|1<<USICS1 ; так наверное компактнее будет..
Вложения
3.png
(16.47 KiB) Скачиваний: 21
2.png
(98.65 KiB) Скачиваний: 17
1.png
(98.81 KiB) Скачиваний: 17
Ответить