IgorKossak 0 21 декабря, 2005 Опубликовано 21 декабря, 2005 · Жалоба а чем ,простите, шит не устраивает . имхо все доходчиво Ну, например, на русский его перевести. B) Хотя, ести перечитать всю эту тему, то это уже сделано. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Petka 0 21 декабря, 2005 Опубликовано 21 декабря, 2005 · Жалоба а чем ,простите, шит не устраивает . имхо все доходчиво Ну, например, на русский его перевести. B) Хотя, ести перечитать всю эту тему, то это уже сделано. Уважаемый Games D.! Вы задаёте вопросы на которые ЕСТЬ однозначные ответы в datahsheet на AVR (если быть точнее в разделе "Two-wire Serial Interface"), поэтому у меня есть конструктивное предложение: задавайте вопросы в таком виде "в пункте таком-то даташита написано что надо делать так-то, что бы получить то-то а у меня выходит сяк-то.". просто практика показывает что если делать, как рекомендуется в datasheet, то всё работает с первого раза и с минимальными временами на отладку. для общего ознакомления с I2C можно прочитать это (на русском). i2c.pdf Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
James D. 0 21 декабря, 2005 Опубликовано 21 декабря, 2005 · Жалоба Я делаю так - передача одного байта (без обработки ошибок), пусть меня поправят, если я не прав: 1. Мастер производит установку скорости передачи (TWSR, TWBR); 2. Посылает сигнал START: (1<<TWINT)|(1<<TWSTA)|(1<<TWEN); 3. Ожидает, когда бит TWINT в TWCR установится в "1"; Слэйв работает по прерываниям TWI; как только происходит перепад из "1" в "0" на шине SDA (при "1" на шине SCL) - значит мастер послал сигнал START, при этом бит TWINT в слэйве уст. в "1"; происходит прерывание и переход на обработчик, в котором слэйв проверяет значение в регистре TWSR (только непонятно, выдает ли при этом слэйв аппаратно ACK?). 4. Мастер, дождавшись установки бита TWINT в "1", проверяет значение в TWSR - оно должно соответствовать $08; 5. Мастер загружает адрес слэйва, допустим $20 в TWDR, обновляет регистр TWCR: (1<<TWINT)|(1<<TWEN); 6. Ожидает, когда бит TWINT в TWCR установится в "1"; Если слэйв определил, что значение TWSR не соответствует $60, значит мастер обращается не к этому слэйву. Слэйв аппаратно выдает NACK и выходит из прерывания - выполняется далее основная программа. Если значение соответствует $60 - слэйв аппаратно выдает ACK, записывает новое значение в TWCR: (1<<TWINT)|(1<<TWEA)|(1<<TWEN), и ждет, когда бит TWINT в TWCR установится в "1". 7. Мастер, дождавшись установки бита TWINT в "1", проверяет значение в TWSR - оно должно соответствовать $18 - адрес слэйвом принят, мастером получен ACK; 8. Заносит в TWDR передаваемый байт; 9. Обновляет TWCR: (1<<TWINT)|(1<<TWEN); 10. Ожидает, когда бит TWINT в TWCR установится в "1"; Слэйв, дождавшись, когда бит TWINT уст. в "1", проверяет рег. TWSR - должен быть код $80; выдает на шину ACK, и сохраняет принятый байт из TWDR в свою память. Далее готовится к приему команды STOP: обновляет TWCR: (1<<TWINT)|(1<<TWEA)|(1<<TWEN), и ждет, когда бит TWINT в TWCR установится в "1". 11. Мастер, дождавшись установки бита TWINT в "1", проверяет значение в TWSR - оно должно соответствовать $28 - данные слэйвом приняты, мастером получен ACK; 12. Мастер, обновляет TWCR: (1<<TWINT)|(1<<TWSTO)|(1<<TWEN), и выходит из программы передачи данных - продолжает выполняться основная программа. Слэйв, дождавшись, когда бит TWINT уст. в "1", проверяет рег. TWSR - должен быть код $A0. После этого слэйв выходит из программы приема данных - продолжает выполняться основная программа. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Petka 0 21 декабря, 2005 Опубликовано 21 декабря, 2005 · Жалоба Я делаю так - передача одного байта (без обработки ошибок), пусть меня поправят, если я не прав: 1. Мастер производит установку скорости передачи (TWSR, TWBR); 2. Посылает сигнал START: (1<<TWINT)|(1<<TWSTA)|(1<<TWEN); 3. Ожидает, когда бит TWINT в TWCR установится в "1"; ВОТ ГДЕ ОШИБКА!!! надо ждать не "1" а "0". ибо: "The TWINT flag must be cleared by software by writing a logic one to it" если флаг "cleared" - "by writing logic ONE" значит флаг имеет ИНВЕРСНУЮ логику! исправляйте ошибку, будем дальше дебажить =) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
James D. 0 21 декабря, 2005 Опубликовано 21 декабря, 2005 · Жалоба Так, заменил на ожидание "0" (в цикле ожидания сразу после посылки START) - теперь мастер зависает здесь: 7. Мастер, дождавшись установки бита TWINT в "1", проверяет значение в TWSR - оно должно соответствовать $18 - адрес слэйвом принят, мастером получен ACK; то есть код в TWSR не равен $18. SLA_Wn: ldi temp,$20 ;Загрузка адреса слэйв + "WRITE" out TWDR,temp ldi temp,(1<<TWINT)|(1<<TWEN) out TWCR,temp wait2n: in temp,TWCR ;Ожидаем ответа от слэйв sbrs temp,TWINT rjmp wait2n in temp,TWSR andi temp,$F8 cpi temp,$18 brne SLA_Wn ;Переход, если ответ от слэйв неверный А раньше зависал в цикле wait2n. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
James D. 0 21 декабря, 2005 Опубликовано 21 декабря, 2005 (изменено) · Жалоба Кстати, в даташите (в приведенном там примере) стоит ожидание "1" - после посылки START. P.S. Прочитал PDF'ку, и сразу возник вопрос: надо ли в процессе работы TWI как-то коммутировать порты (PC0, PC1). У меня они настроены на ввод с вкл. подтягивающими резисторами. Изменено 21 декабря, 2005 пользователем James D. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Petka 0 21 декабря, 2005 Опубликовано 21 декабря, 2005 (изменено) · Жалоба Кстати, в даташите (в приведенном там примере) стоит ожидание "1" - после посылки START. Какой вы упёртый =) цитата из даташита: "while (!(TWCR & (1<<TWINT))); // Wait for TWINT flag set. This indicates that the START condition has been transmitted" Изменено 21 декабря, 2005 пользователем Petka Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
IgorKossak 0 21 декабря, 2005 Опубликовано 21 декабря, 2005 · Жалоба Я делаю так - передача одного байта (без обработки ошибок), пусть меня поправят, если я не прав: 1. Мастер производит установку скорости передачи (TWSR, TWBR); 2. Посылает сигнал START: (1<<TWINT)|(1<<TWSTA)|(1<<TWEN); 3. Ожидает, когда бит TWINT в TWCR установится в "1"; Слэйв работает по прерываниям TWI; как только происходит перепад из "1" в "0" на шине SDA (при "1" на шине SCL) - значит мастер послал сигнал START, при этом бит TWINT в слэйве уст. в "1"; происходит прерывание и переход на обработчик, в котором слэйв проверяет значение в регистре TWSR (только непонятно, выдает ли при этом слэйв аппаратно ACK?). Нет такого события. Слейв не реагирует на START. Зато есть событие 0x60 Own SLA+W has been received; ACK has been returned Это значит, что первое прерывание у слейва возникает только если его адрес совпал или было обращение по широковещательному адресу (событие 0x70) или их ошибочные варианты (0x68, 0x78). Далее требуется коррекция Вашего алгоритма. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
James D. 0 21 декабря, 2005 Опубликовано 21 декабря, 2005 · Жалоба Это значит, что первое прерывание у слейва возникает только если его адрес совпал или было обращение по широковещательному адресу (событие 0x70) или их ошибочные варианты (0x68, 0x78). Далее требуется коррекция Вашего алгоритма. Но ведь слэйв проверяет содержимое TWSR на соответствие $60 как раз в обработчике прерывания, значит само прерывание возникает до того. У меня обработчик слэйва начинается так: ;******************************************************************* ;Режим - подчиненный-приемник: TWI_Obr:in temp,TWSR andi temp,$F8 cpi temp,$60 ;Проверка принятого адреса breq Pr_data ;Переход на прием данных reti Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
IgorKossak 0 21 декабря, 2005 Опубликовано 21 декабря, 2005 · Жалоба ;******************************************************************* ;Режим - подчиненный-приемник: TWI_Obr:in temp,TWSR andi temp,$F8 cpi temp,$60;Проверка принятого адреса breq Pr_data ;Переход на прием данных reti В таблице Status Codes for Slave Receiver Mode в поле Application Software Response To TWCR требуется обязательно сбросить TWINT записью в него 1 после завершения всех операций по TWI, но перед reti, чтобы иметь возможность воспринимать другие события. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
IgorKossak 0 21 декабря, 2005 Опубликовано 21 декабря, 2005 · Жалоба Добавлю также, что надо анализировать ВСЕ события и делать все действия. Ничего не сокращая! Оптимизировать будете когда всё заработает. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
bodja74 0 21 декабря, 2005 Опубликовано 21 декабря, 2005 · Жалоба То bodja74: "Если на шине не то что ему нужно,он просто не выдаст прерывания" А вот и нет - выдает постоянно, даже если к нему никто не обращается. Это я вижу? Или это сон? А если слэйву из прерывания не выходить, при приеме адреса, данных, а принимать все в пределах одного прерывания по TWI? Просто ждать, когда TWINT уст. в "1"? Зачем? "И ПОСЛЕДНЕЕ решаем выставлять нам АСК при следующем получении данных или нет." Что-то я не пойму все-таки, как слэйв должен выдавать ACK или NACK. Это же делается аппаратно? Как это сделать программно? Аппаратно выставляется АСК при совпадении адресса. Программно можно выставить NACK при получении данных елементарно TWEA=0 Мастер на шине один, и два подчиненных. Значит обработку ошибок касательно арбитража можно откинуть? Что должен делать слэйв, если его адрес не совпал с переданным мастером? В даташитовской таблице для подч-приемника это не описано. 1 Арбитраж нужен когда два мастера ,а не два слейва. 2 Если адресс слейва не совпал ,слейв ничего не делает (NACK) 3 В таблице ничего и не будет описано.В таблице описаны ТОЛЬКО ТЕ СОБЫТИЯ при которых возникает прерывания.Поэтому и задал вопрос в начале поста Теперь раскладка по регистрам что касается слейва 1 Инициализация TWI 1.1 #H00->TWBR 1.2 #H00->TWSR //Устанавливаем максимальную скороcть приема 1.3 #H40->TWAR //Адресс слейва 20НЕХ без учета последнего разряда 1.4 #H45->TWSR //Включение ,разрешение прерывания,ACK ,(TWINT=0) 2 Основная программа (ждем прерывание) 3 Прерывание по TWI (TWI_Finished) 3.1 <TWSR=#H60> //Если TWSR=#H60 ,устанавливаем TWINT=1 (#HC5->TWCR),Выходим из подпрограммы (RETI) 3.2 <TWSR=#H80> //Если TWSR=#H80 ,устанавливаем TWINT=1 (#HC5->TWCR),Извлекаем данные из TWDR,Выходим из подпрограммы (RETI) 3.1 <TWSR=#H88> //Если TWSR=#H88 ,устанавливаем TWINT=1 (#HC5->TWCR),Выходим из подпрограммы (RETI) Все!!! Сложно? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
bbill 0 22 декабря, 2005 Опубликовано 22 декабря, 2005 · Жалоба Немного не по теме. Кто-нибудь встречал русскоязычное описание USI для "тинек", для того же двухпроводного интерфейса? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
James D. 0 22 декабря, 2005 Опубликовано 22 декабря, 2005 (изменено) · Жалоба Сделал следующее. Убрал из программ мастера и слэйва передачу данных при включении обоих МК - там было не по прерываниям, а в основной программе. Далее. Слэйв: ;Инициализация TWI: ldi temp,$00;Установка скорости передачи out TWBR,temp ldi temp,$00 out TWSR,temp ldi temp,$40;Инициализация режима "Приемник" out TWAR,temp ldi temp,(1<<TWEA)|(1<<TWEN)|(1<<TWIE) out TWCR,temp sei ;Обработчик прерывания TWI (слэйв): TWI_Obr:in temp,TWSR andi temp,$F8 cpi temp,$60;Проверка принятого адреса от мастера breq Address cpi temp,$80;Прием данных breq Data cpi temp,$88;Stop breq Stop reti Address:ldi temp,(1<<TWINT)|(1<<TWEA)|(1<<TWEN)|(1<<TWIE) out TWCR,temp reti ;Прием данных: Data:ldi temp,(1<<TWINT)|(1<<TWEA)|(1<<TWEN)|(1<<TWIE);здесь пока ничего не делается out TWCR,temp reti ;Стоп: Stop:ldi temp,(1<<TWINT)|(1<<TWEA)|(1<<TWEN)|(1<<TWIE) out TWCR,temp reti Программа мастера: sbi PORTD,2;Временная индикация sbi PORTD,3 sbi PORTC,2 sbi PORTC,3 sbi PORTC,4 sbi PORTC,5 sbi PORTC,6 ldi temp,$00;Установка скорости передачи= ? kHz out TWBR,temp ldi temp,$00 out TWSR,temp Pusk_Sn:ldi temp,(1<<TWINT)|(1<<TWSTA)|(1<<TWEN) out TWCR,temp;Посылка сигнала "START" wait1n: in temp,TWCR;Ожидаем ответа от слэйва sbrc temp,TWINT rjmp wait1n in temp,TWSR andi temp,$F8 cpi temp,$08;Проверка подтверждения приема от слэйва brne Pusk_Sn SLA_Wn: ldi temp,$20;Загрузка адреса слэйва + "WRITE" out TWDR,temp ldi temp,(1<<TWINT)|(1<<TWEN) out TWCR,temp wait2n: in temp,TWCR;Ожидаем ответа от слэйва sbrs temp,TWINT rjmp wait2n in temp,TWSR;Переход, в зависимости от содержимого TWSR andi temp,$F8 cpi temp,$08 breq Kod_08 cpi temp,$10 breq Kod_10 cpi temp,$18 breq Kod_18 cpi temp,$20 breq Kod_20 cpi temp,$28 breq Kod_28 cpi temp,$30 breq Kod_30 cpi temp,$38 breq Kod_38 ST_TWI: rjmp ST_TWI Kod_08: cbi PORTD,2;Индикация на светодиодах rjmp Kod_08 Kod_10: cbi PORTD,3 rjmp Kod_10 Kod_18: cbi PORTC,2 rjmp Kod_18 Kod_20: cbi PORTC,3 rjmp Kod_20 Kod_28: cbi PORTC,4 rjmp Kod_28 Kod_30: cbi PORTC,5 rjmp Kod_30 Kod_38: cbi PORTC,6 rjmp Kod_38 Так вот, слэйв в обработчик прерывания вообще не заходит, а мастер содержит в TWSR код $08 (по индикации). На шине TWI оставил, для чистоты эксперимента, только два МК - мастер и слэйв. И еще: скорость передачи устанавливается только в мастере, или в слэйве тоже? Изменено 22 декабря, 2005 пользователем James D. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
IgorKossak 0 22 декабря, 2005 Опубликовано 22 декабря, 2005 · Жалоба 1. Скорость передачи устанавливается только в мастере и обязательно! Note: TWBR should be 10 or higher if the TWI operates in Master mode. If TWBR is lower than 10, the Master may produce an incorrect output on SDA and SCL for the reminder of the byte. The problem occurs when operating the TWI in Master mode, sending Start + SLA + R/W to a Slave (a Slave does not need to be connected to the bus for the condition to happen). При тактовой 8МГц и скорости TWI 100кГц TWBR = 32. 2. Между этими командами у слейва breq Stop reti тоже надо вставить сброс TWINT на случай ошибочных ситуаций (может даже с какой-нибудь индикацией). 3. Мастер. При посылке СТАРТ мы ожидаем реакции не от слейва, а от интерфейса (но это только терминология). СТАРТ будет осуществлён и TWINT возникнет только тогда, когда шина будет свободна и вариантов здесь нет. Закольцовывать эту процедуру brne Pusk_Sn не нужно. 4. Байт адреса слейва, передаваемый мастером в Вашем случае должен быть 0x40, т. е. сдвинутым на 1 влево, т. к. младший бит это R/W. См. рисунок Typical Data Transmission. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться