|
|
  |
Проблема с TWI |
|
|
|
Dec 25 2005, 10:57
|
Знающий
   
Группа: Свой
Сообщений: 543
Регистрация: 22-10-05
Пользователь №: 9 984

|
Вот простейший код еще для слейва. Будет работать в паре с кодом мастера ,что приводил выше. Проверка $A0 это рестарт без стопа,ее можно внести повторив код например обработчика старта,Но если мастер не делает рестарт это в принципе и не нужно. Код ; TWI Slave ; Specify Device. .include "m8def.inc"
.equ SP =$3D ; Variable Declarations .def temp = r16 .def W = r24 .def X = r26 .def Y = r28 .def Z = r30
.cseg ; CODE segment.
.org 0 rjmp PROG ; origin. reti reti reti reti reti reti reti reti reti reti reti reti reti reti reti reti rjmp TWI_Finished;Вектор прерывания TWI reti PROG: ldi r16,$F0 ;Инициализация стека out SP,r16 ldi temp,$00 ;Инициализация TWI out TWSR,temp ldi temp,$00 ; out TWBR,temp ldi temp,$40 out TWAR,temp ldi temp,$45 out TWCR,temp
ldi temp,$FF ;Подключение порта D out DDRD,temp sei cycle: nop rjmp cycle
TWI_Finished: sts $0F1,temp ;Сохранение помежуточного регистра in temp,TWSR cpi temp,$60 ;Проверка старт breq t1 in temp,TWSR cpi temp,$80 ;Проверка дата breq t2
t1: ldi temp,$C5 ;Обработка старт out TWCR,temp lds temp,$0F1 ;Востановление промежуточного регистра reti
t2: ldi temp,$C5 ;Обработка дата out TWCR,temp in temp,TWDR out PORTD,temp ;Выводим полученный байт в порт D lds temp,$0F1 ;Востановление промежуточного регистра reti
|
|
|
|
|
Dec 25 2005, 12:15
|

Местный
  
Группа: Участник
Сообщений: 315
Регистрация: 10-10-05
Пользователь №: 9 466

|
bodja74, огромное Вам спасибо за помощь. Все исправил. Работает. В слэйве счетчик принимаемых байт не стал задействовать. После приема 1-го байта, и сохранения его в память, вызывается п/п: Код ;******************************************************************* TW_NT_n:ldi temp,(1<<TWINT)|(1<<TWEA)|(1<<TWEN) out TWCR,temp
wait2n: in temp,TWCR ;Ожидаем ответа от мастера sbrs temp,TWINT rjmp wait2n
in temp,TWSR cpi temp,$80 brne STOP ;Переход на STOP, если данные от мастера не получены
ret ;*******************************************************************
STOP: ldi temp,(1<<TWINT)|(1<<TWEA)|(1<<TWEN)|(1<<TWIE) out TWCR,temp
reti вызывается она столько раз, сколько байт надо принять. Может это и не правильно, но так удобнее. Ругайте... Подключил второй слэйв. Прогу мастера подправил: Код SLA_Wn: ldi temp,$20;Загрузка адреса слэйв + "WRITE" (или адрес $40 - для второго слэйва) out TWDR,temp ldi temp,(1<<TWINT)|(1<<TWEN) out TWCR,temp
wait2n: in temp,TWCR;Ожидаем ответа от слэйв sbrs temp,TWINT rjmp wait2n
in temp,TWSR;<<<<<<<Эти команды оставил, т.к., я думаю, для двух слэйвов они нужны (?) cpi temp,$18 brne STOP ;Переход, если ответ от слэйв неверный
;Начинаем передавать данные:
DATA:
;******************************************************************* ;Все данные переданы - STOP (линия приема/передачи переходит в высокоимпедансное состояние)
STOP: ldi temp,(1<<TWINT)|(1<<TWSTO)|(1<<TWEN) out TWCR,temp Данные на первый слэйв передаются. А вот на второй - чтобы сказать наверняка, нужно теперь мастеру со второго слэйва принять данные. Потом информация выводится на LCD-индикатор, и можно быть уверенным в результате. Насчет паузы после STOP. Прога мастер-передатчик запускается около 30 раз в секунду, я думаю, этого достаточно, чтобы не делать специальную паузу. Как теперь организовать прием мастером данных от слэйв2?
|
|
|
|
|
Dec 25 2005, 13:29
|

Местный
  
Группа: Участник
Сообщений: 315
Регистрация: 10-10-05
Пользователь №: 9 466

|
Сейчас прикинул как сделать.
Мастер: 1. мастер после передачи данных, выдает STOP, 2. пауза, 3. опять настраивает скорость, выдает START, 4. ожидает ответ интерфейса, 5. выдает адрес слэйв2 - $41 в TWDR, 6. ожидает ответ от слэйв2, 7. проверяет код в TWSR=$50, сохраняет полученный байт, иначе STOP, 8. ждет следующий байт, и т.д. 9. STOP.
Правильно?
Слэйв: 1. после приема последнего байта, и получения STOP, ждет следующего прерывания, 2. принимает START+адрес+R, 3. проверяет код в TWSR=$A8, иначе STOP, 4. выдает байт данных, 5. проверяет код в TWSR=$B8, иначе STOP...
Вобщем тут я пока без четкого алгоритма...
|
|
|
|
|
Dec 25 2005, 14:23
|
Знающий
   
Группа: Свой
Сообщений: 543
Регистрация: 22-10-05
Пользователь №: 9 984

|
Цитата(James D. @ Dec 25 2005, 15:15)  bodja74, огромное Вам спасибо за помощь. Все исправил. Работает. Рад слышать что появились здвиги,Теперь можно потихоничку подключать проверку TWSR. В мастере с этим внимательно.Если Вы занесли вначале программы значение предделителяв TWSR То и зачение при проверке TWSR увеличиться на столько же. Цитата В слэйве счетчик принимаемых байт не стал задействовать. После приема 1-го байта, и сохранения его в память, вызывается п/п: Дело Ваше,но при этом прога будет крутиться в цикле обработчика,основная прога выполняться не будет. Цитата Данные на первый слэйв передаются. А вот на второй - чтобы сказать наверняка, нужно теперь мастеру со второго слэйва принять данные. Потом информация выводится на LCD-индикатор, и можно быть уверенным в результате.
Насчет паузы после STOP. Прога мастер-передатчик запускается около 30 раз в секунду, я думаю, этого достаточно, чтобы не делать специальную паузу. Если между стопом и стартом будет приличная пауза ,пожалуста. Цитата Как теперь организовать прием мастером данных от слэйв2? Тоже самое что и при передаче только адресс указываем $41(20) , $21(10),и не передаем в TWDR а илвлекаем.
|
|
|
|
|
Dec 25 2005, 16:42
|

Местный
  
Группа: Участник
Сообщений: 315
Регистрация: 10-10-05
Пользователь №: 9 466

|
Мастер: Код
;************************* ;Передача на слэйв 2: ;*************************
ldi temp,$14;Установка скорости передачи= ? kHz out TWBR,temp ldi temp,$00 out TWSR,temp
Pusk_Sr:ldi temp,(1<<TWINT)|(1<<TWSTA)|(1<<TWEN) out TWCR,temp;Посылка сигнала "START"
wait1r: in temp,TWCR;Ожидаем ответа интерфейса sbrs temp,TWINT rjmp wait1r
SLA_Wr: ldi temp,$40;Загрузка адреса слэйв2 + "WRITE" out TWDR,temp ldi temp,(1<<TWINT)|(1<<TWEN) out TWCR,temp
wait2r: in temp,TWCR;Ожидаем ответа от слэйв2 sbrs temp,TWINT rjmp wait2r
in temp,TWSR andi temp,$F8 cpi temp,$18 brne STOP_r ;Переход, если ответ от слэйв2 неверный
;Начинаем передавать данные:
DATA_r: out TWDR,Byte1 ;Отправка: 1-ый байт rcall Writer out TWDR,Byte2 ;Отправка: 2-ой байт rcall Writer rjmp STOP_r ;Передача данных завершена
;******************************************************************* Writer: ldi temp,(1<<TWINT)|(1<<TWEN) out TWCR,temp
wait3r: in temp,TWCR;Ожидаем ответа от слэйв2 sbrs temp,TWINT rjmp wait3r
in temp,TWSR cpi temp,$28 brne STOP_r ;Переход, если ответ от слэйв2 неверный
ret ;******************************************************************* ;Все данные переданы - STOP (линия приема/передачи переходит в высокоимпедансное состояние)
STOP_r: ldi temp,(1<<TWINT)|(1<<TWSTO)|(1<<TWEN) out TWCR,temp
PAUSE: ldi temp,$40;Пауза, чтобы модуль TWI смог завершить команду СТОП ldi r25,$00 dec temp cpse temp,r25 rjmp PAUSE
;*******************************************************************
;************************* ;Прием со слэйв2: ;*************************
ldi temp,$14;Установка скорости передачи= ? kHz out TWBR,temp ldi temp,$00 out TWSR,temp
ldi temp,(1<<TWINT)|(1<<TWSTA)|(1<<TWEN) out TWCR,temp;Посылка сигнала "START"
waitR1: in temp,TWCR;Ожидаем ответа интерфейса sbrs temp,TWINT rjmp waitR1
ldi temp,$41;Загрузка адреса слэйв2 + "READ" out TWDR,temp ldi temp,(1<<TWINT)|(1<<TWEA)|(1<<TWEN) out TWCR,temp
waitR2: in temp,TWCR;Ожидаем ответа слэйв2 sbrs temp,TWINT rjmp waitR2
in temp,TWSR cpi temp,$40 brne STOP_RD ;Переход, если ответ от слэйв2 неверный
;******* ;Прием данных:
Data: rcall TW_NT_R ;Прием: 1-ый байт in temp,TWDR sts Byte1,temp rcall TW_NT_R ;Прием: 2-ой байт in temp,TWDR sts Byte2,temp
rjmp STOP_RD ;Передача данных завершена
;******************************************************************* TW_NT_R:ldi temp,(1<<TWINT)|(1<<TWEA)|(1<<TWEN) out TWCR,temp
waitRr: in temp,TWCR ;Ожидаем ответа от слэйв2 sbrs temp,TWINT rjmp waitRr
in temp,TWSR cpi temp,$50 brne STOP_RD ;Переход, если данные от слэйв2 не получены
ret
;******************************************************************* STOP_RD:ldi temp,(1<<TWINT)|(1<<TWSTO)|(1<<TWEN) out TWCR,temp
Далее выполняется основная программа. ;******************************************************************* Проблема: дописал для мастера прием данных - мастер стал зависать. Сейчас выложу прогу слейва2.
|
|
|
|
|
Dec 25 2005, 16:53
|

Местный
  
Группа: Участник
Сообщений: 315
Регистрация: 10-10-05
Пользователь №: 9 466

|
Слэйв2: Код ;Инициализация TWI:
ldi temp,$40 ;Инициализация режима "Приемник" - адрес out TWAR,temp ldi temp,$00 out TWSR,temp ldi temp,(1<<TWEA)|(1<<TWEN)|(1<<TWIE) out TWCR,temp
sei
;***** Основной Цикл: *****
START: rjmp START
;******************************************************************* ;Режим - подчиненный-приемник/передатчик:
TWI_Obr:in temp,TWSR cpi temp,$60;Проверка принятого адреса от мастера breq Address cpi temp,$80;Прием данных breq DataR cpi temp,$A8;Передача данных breq DataT
ldi temp,(1<<TWINT)|(1<<TWEA)|(1<<TWEN)|(1<<TWIE) out TWCR,temp reti
;******* Address:ldi temp,(1<<TWINT)|(1<<TWEA)|(1<<TWEN)|(1<<TWIE) out TWCR,temp reti
;Прием данных:
DataR: in Byte1,TWDR ;Прием: 1-ый байт rcall TW_NT_n in Byte2,TWDR ;Прием: 2-ой байт
rjmp STOP_n
;******************************************************************* TW_NT_n:ldi temp,(1<<TWINT)|(1<<TWEA)|(1<<TWEN) out TWCR,temp
wait2n: in temp,TWCR ;Ожидаем ответа от мастера sbrs temp,TWINT rjmp wait2n
in temp,TWSR cpi temp,$80 brne STOP_n ;Переход, если данные от мастера не получены
ret
;******************************************************************* ;Все данные приняты - STOP (линия приема/передачи переходит в высокоимпедансное состояние)
STOP_n: ldi temp,(1<<TWINT)|(1<<TWEA)|(1<<TWEN)|(1<<TWIE) out TWCR,temp
reti
;*******************************************************************
;Передача данных:
DataT: out TWDR,Byte1 ;Отправка: 1-ый байт rcall Write out TWDR,Byte2 ;Отправка: 2-ой байт rcall Write rjmp STOP_n ;Передача данных завершена ;******************************************************************* Write: ldi temp,(1<<TWINT)|(1<<TWEA)|(1<<TWEN) out TWCR,temp
wait3n: in temp,TWCR ;Ожидаем ответа от мастера sbrs temp,TWINT rjmp wait3n
in temp,TWSR cpi temp,$B8 brne STOP_n ;Переход, если ответ от мастера неверный
ret
;******************************************************************* P.S. Слэйв не зависает.
|
|
|
|
|
Dec 25 2005, 18:22
|
Знающий
   
Группа: Свой
Сообщений: 543
Регистрация: 22-10-05
Пользователь №: 9 984

|
Блин Вроде все верно, единственно нужно попробовать увеличить паузу она у меня на 400кГц а здесь приблизительно 60кГц. И еще,попробуйте этот участок по прерыванию сделась все таки
Write: ldi temp,(1<<TWINT)|(1<<TWEA)|(1<<TWEN) out TWCR,temp
wait3n: in temp,TWCR ;Ожидаем ответа от мастера sbrs temp,TWINT rjmp wait3n
in temp,TWSR cpi temp,$B8 brne STOP_n ;Переход, если ответ от мастера неверный
ret
|
|
|
|
|
Dec 25 2005, 19:12
|

Местный
  
Группа: Участник
Сообщений: 315
Регистрация: 10-10-05
Пользователь №: 9 466

|
Скорость приема/передачи = 71429 Hz Паузу увеличил в 4 раза ($FF). Но мастер зависает все равно. Сделал для простоты так: мастер передает на слэйв2 один байт и один байт принимает. Связь со слэйв1 оставил, как и было - там мастер только передает около 10 байт. Я пока не совсем четко понимаю, мастер, после приема последнего байта, должен выдавать NACK? Какие еще коды TWSR надо обрабатывать? Слэйв переписал: Код ;******************************************************************* ;Режим - подчиненный-приемник/передатчик:
TWI_Obr:in temp,TWSR cpi temp,$60;Проверка принятого адреса от мастера breq Address cpi temp,$80;Прием данных breq DataR cpi temp,$A8;Передача данных breq DataT
ldi temp,(1<<TWINT)|(1<<TWEA)|(1<<TWEN)|(1<<TWIE) out TWCR,temp reti
;******* Address:ldi temp,(1<<TWINT)|(1<<TWEA)|(1<<TWEN)|(1<<TWIE) out TWCR,temp reti
;Прием данных:
DataR: in Byte,TWDR ;Прием
rjmp STOP_n
;******************************************************************* TW_NT_n:
;******************************************************************* ;Все данные приняты - STOP (линия приема/передачи переходит в высокоимпедансное состояние)
STOP_n: ldi temp,(1<<TWINT)|(1<<TWEA)|(1<<TWEN)|(1<<TWIE) out TWCR,temp
reti
;*******************************************************************
;Передача данных:
DataT: out TWDR,Byte ;Отправка
ldi temp,(1<<TWINT)|(1<<TWEA)|(1<<TWEN)|(1<<TWIE) out TWCR,temp reti
|
|
|
|
|
Dec 25 2005, 22:26
|
Знающий
   
Группа: Свой
Сообщений: 543
Регистрация: 22-10-05
Пользователь №: 9 984

|
Цитата(James D. @ Dec 25 2005, 23:22)  Не понял... У меня мастер из паузы не выходит:
PAUSE: ldi temp,$FF ;Пауза, чтобы модуль TWI смог завершить команду СТОП ldi r17,$00 dec temp cpse temp,r17 rjmp PAUSE
Что за дела? Ну так мы же с Вами великие программеры. PAUSE: ldi temp,$FF ;Пауза, чтобы модуль TWI смог завершить команду СТОП P: ldi r17,$00 dec temp cpse temp,r17 rjmp P
|
|
|
|
|
Dec 26 2005, 10:57
|

Местный
  
Группа: Участник
Сообщений: 315
Регистрация: 10-10-05
Пользователь №: 9 466

|
Так правильно? Не совсем понял, как надо обработать состояние $F8? Код ;******************************************************************* ;Режим - подчиненный-приемник/передатчик:
TWI_Obr:in temp,TWSR cpi temp,$60;Проверка принятого адреса от мастера breq Address cpi temp,$80;Прием данных breq DataR cpi temp,$A8;Передача данных breq DataT cpi temp,$00; breq Sob_00 cpi temp,$F8; breq Sob_F8
ldi temp,(1<<TWINT)|(1<<TWEA)|(1<<TWEN)|(1<<TWIE) out TWCR,temp reti
Sob_00: ldi temp,(1<<TWINT)|(1<<TWEA)|(1<<TWSTO)|(1<<TWEN)|(1<<TWIE) out TWCR,temp reti
Sob_F8: ldi temp,(1<<TWINT)|(1<<TWEA)|(1<<TWSTO)|(1<<TWEN)|(1<<TWIE) out TWCR,temp reti При таком раскладе все равно зависает мастер.
Сообщение отредактировал James D. - Dec 26 2005, 11:00
|
|
|
|
|
  |
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|