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

Обсуждаем контроллеры компании Atmel.
Ответить
bepis666
Родился
Сообщения: 3
Зарегистрирован: Ср ноя 29, 2023 13:56:55

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

Сообщение bepis666 »

Прошу помощи в реализации интерфейса 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 КБ) 39 скачиваний
2.png
Отправляется 0x01, в USIDR - 0x03
(34.35 КБ) 37 скачиваний
1.png
Отправляется 0x00, в USIDR оказывается 0x01
(35.09 КБ) 38 скачиваний
Реклама
Игорь_396
Встал на лапы
Сообщения: 102
Зарегистрирован: Ср дек 25, 2019 21:17:31
Откуда: Саратов

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

Сообщение Игорь_396 »

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

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

Сообщение bepis666 »

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

Попробовал, результат тот же
Игорь_396
Встал на лапы
Сообщения: 102
Зарегистрирован: Ср дек 25, 2019 21:17:31
Откуда: Саратов

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

Сообщение Игорь_396 »

А в роли мастера что? Можешь хекс слейва кинуть? Прогоню в отладчике с анализатором, гляну что к чему..
Реклама
Эиком - электронные компоненты и радиодетали
bepis666
Родился
Сообщения: 3
Зарегистрирован: Ср ноя 29, 2023 13:56:55

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

Сообщение bepis666 »

[uquote="Игорь_396",url="/forum/viewtopic.php?p=4511809#p4511809"]А в роли мастера что? Можешь хекс слейва кинуть? Прогоню в отладчике с анализатором, гляну что к чему..[/uquote]

Прикрепил хекс
Немного изменил код что бы понимать что происходит при выполнении в железе. В зависимости от полученного байта будет изменяться скважность ШИМ на ноге 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 КБ) 40 скачиваний
Реклама
Игорь_396
Встал на лапы
Сообщения: 102
Зарегистрирован: Ср дек 25, 2019 21:17:31
Откуда: Саратов

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

Сообщение Игорь_396 »

Только что добрался до отладчика. Пробуй читать 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 КБ) 50 скачиваний
2.png
(98.65 КБ) 41 скачивание
1.png
(98.81 КБ) 49 скачиваний
Реклама
Ответить

Вернуться в «AVR»