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

i2c на прерываниях не отправляется адрес.

Ср авг 17, 2022 11:05:16

Здравствуйте, хочу написать функцию на прерываниях для i2c. Формирую условие старта . в прерываниях ловлю код 0х08 ,далее в регистр данных посылаю адрес , но в этом месте все зависает в прерывании ... что не так? Контроллер ATMEGA 328 AVRStudio 7. все по даташиту дела.


void i2c_transmit(void) // функция передачи инициирует условие старта далее все должно происходить в прерывани.
{
TWCR= (1<<TWINT)|(1<<TWEN)|(1<<TWSTA)|(1<<TWIE);

}


вектор прерывания

ISR (TWI_vect) // прерывание по i2c
{
switch((TWSR & 0xF8))
{
case 8: // если старт прошел зависает на этом кейсе
{
TWDR = i2c_SlaveAddress; // в дата регистр пишем адрес подчиненного (он уже сдвинут на 1 в лево!)
TWCR = 1<<TWINT|0<<TWSTA|0<<TWSTO|1<<TWEN|1<<TWIE; // команда напередачу
break;
}

case 0x18: // если аск от ведомого получен
{
TWDR=200; // передаем например 200
TWCR = (1<<TWINT)|(1<<TWEN);
}
}

}

Re: i2c на прерываниях не отправляется адрес.

Ср авг 17, 2022 11:16:47

vdv22 писал(а):TWCR= (1<<TWINT)|(1<<TWEN)|(1<<TWSTA)|(1<<TWIE);


vdv22 писал(а):TWCR = 1<<TWINT|0<<TWSTA|0<<TWSTO|1<<TWEN|1<<TWIE; // команда напередачу


какой разный стиль... а вот я бы везде ставил скобки, потому что, к стыду своему, приоритетность плохо помню.
а зачем при команде на передачу ещё раз включать и интерфейс, и прерывание, это действительно по даташиту так у атмелов?

Добавлено after 4 minutes 49 seconds:
а, TWCR-у всё заново присваивается... ну. так некрасиво. Это портит логику работы.

Re: i2c на прерываниях не отправляется адрес.

Ср авг 17, 2022 11:19:57

по даташиту TWCR = (1<<TWINT) | (1<<TWEN); так тоже не работает

А разность написания это все результат экспериментов- целый день убил на это . Без прерываний все отлично работает.

Re: i2c на прерываниях не отправляется адрес.

Ср авг 17, 2022 11:26:01

В AVR-ах ни бум-бум, но так делать, пожалуй, не стоит:
Код:
switch((TWSR & 0xF8))
Вы уверены, что в регистре будет стоять только один этот бит
Код:
case 8:
А то что не выходите из прерывания - какой-то флаг обработки его не сбрасываете.

Re: i2c на прерываниях не отправляется адрес.

Ср авг 17, 2022 11:44:06

Здравствуйте, хочу написать функцию на прерываниях для i2c. Формирую условие старта . в прерываниях ловлю код 0х08

Я в Си не понимаю, но вот что бросилось в глаза... пишете что ловите 0х08 а в коде пишете 0хF8... :dont_know:
switch((TWSR & 0xF8))

а ведь нужно проверять после команды старт именно 0x08 а не 0хF8 :)
Последний раз редактировалось VNS Ср авг 17, 2022 11:46:29, всего редактировалось 1 раз.

Re: i2c на прерываниях не отправляется адрес.

Ср авг 17, 2022 11:47:13

если перед выходом из прерывания добавить TWCR = (1<<TWINT); то зависания нет ,но адрес упороно не передается (по осциллнографу и лог анализатору.

SR (TWI_vect) // прерывание по i2c
{

switch((TWSR & 0xF8))
{
case 8: // если старт прошел
{ out=(TWSR & 0xF8);
TWDR = i2c_SlaveAddress; // в дата регистр пишем адрес подчиненного (он уже сдвинут на 1 в лево!)
TWCR = (1<<TWINT)|(0<<TWSTA)|(0<<TWSTO)|(1<<TWEN); // команда напередачу
break;
}

case 0x18: // если аск от ведомого получен
{
TWDR=200; // передаем например 200
TWCR = (1<<TWINT)|(1<<TWEN);
}
}

TWCR = (1<<TWINT); // если добавить сброс флага ,то зависания нет ,но адрес упороно не передается (по осциллнографу и лог анализатору.)
}

Добавлено after 1 minute 6 seconds:
Здравствуйте, хочу написать функцию на прерываниях для i2c. Формирую условие старта . в прерываниях ловлю код 0х08

Я в Си не понимаю, но вот что бросилось в глаза... пишете что ловите 0х08 а в коде пишете 0хF8... :dont_know:
switch((TWSR & 0xF8))


F8 это маска . она накладывается на регистр и смотрим какое число получилось

Re: i2c на прерываниях не отправляется адрес.

Ср авг 17, 2022 11:53:24

F8 это маска

Теперь понял... извиняюсь что отвлёк... :)

Re: i2c на прерываниях не отправляется адрес.

Ср авг 17, 2022 11:56:40

Ну если вы так упорствуете:
vdv22 писал(а):case 8: // если старт прошел
case 0x18: // если аск от ведомого получен
То где кейсы для 0x38, 0x48, 0x58 ... 0xF8? Каждый флаг должен обрабатываться.

В моём драйвере для силикон-лабовского кристалла обработчик выглядит так:

Re: i2c на прерываниях не отправляется адрес.

Ср авг 17, 2022 12:06:38

Ждете, пока шина будет готова, проверьте код состояния для отправленного условия запуска:
Код:
while(!(TWCR & (1<<TWINT)));

Было бы хорошо обработать все возможные состояния.

Re: i2c на прерываниях не отправляется адрес.

Ср авг 17, 2022 12:11:06

Обработчик всех флагов будет, но мне сейчас дадо чтоб он хоть адрес отправит - я в свиче обычно делаю default чтоб другое не нужное отсечь. Сейчас в прерывание он заходит только один раз (отслеживаю через uart ) то есть после получения 0x08.

Добавлено after 1 minute 45 seconds:
Ждете, пока шина будет готова, проверьте код состояния для отправленного условия запуска:
Код:
while(!(TWCR & (1<<TWINT)));

Было бы хорошо обработать все возможные состояния.

то что вы предлогаете это блокирующий режим -он у меня прекрасно работает . Но я не хочу в цикле жать -мне нужен режим с прерываниями.

Re: i2c на прерываниях не отправляется адрес.

Ср авг 17, 2022 12:30:23

Отключите возможности для прерывание в прерывании.
Обработайте все возможные команды/состояния.
Поставьте break; след второй выбор.
Ответить