James D.
Nov 4 2005, 17:14
Соединил 3 МК по TWI - Master передает данные на Slave 1, потом на Slave 2 (поочередно, друг за другом). Два из них общаются нормально (односторонняя передача от Master к Slave 1), а как только нужно передать от Master к Slave 2, один раз передача проходит и все зависает. Судя по всему, после этого не получается передать данные на Slave 1.
В конце каждой передачи Master осуществляет условие STOP
STOP: ldi temp,(1<<TWINT)|(1<<TWSTO)|(1<<TWEN)
out TWCR,temp,
а Slave 1/2, после приема переданных байт, просто переходят к дальнейшему выполнению основной программы, т.е. никаких стоповых функций нет. Должны ли они как-то обрабатывать функцию STOP?
Можно ли в режиме "slave приемник" узнать какой адрес передал "master передатчик", т.е. к кому в данный момент он обращается? Появляется ли этот адрес в TWDR?
Как правильно обратиться к конкретному "slave приемнику", чтобы второй "slave приемник" на вызов не реагировал?
James D.
Nov 5 2005, 15:37
Попробовал отключать от линии приемник, к которому сейчас нет обращения:
ldi temp,(0<<TWEA)
out TWCR,temp
Все равно где-то вся эта лабуда зависает!
У меня Мастер-передатчик - mega32, первый приемник - тоже mega32, второй приемник - mega16.
Выяснил вот что: когда мастер пытается обращаться ко второму приемнику, после посылки сигнала START, они оба зацикливаются:
wait1: in temp,TWCR
sbrs temp,TWINT
rjmp wait1
дальше этого цикла ожидания у них дело не идет. То ли мастер не может START передать, то приемник не может его получить.
В чем же тут проблема?
haker_fox
Nov 6 2005, 08:18
Была у меня такая ситуация. Но я забыл поставить на линии резисторы на +5В. У Вас они стоят? По сколько КОм?
И если можно, выложите код, относящийся к TWI.
James D.
Nov 6 2005, 08:43
Резисторы по 4.7кОм стоят на каждой линии (соединяют с +5В).
Привожу пример моих прог приема-передачи.
Передатчик - mega32, приемник - mega16. Передатчик зависает на этапе передачи адреса + W, а приемник зацикливается в цикле wait1n:
Как это все настроить?
Эта прога находится в передатчике:
;*******************************************************************
;Программа передачи байта от мастера подчиненному:
To_SR: ldi temp,$00 ;Установка скорости передачи=22727 Hz
out TWSR,temp
ldi temp,$14
out TWBR,temp
Pusk_Sr: ldi temp,(1<<TWINT)|(1<<TWSTA)|(0<<TWSTO)|(1<<TWEN)
out TWCR,temp ;Посылка сигнала "START"
wait1r: in temp,TWCR ;Ожидаем ответ от SR-контроллера
sbrs temp,TWINT
rjmp wait1r
in temp,TWSR
andi temp,$F8
cpi temp,$08 ;Проверка подтверждения приема от SR (START)
brne Pusk_Sr
SLA_Wr: ldi temp,$04 ;Загрузка адреса SR-контроллера + "WRITE"
out TWDR,temp
ldi temp,(1<<TWINT)|(0<<TWSTA)|(0<<TWSTO)|(1<<TWEN)
out TWCR,temp
wait2r: in temp,TWCR ;Ожидаем ответ от SR-контроллера
sbrs temp,TWINT
rjmp wait2r
in temp,TWSR
andi temp,$F8
cpi temp,$18
brne SLA_Wr ;Переход, если ответ от SR неверный
;Начинаем передавать данные:
DATA_r: out TWDR,Byte ;Отправка байта данных
rcall Writer
rjmp STOP_r ;Передача данных завершена
;*******************************************************************
Writer: ldi temp,(1<<TWINT)|(0<<TWSTA)|(0<<TWSTO)|(1<<TWEN)
out TWCR,temp
wait3r: in temp,TWCR ;Ожидаем ответ от SR-контроллера
sbrs temp,TWINT
rjmp wait3r
in temp,TWSR
andi temp,$F8
cpi temp,$28
brne Writer ;Переход, если ответ от SR неверный
ret
;*******************************************************************
;Все данные переданы - STOP (линия приема/передачи переходит в высокоимпедансное состояние)
STOP_r: ldi temp,(1<<TWINT)|(0<<TWSTA)|(1<<TWSTO)|(1<<TWEN)
out TWCR,temp
;*******************************************************************
А эта прога находится в приемнике:
;*******************************************************************
;Программа приема байта от мастера:
From_MT: ldi temp,$04 ;Инициализация режима "Приемник"
out TWAR,temp
TWINT_n: ldi temp,(1<<TWINT)|(1<<TWEA)|(0<<TWSTA)|(0<<TWSTO)|(1<<TWEN)
out TWCR,temp
wait1n: in temp,TWCR ;Ожидаем вызова от MT-контроллера
sbrs temp,TWINT
rjmp wait1n
in temp,TWSR
andi temp,$F8
cpi temp,$60 ;Проверка принятого адреса от MT
brne TWINT_n
;Прием данных:
Pr_data: rcall TW_NT_n ;Прием байта
in Byte,TWDR
rjmp STOP_n
;*******************************************************************
TW_NT_n: ldi temp,(1<<TWINT)|(1<<TWEA)|(0<<TWSTA)|(0<<TWSTO)|(1<<TWEN)
out TWCR,temp
wait2n: in temp,TWCR ;Ожидаем ответа от MT-контроллера
sbrs temp,TWINT
rjmp wait2n
in temp,TWSR
andi temp,$F8
cpi temp,$80
brne TW_NT_n ;Переход, если данные от MT не получены
ret
;*******************************************************************
;Все данные приняты - STOP (линия приема/передачи переходит в высокоимпедансное состояние)
STOP_n: ldi temp,(1<<TWINT)|(1<<TWEA)|(0<<TWSTA)|(0<<TWSTO)|(1<<TWEN)
out TWCR,temp
wait4: in temp,TWCR ;Ожидаем ответа от MT-контроллера
sbrs temp,TWINT
rjmp wait4
in temp,TWSR
andi temp,$F8
cpi temp,$A0
brne STOP_n ;Переход, если STOP от MT не получен
;*******************************************************************
haker_fox
Nov 6 2005, 10:41
Цитата
SLA_Wr: ldi temp,$04 ;Загрузка адреса SR-контроллера + "WRITE"
out TWDR,temp
ldi temp,(1<<TWINT)|(0<<TWSTA)|(0<<TWSTO)|(1<<TWEN)
out TWCR,temp
Не нужно при передачи байта посылать условие старт, нужно заменить строку на эту:
ldi temp,(1<<TWINT)|(1<<TWEN)
это по программе в передатчике, по приемнику - не знаю.
Но советую зайти на www.atmel.com и скачать примеры (application notes), там есть несколько довольно неплохих документов. Я по ним разбирал работу модуля TWI. Кстати где-то ниже должна быть моя ветка "Проблемы TWI".
James D.
Nov 6 2005, 12:44
Да примеры-то эти я уже давно все скачал и просмотрел. Но примеры там на Си, а я его не знаю...
Строку заменил, то же самое: передатчик зависает на этапе передачи адреса + W, а приемник зацикливается в цикле wait1n:
Контроллеры соединены двухжильным проводом, и находятся на расстоянии ~15см. Уже не знаю на что и грешить.
haker_fox
Nov 6 2005, 14:16
Цитата
Pusk_Sr: ldi temp,(1<<TWINT)|(1<<TWSTA)|(0<<TWSTO)|(1<<TWEN)
out TWCR,temp ;Посылка сигнала "START"
Вы устанавливаете биты "старт" и "стоп" одновременно! так делать нелья, условие старт подается так;
Pusk_Sr: ldi temp,(1<<TWINT)|(1<<TWSTA)|(1<<TWEN)
out TWCR,temp ;Посылка сигнала "START"
Потом, условие стоп!
Цитата
;Все данные переданы - STOP (линия приема/передачи переходит в высокоимпедансное состояние)
STOP_r: ldi temp,(1<<TWINT)|(0<<TWSTA)|(1<<TWSTO)|(1<<TWEN)
out TWCR,temp
Оно (условие) не отличается от условия "СТАРТ" выше.
условие "стоп" передается так
;Все данные переданы - STOP (линия приема/передачи переходит в высокоимпедансное состояние)
STOP_r: ldi temp,(1<<TWINT)|(1<<TWSTO)|(1<<TWEN)
out TWCR,temp
Я думаю, что еще есть ошибки! В общем весь текст программы практически не верный. Нужно искать примеры в интернете на асме.
Могу посоветовать:
www.avrfreaks.net
В даташите на МК с аппаратным TWI есть вся необходимая информация. Там же есть примеры на асме, как передавать данные по этой шине. Удачи.
James D.
Nov 6 2005, 15:11
Так в даташите как раз есть такая фраза:
"Для разрешения работы TWI необходимо записать лог. 1 в TWEN. Для разрешения подтверждения собственно подчиненного адреса или адреса общего вызова записывается 1 в TWEA. Битам TWSTA и TWSTO необходимо присвоить нулевое значение." Я же это не придумал.
Заходил на www.avrfreaks.net, по TWI нашел только программную реализацию всей этой лабуды, а на кой, спрашивается тогда, разработчики делали аппаратный TWI?
В энный раз просмотрел свою прогу, изменил указанные места:
STOP_r: ldi temp,(1<<TWINT)|(0<<TWSTA)|(1<<TWSTO)|(1<<TWEN)
out TWCR,temp, и т.д. все равно приемник не признает передаваемый адрес.
James D.
Nov 6 2005, 16:29
Выяснилось следующее: если передавать с mega32 на mega32 - TWI работает нормально, с mega16 на mega32 - тоже, а с mega32 на mega16 - не работает.
Может тут какие-то тонкости есть?
AVR089 просмотрел, там ничего подходящего к моей ситуации нет: прерывания я не использую, спящий режим тоже.
haker_fox
Nov 7 2005, 00:12
Цитата
STOP_r: ldi temp,(1<<TWINT)|(0<<TWSTA)|(1<<TWSTO)|(1<<TWEN)
Так нельзя сбрасывать бит TWSTA. В левой части всегда должна быть 1, т.к. она сдвигается на определенное количество разрядов. Для бита TWINT=7, еденица сдвинется на 7 разрядов влево (операция <<) и в 7 разряде будет лог. 1.
Для сброса бита можно воспользоваться инструкцией cbi.
В общем нужно разобраться с самим ассемблером. И еще в форуме тяжело объяснять такие вещи. Если хотите, можно пообщаться в аське.
Мой ICQ UIN 339085018. Я там обычно с 3-00 до 13-00 по Московскому времени. Обращайтесь!
В VMLAB в папке AVR_demo есть рабочий проект TWI на асме.
Удобно то, что на осциллографе можно просмотреть все сигналы.
Советую посмотреть.
Удачи.
James D.
Nov 7 2005, 05:32
Вы понимаете, я обнуление (например, 0<<TWSTA и пр.) везде повыкидывал, оставил только те биты, которые надо установить в 1.
Программа работает, но передача осуществляется только с mega32 на mega32 или с mega16 на mega32. А с mega32 на mega16 - не работает.
Вот в чем проблема. А программа работоспособная, на все сто.
Может там fuse биты у МК настраивать надо?
To rmo:
У меня, к сожалению, нет программы VMLAB, я был бы вам очень благодарен, если бы вы мне сказали где можно скачать полностью работоспособную версию этой проги. Я слыхал, там можно смоделировать работу двух МК - вот это мне бы подошло!
James D.
Nov 7 2005, 10:41
М-да, выглядит как игрушка. Сомневаюсь я насчет реального моделирования.
Да и разбираться с ней времени нет. Я как-то к AVRStudio уже привык и осваивать новую прогу неохота.
Посмотрел я пример TWI - общий алгоритм у меня такой же, только без прерываний. И, главное, моя прога-то работает, но только с mega32 на mega16 данные не передаются. А обратно - пожалуйста.
Вот в чем проблема!
beer_warrior
Nov 7 2005, 12:30
Ну я думаю во-первых, если не работает на разных кристаллах, проверить инициализацию меги 16.
Во-вторых, есть подозрение, что в транзакция не закрываеться
(не опознан адрес, не выставлен ACK etc)
Посему скромная рекомендация: делаем некую переменную, в которую по окончанию каждого этапа транзакции, ложим число.
По окончании всего выбрасываем это число на индикатор или в uart.
И смотрим в какой момент автомат TWI понесло не в ту сторону.
James D.
Nov 7 2005, 12:53
У меня временная индикация сделана на светодиодах.
Приемник (В этом случае - диод D,0 горит, а D,1 нет):
From_MT:ldi temp,$04 ;Инициализация режима "Приемник"
out TWAR,temp
TWINT_n:ldi temp,(1<<TWINT)|(1<<TWEA)|(1<<TWEN)
out TWCR,temp
cbi PORTD,0
wait1n: in temp,TWCR ;Ожидаем вызова от MT контроллера
sbrs temp,TWINT
rjmp wait1n
cbi PORTD,1
in temp,TWSR
andi temp,$F8
cpi temp,$60 ;Проверка принятого адреса от MT
brne TWINT_n
cbi PORTD,2
.
.
.
Передатчик (здесь С,2; C,3; C,4 и C,5 - горят, а С,6 - уже не горит):
To_SR:
ldi temp,$00 ;Установка скорости передачи= 10 kHz
out TWSR,temp
ldi temp,192
out TWBR,temp
Pusk_Sr:ldi temp,(1<<TWINT)|(1<<TWSTA)|(1<<TWEN)
out TWCR,temp ;Посылка сигнала "START"
cbi PORTC,2
wait1r: in temp,TWCR ;Ожидаем ответа от SR контроллера
sbrs temp,TWINT
rjmp wait1r
cbi PORTC,3
in temp,TWSR
andi temp,$F8
cpi temp,$08 ;Проверка подтверждения приема от SR (START)
brne Pusk_Sr
cbi PORTC,4
SLA_Wr: ldi temp,$04 ;Загрузка адреса SR-контроллера + "WRITE"
out TWDR,temp
ldi temp,(1<<TWINT)|(1<<TWEN)
out TWCR,temp
wait2r: in temp,TWCR ;Ожидаем ответа от SR контроллера
sbrs temp,TWINT
rjmp wait2r
cbi PORTC,5
in temp,TWSR
andi temp,$F8
cpi temp,$18
brne SLA_Wr ;Переход, если ответ от SR неверный
cbi PORTC,6
.
.
.
beer_warrior
Nov 7 2005, 13:25
Ну и все проходит нормально?
Нигде не не вылетает с неопознаным кодом?
James D.
Nov 7 2005, 14:12
Прога полностью работает при пересылке от m32 (мастер передатчик) к m32 (подчин. приемник) или от m16 (мастер передатчик) к m32 (подчин. приемник), а если от m32 (мастер передатчик) к m16 (подчин. приемник) - получается вышеприведенная ситуация.
beer_warrior
Nov 7 2005, 15:24
Ну и на каком этапе вылетает обмен между м32 и м16?
Все таки еще раз напомню о проверке инициализации м16 как slave.
_artem_
Nov 7 2005, 16:22
Ne znayu rabotaet ili net - no yesli da mozet i prigoditsya dlya debugginga sini .
http://fruttenboel.verhoeven272.nl/i2c/index.html
James D.
Nov 7 2005, 21:08
To beer_warrior:
а как проверить инициализацию м16 как slave?
Приемник (m16) cтопорит на начальном этапе ожидания связи с передатчиком - бит TWINT не устанавливается.
Передатчик (m32) после передачи SLA+W не принимает ACK - судя по-всему код в TWSR не $18.
_artem_
Nov 7 2005, 23:28
Po moemu v code priemnika ty dlzen zapisat v TWAR $08 vmesto $04. Tam address biti smeseni na odnu poziciyu nalevo tak chto u tebya slave ozidaet address 2 a ne 4 .
Vnizu raskladka is Data sheeta atmega 16 dlya TWAR registra:
-------------------------------------------------------------
TWA6 TWA5 TWA4 TWA3 TWA2 TWA1 TWA0 TWGCE
-------------------------------------------------------------
0 0 0 0 0 1 0 0
daet address $02 dlya priemnika .
James D.
Nov 8 2005, 06:49
Попробовал $08 - не то.
Понимаете, artem, с mega32 пересылаю на mega32 - все работает (с адресом $04 у обоих; если ставлю $08 у приемника - не работает), потом вынимаю mega32 - приемник, ставлю на его место mega16 - не работает с любыми адресами!
beer_warrior
Nov 8 2005, 08:57
Цитата(James D. @ Nov 7 2005, 23:08)

To beer_warrior:
а как проверить инициализацию м16 как slave?
Приемник (m16) cтопорит на начальном этапе ожидания связи с передатчиком - бит TWINT не устанавливается.
Передатчик (m32) после передачи SLA+W не принимает ACK - судя по-всему код в TWSR не $18.
Я имею в виду нет ли различий в коде м16 и м32. Возможно даже не относящихся непосредственно
к TWI. (прерывания, ватчдог)
Далее, проясните вопрос с передачей: клинит на первом обращении или на последующих, не требуеться ли repeated start?
Далее, проверяем прошел ли нормально start condition, если нет то что в статусе у мастера.
Бит TWINT должен устанавливаться в любом случае, если посылка проехала физически,
проверьте это.
Далее проверяем все-таки что твориться в TWSR слэйва, он возвращает ACK, NACK, arbitration lost,
что-то другое?
Для блезиру можно попробовать SLA+R, general call возможно это что-то прояснит.
_artem_
Nov 8 2005, 10:04
Soglasen s beer_warrior, nado snachala soblyusti chistotu eksperimenta - ubrat vse vnesnie faktori mogusie pomesat i smotret na status register pered peredachey i v techenii ee .
No mne klazetsya podozritelnym chto device reagiruyet na $02 kogda kak $04 posilaetsya .
Slusay a ne mozes li ty gotoviy proyekt zaprogramirovat v atmega 16 "AVR311: Using the TWI module as I2C slave". To est mozno budet ubeditsya chto chip rabotaet po proverennomu kodu.
James D.
Nov 8 2005, 10:51
Различия в коде, конечно есть.
Система у меня такая: два m32 + m16, все три соединены по TWI. Обе меги32 работают нормально (у каждой свой код), регулярно одна мега (мастер передат.) передает данные на другую (подчинен. приемник) приблиз. 30 раз в сек.
Мега 16 имеет функцию часов реального времени - внеш. кварц 32768 Гц. По нажатию спец. кнопочки, m32 (мастер передат.) связывается с m16 (подчинен. приемник), передает пару байт, и должен принять текущее значение времени. Так вот, при первом же нажатии этой кнопки связи не получается, оба контроллера зависают, а третий - m32 (подчинен. приемник), продолжает работать. То есть клинит на первом обращении.
Сделал еще два пробных проекта - первый m16 - мастер приемник, второй - m32 - подчин. передатчик. Ничего лишнего, только у m16 оставил часы реал. врем. Работают оба МК по прерываниям таймеров по переполнению или совпадению (в принципе неважно, главное связь по TWI проходит одним циклом, т.е. сработало прерывание - идет передача, закончилась передача - reti) После многочисленных неудачных попыток, заработало - пришлось только у обоих МК в самом конце передачи вставить команду
ldi temp,(0<<TWEN)
out TWCR,temp
потому как все зависало при ВТОРОМ соединении, первое полностью проходило нормально.
Вставил эти рабочие куски кода в свою 3-х контроллерную систему, все проверил, но опять та же фигня - клинит на первом же обращении m32 к m16.
Может соединить все это хозяйство по USART? Как думаете?
Беда только в том, что с USART я никогда не работал, как там со сложностью и стабильностью?
beer_warrior
Nov 8 2005, 11:39
USART это точка-точка в общем случае.
Вам какое расстояние нужно? Может SPI спасет.
По поводу TWI. Если я правильно понял вход слэйва в режим
приема производиться по таймеру. Это не есть хорошо. Слэйв на то
и слэйв чтобы вестись в обмене сигналами мастера. Т.е. мы ждем
прерывания от TWI (start condition) далее не вылазим оттедова пока
мастер нас не отпустит.
Сильно подозреваю что по вашей системе слэйв теряет либо старт
либо один из клоков и поэтому ждет еще чего-н из порта.
А вообще-то переходите на С, сильно облегчит жизнь :-)
James D.
Nov 8 2005, 11:42
Еще кое-что удалось выяснить: убрал я передачу данных на вторую m32 (приемник), заработала связь m16 - мастер приемник, с m32 - подчинен. передатчик. По нажатию кнопочки, все как положено.
У меня уже крыша едет.
У меня сделано так: первая m32 - это мастер-передатчик, когда связывается со второй m32, и подчиненный передатчик, когда связывается с m16. Видно что-то происходит со связью после соединения m32-m32, так как после этого не получается соединение первой m32 с m16.
Как же правильно завершать работу TWI, и переходить с мастера-передатчика на подчиненный передатчик?
В даташите про это ничерта не написано! Мудрецы!
P.S. Связь m32-m32 и m32-m16 осуществляется в пределах одного обработчика прерывания. Сначала идет передача на один МК, потом на второй. По следующему прерыванию опять тоже самое.
beer_warrior
Nov 8 2005, 12:42
Батенька, с арбитражем у вас проблемы. И с отработкой нештатных
ситуаций.
К изучению:
ATMega16 ->TWI ->Multi-master Systems and Arbitration
http://www.semiconductors.philips.com/acro...98/39340011.pdfМогу закинуть свой исходник на С и по непонятным местам прокомментировать
beer_warrior
Nov 8 2005, 12:56
Батенька, с арбитражем у вас проблемы. И с отработкой нештатных
ситуаций.
К изучению:
ATMega16 ->TWI ->Multi-master Systems and Arbitration
http://www.semiconductors.philips.com/acro...98/39340011.pdfМогу закинуть свой исходник на С и по непонятным местам прокомментировать
James D.
Nov 8 2005, 13:39
Спасибо, изучу PDF и арбитраж.
А насчет Си, я боюсь, вам очень многое придется объяснять, и начать придется с самого Си.

Кстати насчет арбитража. Первоначально, у меня был только один мастер - m32, и два подчиненных - m32 и m16. Мастер просто должен был передавать данные то одному то другому. Никаких других мастеров в системе нет, о какой потере арбитража может идти речь?
beer_warrior
Nov 8 2005, 15:48
Ну тогда и говорим о первоначальном варианте.
м32 мастер, м32 слэйв, м16 слэйв.
Мастер пишет в слэйв м32по таймеру.
Мастер читает слэйв м16 по кнопке.
Я правильно понял?
James D.
Nov 8 2005, 16:16
Правильно так:
м32 мастер, м32 слэйв, м16 слэйв.
1. Вход в обработчик прерывания таймера.
2. Мастер пишет в слэйв м32 по таймеру.
3. Мастер пишет в слэйв м16 по таймеру (забудем о кнопке, просто запись в м16 может производиться, но может быть и пропущена, после записи мастер читает из слэйв м16 (чтение идет сразу же после записи и может быть также пропущено - запись/чтение - одна операция)).
4. Выход из обработчика прерывания.
Дальше все повторяется.
beer_warrior
Nov 8 2005, 20:54
ОК, значит щелкнул таймер, обмен с м32 прошел, начал писать
в м16 и заткнулся. Так?
Если да, то проверить правильно ли отработал стоп в первом обмене
и старт во-втором. Поставить приличную паузу между стопом и стартом.
Заремить запись в м16 и тупо прочитать 1 байт.
Мне почему-то кажеться, что что-то не так со второй транзакцией.
James D.
Nov 9 2005, 07:08
Для чистоты эксперимента сделал следующее.
Общение всех МК происходит в самом начале работы программ, т.е. после RESET идет настройка стека и портов, и сразу же вкл. работа блоков TWI.
1. Мастер m32 вызывает п/п передачи на слэйв m32 (адрес $02), потом на слэйв m16 (адрес $04) и останавливается - задан бесконечный цикл.
2. Слэйв m32 (RESET, настройка стека и портов) вызывает п/п приема данных, принимает несколько байт данных от мастера, индицирует завершение своей работы (светодиод), и останавливается - задан бесконечный цикл. Этот пункт полностью работает.
3. Слэйв m16 (RESET, настройка стека и портов), во время обмена двух m32 постоянно ждет, когда к нему обратится мастер (см. ниже цикл ожидания wait11).
После того, как мастер завершил передачу на слэйв m32, он индицирует завершение своей работы со слэйв m32 (светодиод), потом вызывает п/п передачи на слэйв m16, посылает START, принимает подтверждение (код $08), загружает адрес слэйв m16 + Write, и после этого ждет когда бит TWINT установится в "1". И все. Бит TWINT не устанавливается.
Слэйв m16, пример кода:
From_A1:ldi temp,$04 ;Инициализация режима "Приемник"
out TWAR,temp
TWINT_1:ldi temp,(1<<TWINT)|(1<<TWEA)|(1<<TWEN)
out TWCR,temp
cbi PORTD,0
wait11: in temp,TWCR ;Ожидаем вызова от мастера m32
sbrs temp,TWINT
rjmp wait11
cbi PORTD,1
Здесь светодиод PORTD,0 - горит, а PORTD,1 - нет. Бит TWINT не устанавливается.
beer_warrior
Nov 9 2005, 09:40
ОК, первая посылка мастера SLAW?
Тогда проверяем какой код вернул мастер 08, 10,18,20,30,38
т.е. что ушло с мастера.
добавлено:
Еще раз пересмотрел условия, сначала опрашиваеться м32, так вот это отключить и сразу писать в м16
James D.
Nov 9 2005, 11:30
Слэйв м32 отключил, пишу сразу в м16.
Кусок кода в мастер м32:
ldi temp,$00 ;Установка скорости передачи= ? kHz
out TWSR,temp
ldi temp,$14
out TWBR,temp
Pusk_S1:ldi temp,(1<<TWINT)|(1<<TWSTA)|(1<<TWEN)
out TWCR,temp ;Посылка сигнала "START"
wait11r:in temp,TWCR ;Ожидаем ответа от слэйв м16
sbrs temp,TWINT
rjmp wait11r
in temp,TWSR
andi temp,$F8
cpi temp,$08 ;Проверка подтверждения приема от слэйв м16 (START)
brne Pusk_S1
SLA_W1: ldi temp,$04 ;Загрузка адреса слэйв м16 + "WRITE"
out TWDR,temp
ldi temp,(1<<TWINT)|(1<<TWEN)
out TWCR,temp
wait22r:in temp,TWCR ;Ожидаем ответа от слэйв м16
sbrs temp,TWINT
rjmp wait22r
in temp,TWSR
andi temp,$F8
cpi temp, (здесь идет проверка кода)
Мастер вернул код $20 - SLA+W был передан, NOT ACK был принят. Почему так?
beer_warrior
Nov 9 2005, 12:32
Ну во-первых, адрес надо сдвигать на 1 бит и накладывать маску 0 или 1 в 0 разряде.
100% не уверен, однако м16 словила старт и теперь тупо ждет
опознания адреса.
TWINT выставляеться по совпадению адреса, а адрес не совпал.
Если бы работало на прерывании, м16 в него бы просто не заехал,
и жил бы себе дальше.
addr = (addr << 1) | 0x01; для чтеия
addr = (addr << 1) & 0xfe; для записи
обязательно.
James D.
Nov 9 2005, 12:52
Вынул из панельки слейв м16, и поставил туда слэйв м32. Зашил в сл. м32 ту же прогу, какая была в сл. м16 (без всяких изменений). Теперь мастер выдал код $18 - то, что и должно быть.
beer_warrior
Nov 9 2005, 13:00
Так может просто кристалл битый?
James D.
Nov 9 2005, 13:09
Сдвинул в мастере код слэйв м16:
ldi temp,$04 ;Загрузка адреса м16 + "WRITE"
lsl temp
andi temp,$FE
out TWDR,temp
Выдается тот же код - $20.
Или я что-то не то делаю?...
У меня есть два м16 - оба выдают такую фигню. Вряд ли они оба битые.
К тому же пробовал ставить м16 - мастером приемником, а м32 - слэйв передатчиком - все работало (на макете, а в основной проге - по прерываниям и т.д. - работать отказался).
James D.
Nov 9 2005, 13:22
Да, и еще. Раньше у меня в системе (громко звучит, не правда ли

) было задействовано два м16 (эти самые, с которыми теперь мучаюсь); один другому передавал данные по TWI. Потом я их заменил на м32.
Так что они полностью исправны. Проверено.
beer_warrior
Nov 9 2005, 13:24
ОК делаем вот такой финт - сразу после инициализации зацикливаем
м16, разрешаем прерывание и в прерывании зажигаем светодиод.
После этого бомбим м16 разными адресами
James D.
Nov 9 2005, 14:20
Значит сделал так: (в м16) после настройки стека и портов настроил прерывание (мигающий светодиод), и сразу же идет работа блока TWI. Так вот, вы знаете передал таки м32 данные на м16! И диод мигает.
Адрес $04 задается у обоих контроллеров.
Ну это хорошо, а как теперь мне культурно все это заделать в своей системке?
Ё-моё! Хоть что-то заработало!!!
James D.
Nov 9 2005, 14:38
Вы еще мне объясните: зачем это левое прерывание-то понадобилось? Чтобы привести в чувство TWI?
beer_warrior
Nov 9 2005, 16:32
Неа, я имел в виду прерывание по TWI т.е. гарантированую хардварную проверку срабатывания TWINT.
Но в любом случае это показало, что девайс работоспособен
и проблема вероятнее всего состоит в неправильном отлове TWINT
Прерывания не зря придумали.
Вот пример проверенный. switсh это проверка условия, case это то, что делаеться по условию.
Обрабатываються все возможные ситуации. Изучайте логику перекладывайте на асм.
James D.
Nov 9 2005, 17:03
Я так и подумал, что надо задействовать прерывание TWI, но из вашего сообщения толком не понял какое прерывание вы имели в виду, поэтому решил попробовать сначала так. И заработало. Попробую переделать основную прогу, если не получится, тогда буду мудрить с прерываниями TWI.
_artem_
Nov 10 2005, 03:14
James , voobse to etot Atmel nado povesit ).
Vot prostudiroval ego datasheet na atmega16 i on govorit chto :
To initiate the Slave Transmitter mode, TWAR and TWCR must be initialized as follows:
TWAR (kak obychno u tebya v programme)
TWCR TWINT TWEA TWSTA TWSTO TWWC TWEN – TWIE
Value 0 1 0 0 0 1 0 X
To est v samom nachale TWINT obnulyaetsya. Esli isxodit iz logiki veshey , to srazu posle zapisi v TWCR - v TWINT dolzna zapisatsya edinica po apparatnoy initializacii I2C slave mode. Et ya predpolagayu . Inache TWINT ne budet funkcionirovat kak dolzen .
Xoroso by proverit eto . Esli eto deystvitelno imeet mesto to tebe nezachem aktivizirovat preryvanie - dostatochno sledovat etoy procedure . Dlya spravki posmotri na stranicu 189 mega16.pdf (datasheet).
Krome togo u Atmela est application note dlya TWI I2C slave mode. Tam code na C pravda i rabota s preryvaniyami no dumayu chto vzglyanut ne pomesaet.
James D.
Nov 10 2005, 08:38
По прерыванию TWI что-то не работает... Прошу не бить меня ногами, но пинание в нужном направлении приветствуется.
При инициализации я сделал так:
1. Настроил прерывания:
.CSEG
.org $000 rjmp RESET ;Сброс вектор
.org $022 rjmp From_м32 ;Обработчик TWI ATmega16
2. Настроил TWI:
ldi temp,$04 ;Инициализация режима "Приемник"
out TWAR,temp
ldi temp,(1<<TWINT)|(1<<TWEA)|(1<<TWEN)|(1<<TWIE)
out TWCR,temp
потом разрешил общие прерывания:
sei
;********************
Обработчик TWI:
From_м32: in temp,TWSR
andi temp,$F8
cpi temp,$60 ;Проверка принятого адреса от м32
breq Pr_data ;Если адрес совпал - прием данных, иначе - выход из прерывания
ldi temp,(1<<TWINT)|(1<<TWEA)|(1<<TWEN)
out TWCR,temp
reti
Pr_data: здесь идет прием данных
James D.
Nov 10 2005, 09:01
artem, насчет повесить - за мной будешь, сначала он мой!