Перейти к содержанию
    

а чем ,простите, шит не устраивает . имхо все доходчиво

Ну, например, на русский его перевести. B)

Хотя, ести перечитать всю эту тему, то это уже сделано.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

а чем ,простите, шит не устраивает . имхо все доходчиво

Ну, например, на русский его перевести. B)

Хотя, ести перечитать всю эту тему, то это уже сделано.

 

Уважаемый Games D.! Вы задаёте вопросы на которые ЕСТЬ однозначные ответы в datahsheet на AVR (если быть точнее в разделе "Two-wire Serial Interface"), поэтому у меня есть конструктивное предложение: задавайте вопросы в таком виде "в пункте таком-то даташита написано что надо делать так-то, что бы получить то-то а у меня выходит сяк-то.". просто практика показывает что если делать, как рекомендуется в datasheet, то всё работает с первого раза и с минимальными временами на отладку.

 

для общего ознакомления с I2C можно прочитать это (на русском).

i2c.pdf

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Я делаю так - передача одного байта (без обработки ошибок), пусть меня поправят, если я не прав:

 

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. После этого слэйв выходит из программы приема данных - продолжает выполняться основная программа.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Я делаю так - передача одного байта (без обработки ошибок), пусть меня поправят, если я не прав:

 

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" значит флаг имеет ИНВЕРСНУЮ логику!

исправляйте ошибку, будем дальше дебажить =)

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Так, заменил на ожидание "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.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Кстати, в даташите (в приведенном там примере) стоит ожидание "1" - после посылки START.

 

P.S. Прочитал PDF'ку, и сразу возник вопрос: надо ли в процессе работы TWI как-то коммутировать порты (PC0, PC1). У меня они настроены на ввод с вкл. подтягивающими резисторами.

Изменено пользователем James D.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Кстати, в даташите (в приведенном там примере) стоит ожидание "1" - после посылки START.

 

Какой вы упёртый =)

 

цитата из даташита:

 

"while (!(TWCR & (1<<TWINT))); // Wait for TWINT flag set. This indicates that the START condition has been transmitted"

Изменено пользователем Petka

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Я делаю так - передача одного байта (без обработки ошибок), пусть меня поправят, если я не прав:

 

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).

Далее требуется коррекция Вашего алгоритма.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Это значит, что первое прерывание у слейва возникает только если его адрес совпал или было обращение по широковещательному адресу (событие 0x70) или их ошибочные варианты (0x68, 0x78).

Далее требуется коррекция Вашего алгоритма.

 

Но ведь слэйв проверяет содержимое TWSR на соответствие $60 как раз в обработчике прерывания, значит само прерывание возникает до того.

У меня обработчик слэйва начинается так:

 

;*******************************************************************
;Режим - подчиненный-приемник:

TWI_Obr:in  temp,TWSR
  andi temp,$F8
  cpi  temp,$60 ;Проверка принятого адреса
  breq Pr_data  ;Переход на прием данных
  reti

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

;*******************************************************************
;Режим - подчиненный-приемник:

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, чтобы иметь возможность воспринимать другие события.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Добавлю также, что надо анализировать ВСЕ события и делать все действия. Ничего не сокращая! Оптимизировать будете когда всё заработает.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

То 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)

 

Все!!!

 

Сложно?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Немного не по теме. Кто-нибудь встречал русскоязычное описание USI для "тинек", для того же двухпроводного интерфейса?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Сделал следующее.

Убрал из программ мастера и слэйва передачу данных при включении обоих МК - там было не по прерываниям, а в основной программе.

Далее. Слэйв:

 

;Инициализация 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 оставил, для чистоты эксперимента, только два МК - мастер и слэйв.

И еще: скорость передачи устанавливается только в мастере, или в слэйве тоже?

Изменено пользователем James D.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...