реклама на сайте
подробности

 
 
> Проблема с TWI
James D.
сообщение Nov 4 2005, 17:14
Сообщение #1


Местный
***

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



Соединил 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 приемник" на вызов не реагировал?
Go to the top of the page
 
+Quote Post
19 страниц V  « < 9 10 11 12 13 > »   
Start new topic
Ответов (150 - 164)
bodja74
сообщение Dec 25 2005, 10:57
Сообщение #151


Знающий
****

Группа: Свой
Сообщений: 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
Go to the top of the page
 
+Quote Post
James D.
сообщение Dec 25 2005, 12:15
Сообщение #152


Местный
***

Группа: Участник
Сообщений: 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?
Go to the top of the page
 
+Quote Post
James D.
сообщение Dec 25 2005, 13:29
Сообщение #153


Местный
***

Группа: Участник
Сообщений: 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...

Вобщем тут я пока без четкого алгоритма...
Go to the top of the page
 
+Quote Post
bodja74
сообщение Dec 25 2005, 14:23
Сообщение #154


Знающий
****

Группа: Свой
Сообщений: 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 а илвлекаем.
Go to the top of the page
 
+Quote Post
James D.
сообщение Dec 25 2005, 16:42
Сообщение #155


Местный
***

Группа: Участник
Сообщений: 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.
Go to the top of the page
 
+Quote Post
James D.
сообщение Dec 25 2005, 16:53
Сообщение #156


Местный
***

Группа: Участник
Сообщений: 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. Слэйв не зависает.
Go to the top of the page
 
+Quote Post
bodja74
сообщение Dec 25 2005, 17:02
Сообщение #157


Знающий
****

Группа: Свой
Сообщений: 543
Регистрация: 22-10-05
Пользователь №: 9 984



По мастеру похоже все верно.
Go to the top of the page
 
+Quote Post
bodja74
сообщение Dec 25 2005, 18:22
Сообщение #158


Знающий
****

Группа: Свой
Сообщений: 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
Go to the top of the page
 
+Quote Post
James D.
сообщение Dec 25 2005, 19:12
Сообщение #159


Местный
***

Группа: Участник
Сообщений: 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
Go to the top of the page
 
+Quote Post
James D.
сообщение Dec 25 2005, 20:22
Сообщение #160


Местный
***

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



Не понял... У меня мастер из паузы не выходит:

PAUSE: ldi temp,$FF ;Пауза, чтобы модуль TWI смог завершить команду СТОП
ldi r17,$00
dec temp
cpse temp,r17
rjmp PAUSE

Что за дела?
Go to the top of the page
 
+Quote Post
bodja74
сообщение Dec 25 2005, 22:26
Сообщение #161


Знающий
****

Группа: Свой
Сообщений: 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
Go to the top of the page
 
+Quote Post
James D.
сообщение Dec 26 2005, 05:49
Сообщение #162


Местный
***

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



Да ну ё-моё!!! Вот это лажа!!! :-)
Go to the top of the page
 
+Quote Post
James D.
сообщение Dec 26 2005, 06:16
Сообщение #163


Местный
***

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



Зависает в мастере здесь:

waitR1: in temp,TWCR ;Ожидаем ответа интерфейса
sbrs temp,TWINT
rjmp waitR1

Twint в "1" не устанавливается.
Go to the top of the page
 
+Quote Post
Petka
сообщение Dec 26 2005, 08:36
Сообщение #164


Профессионал
*****

Группа: Свой
Сообщений: 1 453
Регистрация: 23-08-05
Пользователь №: 7 886



Добавьте в код слэйва в обработчик прерываний обработку слудующих событий:
case 0x00:
TWCR=0b11010101;
case 0xF8: // No relevant state information available; TWINT = "0"
Go to the top of the page
 
+Quote Post
James D.
сообщение Dec 26 2005, 10:57
Сообщение #165


Местный
***

Группа: Участник
Сообщений: 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
Go to the top of the page
 
+Quote Post

19 страниц V  « < 9 10 11 12 13 > » 
Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 28th July 2025 - 22:46
Рейтинг@Mail.ru


Страница сгенерированна за 0.0154 секунд с 7
ELECTRONIX ©2004-2016