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

|
ВСЕ!!! Добил. Думаю разберетесь. Код мастера Код ; TWI Master ; Specify Device. .include "m8def.inc"
; Variable Declarations .def temp = r16 .def temp_a = r17 .def adress = r18 .def data = r19 .def W = r24 .def X = r26 .def Y = r28 .def Z = r30
.cseg ; CODE segment.
.org 0; origin.
PROG: ldi temp,$04 ; Initialize the stack. out SPH,temp ldi temp,$5F out SPL,temp ldi temp,$00 out TWBR,temp ldi temp,$00 out TWSR,temp
ldi temp,$FF out DDRD,temp
ldi adress,$41;Получаем rcall TWI_START rcall TWI_DATA_R_ACK rcall TWI_DATA_R_NACK;При при получении последнего байта нужно rcall TWI_STOP ;обязательно указывать NACK rcall PAUSE
ldi adress,$40 ;Отправляем rcall TWI_START ldi data,$FF rcall TWI_DATA rcall TWI_DATA rcall TWI_STOP rcall PAUSE
ldi adress,$40 rcall TWI_START rcall TWI_DATA rcall TWI_STOP rcall PAUSE
ldi adress,$41 rcall TWI_START rcall TWI_DATA_R_ACK rcall TWI_DATA_R_NACK rcall TWI_STOP rcall PAUSE
end: rjmp end
TWI_START: ldi temp,$A4 out TWCR,temp s1: in temp,TWCR sbrs temp,7 rjmp s1 out TWDR,adress ldi temp,$C4 out TWCR,temp s2: in temp,TWCR sbrs temp,7 rjmp s2 ret
TWI_DATA: out TWDR,data ldi temp,$C4 out TWCR,temp d1: in temp,TWCR sbrs temp,7 rjmp d1 ret
TWI_STOP: ldi temp,$94 out TWCR,temp ret
PAUSE: ldi temp,$40 ldi temp_a,$00 p: dec temp cpi temp,$00 brne p ret
TWI_DATA_R_NACK:ldi temp,$84 out TWCR,temp d2: in temp,TWCR sbrs temp,7 rjmp d2 in temp,TWDR out PORTD,temp ret TWI_DATA_R_ACK: ldi temp,$C4 out TWCR,temp d3: in temp,TWCR sbrs temp,7 rjmp d3 in temp,TWDR out PORTD,temp ret Код слейва Код ; TWI Slave ; Specify Device. .include "m8def.inc"
; Variable Declarations .def temp = r16 .def temp_a = r17 .def adress = r18 .def data = r19 .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 reti PROG: ldi r16,$04 ; Initialize the stack. out SPH,r16 ldi r16,$5F out SPL,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 out DDRD,temp sei end: rjmp end ; конец программы
TWI_Finished: sts $0F1,temp in temp,TWSR cpi temp,$60 breq t1 in temp,TWSR cpi temp,$80 breq t2 in temp,TWSR cpi temp,$A8 breq t3 in temp,TWSR cpi temp,$B0 breq t3 in temp,TWSR cpi temp,$B8 breq t4 ldi temp,$C5 out TWCR,temp reti
t1: ldi temp,$C5 ;Определяем Адресс.Мастер передает out TWCR,temp reti
t2: in temp,TWDR ;Получаем данные out PORTD,temp ldi temp,$C5 out TWCR,temp reti
t3: ldi temp,$01 ;Определяем Адресс.Мастер получает 1 байт out TWDR,temp ldi temp,$C5 out TWCR,temp ldi temp,$01 out TWDR,temp reti
t4: ldi temp,$02 ;Мастер получает 2 байт и далее out TWDR,temp ldi temp,$85 ;$85 последний байт, $C5 далее out TWCR,temp reti Пробуйте.
|
|
|
|
|
Dec 28 2005, 14:23
|

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

|
Вроде все исправил, но мастер зависает в том же месте. Слейв2 не хочет принимать свой адрес. Вопросы: 1. Почему у вас везде TWBR=0? Значение ведь должно быть не менее 10? 2. В вашей проге мастер сначала принимает 2 байта, отправляет 2 байта, отправляет 1 байт, и, наконец принимает 2 байта. Я же сделал, чтобы мастер отправлял 2 байта, а потом принимал 6 байт (впрочем, до приема дело не доходит). Это же не принципиально важно? 3. В проге слейва, в этом месте:
t3: ldi temp,$01 ;Определяем Адресс.Мастер получает 1 байт out TWDR,temp ldi temp,(1<<TWINT)|(1<<TWEA)|(1<<TWEN)|(1<<TWIE) out TWCR,temp ldi temp,$01 out TWDR,temp reti
зачем 2 раза заносить значение в TWDR?
Ситуация у меня, наверное, осложняется присутствием на шине 2-х слейвов. В слейве1 прием данных завершается командой:
STOP: ldi temp,(1<<TWINT)|(1<<TWEN)|(1<<TWIE) out TWCR,temp reti
Слейв1 ничего не передает мастеру - только принимает. После этого идет передача/прием на слейв2.
|
|
|
|
|
Dec 28 2005, 17:25
|
Знающий
   
Группа: Свой
Сообщений: 543
Регистрация: 22-10-05
Пользователь №: 9 984

|
Вот исправленный код для мастера. Должен работать с двумя слейвами. У слейвов код тотже. Код ; TWI Master ; Specify Device. .include "m8def.inc"
; Variable Declarations .def temp = r16 .def temp_a = r17 .def adress = r18 .def data = r19 .def W = r24 .def X = r26 .def Y = r28 .def Z = r30
.cseg ; CODE segment.
.org 0; origin.
PROG: ldi temp,$04 ; Initialize the stack. out SPH,temp ldi temp,$5F out SPL,temp ldi temp,$02 out TWBR,temp ldi temp,$02 out TWSR,temp
ldi temp,$FF out DDRD,temp
ldi adress,$40 rcall TWI_START ldi data,$F0 rcall TWI_DATA rcall TWI_DATA rcall TWI_STOP rcall PAUSE
ldi adress,$20 rcall TWI_START ldi data,$0F rcall TWI_DATA rcall TWI_DATA rcall TWI_STOP rcall PAUSE
ldi adress,$41 rcall TWI_START rcall TWI_DATA_R_ACK rcall TWI_DATA_R_NACK rcall TWI_STOP rcall PAUSE
ldi adress,$21 rcall TWI_START rcall TWI_DATA_R_ACK rcall TWI_DATA_R_NACK rcall TWI_STOP rcall PAUSE
end: rjmp end
TWI_START: ldi temp,$A4 out TWCR,temp s1: in temp,TWCR sbrs temp,7 rjmp s1 out TWDR,adress ldi temp,$C4 out TWCR,temp s2: in temp,TWCR sbrs temp,7 rjmp s2 ret
TWI_DATA: out TWDR,data ldi temp,$C4 out TWCR,temp d1: in temp,TWCR sbrs temp,7 rjmp d1 ret
TWI_STOP: ldi temp,$94 out TWCR,temp ret
PAUSE: ldi temp,$40 ldi temp_a,$00 p: dec temp cpi temp,$00 brne p ret
TWI_DATA_R_NACK:ldi temp,$84 out TWCR,temp d2: in temp,TWCR sbrs temp,7 rjmp d2 in temp,TWDR out PORTD,temp ret TWI_DATA_R_ACK: ldi temp,$C4 out TWCR,temp d3: in temp,TWCR sbrs temp,7 rjmp d3 in temp,TWDR out PORTD,temp ret Пробуйте.
|
|
|
|
|
Dec 30 2005, 06:08
|

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

|
Код слейва2: Код ;Инициализация TWI:
ldi temp,$40 ;Инициализация режима "Приемник" - адрес out TWAR,temp ldi temp,$00 out TWSR,temp ldi temp,$14 out TWBR,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 DataT1 cpi temp,$B0; breq DataT1 cpi temp,$B8; breq DataT2
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_1,TWDR ;Прием: байт 1 rcall TW_NT_n in Byte_2,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
ret
;******************************************************************* ;Все данные приняты - STOP (линия приема/передачи переходит в высокоимпедансное состояние)
STOP_n: ldi temp,(1<<TWINT)|(1<<TWEA)|(1<<TWEN)|(1<<TWIE) out TWCR,temp
;*******************************************************************
;Передача данных:
DataT1: out TWDR,Byte_3 ;Отправка: байт 3 rcall Write out TWDR,Byte_4 ;Отправка: байт 4 rcall Write out TWDR,Byte_5 ;Отправка: байт 5 rcall Write out TWDR,Byte_6 ;Отправка: байт 6 rcall Write out TWDR,Byte_7 ;Отправка: байт 7 rcall Write
DataT2: out TWDR,Byte_8 ;Отправка: байт 8
ldi temp,(1<<TWINT)|(1<<TWEN)|(1<<TWIE) ;последний байт out TWCR,temp
reti ;******************************************************************* Write: ldi temp,(1<<TWINT)|(1<<TWEA)|(1<<TWEN)|(1<<TWIE) out TWCR,temp
wait3n: in temp,TWCR;Ожидаем ответа от мастера sbrs temp,TWINT rjmp wait3n
ret
;******************************************************************* Код слейва1 такой же, но там только принимаются данные.
|
|
|
|
|
Dec 30 2005, 06:21
|

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

|
Код слейва 1: Код ;Инициализация TWI:
ldi temp,$20;Инициализация режима "Приемник" 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 Data 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: reti
;******* Address:ldi temp,(1<<TWINT)|(1<<TWEA)|(1<<TWEN)|(1<<TWIE) out TWCR,temp reti
;******* ;Прием данных:
Data: in Byte_1,TWDR ;Прием: байт 1
Data2: rcall TW_NT_n ;Прием: байт 2 in Byte_2,TWDR
Data3: rcall TW_NT_n ;Прием: байт 3 in temp,TWDR sts Byte_3,temp
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
ret
;******************************************************************* ;Все данные приняты - STOP (линия приема/передачи переходит в высокоимпедансное состояние)
STOP_n: ldi temp,(1<<TWINT)|(1<<TWEA)|(1<<TWEN)|(1<<TWIE) out TWCR,temp
reti ;*******************************************************************
|
|
|
|
|
Dec 30 2005, 16:05
|

Участник

Группа: Участник
Сообщений: 65
Регистрация: 28-12-05
Из: Odessa
Пользователь №: 12 673

|
Непонимаю радости использовать аппаратный TWI. Вот отработанный мною годами код к програмной реализации аналога I2C. Может одумаетесь. Особых преимуществ невижу. А на этом коде можно увеличить несущюю CLK  . Определяете четыре константы и все. .equ DDRX = DDRX (любой порт DDRX - выбора направления) .equ PINX = PINX (любой порт PINX конечно тотже триады что и DDRX) .equ XSCL = 0-7 .equ XSDA = 0-7 ; Примечание : ; можете цеплять внешние сопротивления и на 1.5 вольта - будет работать. Работала несущая и на 1.5 mbю InstallI2C: cbi DDRX,XSCL ; установка линии SCL в 1 cbi DDRX,XSDA ; установка линии SDA в 1 ret StartI2C: rcall PausI2C cbi DDRX,XSDA ; установка в 1 rcall PausI2C cbi DDRX,XSCL ; установка в 1 rcall PausI2C sbi DDRX,XSDA ; установка в 0 rcall PausI2C sbi DDRX,XSCL ; установка в 0 rcall PausI2C ret StopI2C: sbi DDRX,XSDA sbi DDRX,XSCL rcall PausI2C cbi DDRX,XSCL rcall PausI2C cbi DDRX,XSDA rcall PausI2C ret
; Вход: R24-data и устанавливае фла переноса если ASK=1 DataOutI2C: ldi r30,8 doq1a: rol r24 brcs doq2a sbi DDRX,XSDA rjmp doq3a doq2a: cbi DDRX,XSDA doq3a: rcall I2CPulse dec r30 brne doq1a cbi DDRX,XSDA rcall PausI2C cbi DDRX,XSCL rcall PausI2C in r24,PINX sbi DDRX,XSCL rcall PausI2C clc sbrc r24,XSDA sec ret ; Выход: R24-data и устанавливае фла переноса если ASK=1 DataInI2C: push r30 ldi r30,8 diiq1: rcall PausI2C cbi DDRX,XSCL rcall PausI2C in r31,PINX sbi DDRX,XSCL clc sbrc r31,XSDA sec rol r24 dec r30 brne diiq1 rcall PausI2C sbi DDRX,XSDA ; 0 rcall PausI2C cbi DDRX,XSCL ; 1 rcall PausI2C sbi DDRX,XSCL ; 0 rcall PausI2C cbi DDRX,XSDA ; 0 rcall PausI2C pop r30 ret
I2CPulse: rcall PausI2C sbi DDRX,XSCL rcall PausI2C cbi DDRX,XSCL rcall PausI2C sbi DDRX,XSCL rcall PausI2C ret
PausI2C: push r30 ldi r30,8 doq33: dec r30 brne doq33 pop r30 ret Моя будущая веб-страница
|
|
|
|
|
  |
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|