Работа TWI по двум датчикам LM75

Обсуждаем контроллеры компании Atmel.
Satyr7
Родился
Сообщения: 15
Зарегистрирован: Вс янв 18, 2026 16:17:44

Работа TWI по двум датчикам LM75

Сообщение Satyr7 »

Здравствуйте! В программировании ботаник, пробую поизучать работу шины I2C. Прописал на ассемблере работу автомата по прерываниям для atmega16 и датчика lm75ad. Всё скомпилировалось и работает в протеусе. И всё бы ничего, но добавил второй lm75 и упëрся как баран. Не пойму как их опросить обоих. Шпаргалки в даташите для опроса одного. Можно пожалуйста попросить пример опроса двух слейвов, хотябы понять как это делается. В обработчике после считывания первого делать рестарт по второму, или выходить из обработчика и инициировать работу автомата по второму? Вообще не понимаю ни первого ни второго. Все попытки ничего не дают. Спасибо если кто-то подскажет.
metan
Вымогатель припоя
Сообщения: 593
Зарегистрирован: Ср янв 06, 2010 10:01:46

Re: Работа TWI по двум датчикам LM75

Сообщение metan »

Все устройства на шине и2ц должны иметь уникальный адрес (надеюсь, это обеспечено). Работа программы с одним устройством в принципе не должна отличаться от работы с другим устройством ничем, кроме выбора адреса устройства. Иными словами, можно просто вызывать одну и ту же функцию опроса, передавая ей разные адреса слейвов.
Satyr7
Родился
Сообщения: 15
Зарегистрирован: Вс янв 18, 2026 16:17:44

Re: Работа TWI по двум датчикам LM75

Сообщение Satyr7 »

Именно это и не понимаю как выполнить. Пытался перед стопом в обработчике сделать рестарт с другим адресом слейва , и пробовал вообще выходить из прерывания и делать по счëтчику входов некое подобие мультиплексора. Ни то ни другое не выходит. Понимаю что делаю что-то неправильно. Шпаргалки нигде не нахожу на ассемблере, хотя вопрос как бы действительно не сложный.
Аватара пользователя
Starichok51
Модератор
Сообщения: 19039
Зарегистрирован: Сб авг 14, 2010 15:05:51
Откуда: г. Озерск, Челябинская обл.

Re: Работа TWI по двум датчикам LM75

Сообщение Starichok51 »

Satyr7, как у тебя в программе записаны адреса датчиков?
адрес должен выглядеть так: 1001-А2-А1-А0-Х
Х - это бит для обозначения записи (0) или чтения (1).
если ты точно задал датчикам разные адреса, то работать должно без проблем с каждым адресом.
Мудрость приходит вместе с импотенцией...
Когда на русском форуме переходят на Вы, в реальной жизни начинают бить морду.
Satyr7
Родился
Сообщения: 15
Зарегистрирован: Вс янв 18, 2026 16:17:44

Re: Работа TWI по двум датчикам LM75

Сообщение Satyr7 »

Вот код опроса единичного датчика. Адрес в SLAR именно так и прописывается. Я упёрся на этапе инициализации второго датчика. Где и как это сделать, все мои выверты ни к чему не приводят. Через рестарт в обработчике - нет. Через старт и адресацию из основного цикла - тоже. Как же это сделать правильно?


.include "m16def.inc"
.def temp = r16
.def razr1 = r17
.def razr2 = r18
.def razr3 = r19

.equ FREQ = 8000000
.equ FreqSCL = 400000
.equ FreqTWBR = ((FREQ/FreqSCL)-16)/2

.dseg
Term:
.byte 5

.cseg
.org 0
jmp Reset
.org $022
jmp TWSI

Reset:
ldi temp, high(RAMEND)
out sph, temp
ldi temp, low(RAMEND)
out spl, temp
ldi temp,FreqTWBR
out TWBR,temp

Prog:
sei
rcall Start
rcall Delay
rjmp Prog

TWSI:
cli
rcall Prov_twsr
cpi temp,0x08
breq SLAW_Adr
cpi temp,0x18
breq Pointer
cpi temp,0x28
breq Start
cpi temp,0x10
breq SLAR_Adr
cpi temp,0x40
breq Read_byte1
cpi temp,0x50
breq Read_byte2
cpi temp,0x58
breq TWI_Stop
Vix:
sei
reti

Prov_twsr:
in temp,TWSR
andi temp,0xF8
ret

Start:
ldi temp,0b10100101
out TWCR,temp
ret

TWI_Stop:
ldi r16, 0b00010100
out TWCR, temp
ret

SLAW_Adr:
ldi temp,0b10010000
out TWDR,temp
ldi temp,0b10000101
out TWCR,temp
rjmp Vix

SLAR_Adr:
ldi temp,0b10010001
out TWDR,temp
ldi temp,0b10000101
out TWCR,temp
rjmp Vix

Pointer:
ldi temp,0b00000000
out TWDR,temp
ldi temp,0b10000101
out TWCR,temp
rjmp Vix

Read_byte1:
ldi zh,high(term)
ldi zl,low(term)
in temp,TWDR
st z,temp
rcall TWI_ReciveAck
rjmp Vix

Read_byte2:
ldi zh,high(term+2)
ldi zl,low(term+2)
in temp,TWDR
st z,temp
rcall TWI_ReciveNack
rjmp Vix

TWI_ReciveAck:
ldi r16, 0b11000101
out TWCR, r16
ret

TWI_ReciveNack:
ldi r16, 0b10000101
out TWCR, r16
ret

Error:
ldi zh,high(term+5)
ldi zl,low(term+5)
ldi temp,0xff
st z,temp
rjmp Vix

Delay:
ldi razr1, 255
ldi razr2, 255
ldi razr3, 20
PDelay:
dec razr1
brne PDelay
dec razr2
brne PDelay
dec razr3
brne PDelay
ret
Последний раз редактировалось Satyr7 Пн янв 19, 2026 15:47:23, всего редактировалось 1 раз.
akl
Друг Кота
Сообщения: 4443
Зарегистрирован: Пт мар 07, 2008 06:54:43
Откуда: Ижевск

Re: Работа TWI по двум датчикам LM75

Сообщение akl »

[uquote="Satyr7",url="/forum/viewtopic.php?p=4781136#p4781136"]... Пытался перед стопом в обработчике сделать рестарт с другим адресом слейва , и пробовал вообще выходить из прерывания и делать по счëтчику входов некое подобие мультиплексора. Ни то ни другое не выходит. Понимаю что делаю что-то неправильно...[/uquote] Может приведете код инициализации, если не секрет. Чтобы увидеть уставку частоты SCL, например.
metan
Вымогатель припоя
Сообщения: 593
Зарегистрирован: Ср янв 06, 2010 10:01:46

Re: Работа TWI по двум датчикам LM75

Сообщение metan »

akl писал(а):приведете код инициализации
да уж и схему бы заодно, а то кофейная гуща почти закончилась :)
Satyr7
Родился
Сообщения: 15
Зарегистрирован: Вс янв 18, 2026 16:17:44

Re: Работа TWI по двум датчикам LM75

Сообщение Satyr7 »

Схема в протеус - контроллер и датчик, и подтяжка типовая. Код выше добавил. Изначально сделал библиотеку для дисплея 44760 на I2C и датчика и понял что поженить эти две библиотеки не могу. Стал пробовать на двух датчиках без дисплея. Подскажите пожалуйста хотябы принцип. Если правильно понял - TWI умеет делать опрос нескольких устройств, но мне непонятен способ обращения к нескольким слейвам.
Аватара пользователя
Starichok51
Модератор
Сообщения: 19039
Зарегистрирован: Сб авг 14, 2010 15:05:51
Откуда: г. Озерск, Челябинская обл.

Re: Работа TWI по двум датчикам LM75

Сообщение Starichok51 »

Satyr7 писал(а):но мне непонятен способ обращения к нескольким слейвам.
что тут не понятно?
обращаешься к каждому устройству по его адресу.
ты в своем коде показал один адрес датчика (0b10010000).
а какой адрес ты установил у второго датчика?
а может, ты и у первого датчика адресные входы никуда не подключал?
Мудрость приходит вместе с импотенцией...
Когда на русском форуме переходят на Вы, в реальной жизни начинают бить морду.
Satyr7
Родился
Сообщения: 15
Зарегистрирован: Вс янв 18, 2026 16:17:44

Re: Работа TWI по двум датчикам LM75

Сообщение Satyr7 »

Вопрос не в адресе, он задаëтся любым. Мне непонятно как после опроса первого датчика сделать опрос второго. Например: Опрос первого - старт в основном цикле, далее в обработчике прерываний slaw, данные, рестарт, slar, запись температуры, стоп. А что дальше? Как со вторым? Или не делать стоп и в обработчике снова сделать рестарт и slaw второго? Или вообще по-другому? Например делать в основном цикле старт и там же slaw первого? Мне здесь всё непонятно.
veso74
Поставщик валерьянки для Кота
Сообщения: 1902
Зарегистрирован: Сб май 05, 2012 20:24:52
Откуда: KN34PC, Болгария
Контактная информация:

Re: Работа TWI по двум датчикам LM75

Сообщение veso74 »

Slave устройства I2C отвечают, когда их выбирают по адресу (и не отвечают на запросы по другим адресам). I2C - по двум проводам напр. 128 устройств (с исключениями). Вызываете первый датчик по его адресу, считываете температуру, вызываете второй датчик по адресу (другому), считываете температуру... С помощью выводов программного адреса количество датчиков может достигать 8.
Satyr7
Родился
Сообщения: 15
Зарегистрирован: Вс янв 18, 2026 16:17:44

Re: Работа TWI по двум датчикам LM75

Сообщение Satyr7 »

Я это понимаю, не понимаю какова процедура на практике. Инициация TWI производится стартом, далее в обработчике производится адресация - это я так сделал, но понимаю, что сделал неправильно, хотя код и работает по одному датчику.
Аватара пользователя
Starichok51
Модератор
Сообщения: 19039
Зарегистрирован: Сб авг 14, 2010 15:05:51
Откуда: г. Озерск, Челябинская обл.

Re: Работа TWI по двум датчикам LM75

Сообщение Starichok51 »

вообще не нужно создавать прерывание по TWI - всё прекрасно делается в основном цикле.
сначала делаешь все процедуры по первому датчику, потом - по второму.
я не знаю, какую запись можно или нужно делать в эти датчики.
а чтение делается так:
1. старт.
2. адрес с битом чтения.
3. чтение байтов температуры.
4. стоп.
делаешь эти 4 пункта для первого датчика, потом делаешь эти 4 пункта для второго датчика.
Мудрость приходит вместе с импотенцией...
Когда на русском форуме переходят на Вы, в реальной жизни начинают бить морду.
Satyr7
Родился
Сообщения: 15
Зарегистрирован: Вс янв 18, 2026 16:17:44

Re: Работа TWI по двум датчикам LM75

Сообщение Satyr7 »

Спасибо большое. Понял. Т. е. - делается всё не на прерываниях по кодам статусного регистра, а упрощëнно без проверок. И просто в основном цикле: старт адресация первого... стоп. Далее старт, адресация второго... стоп. Если правильно понял - в обработчике TWSI, как прописано выше в коде, вообще невозможно адресовать больше одного устройства. Просто я предполагал, что можно как-то задать выбор адресов. К примеру: счëтчик 0 - slaw первый, счётчик 1 - slaw второй, ит. д. Но лично у меня этого не получилось.
Аватара пользователя
Starichok51
Модератор
Сообщения: 19039
Зарегистрирован: Сб авг 14, 2010 15:05:51
Откуда: г. Озерск, Челябинская обл.

Re: Работа TWI по двум датчикам LM75

Сообщение Starichok51 »

Satyr7 писал(а):сли правильно понял - в обработчике TWSI, как прописано выше в коде, вообще невозможно адресовать больше одного устройства. Просто я предполагал, что можно как-то задать выбор адресов. К примеру: счётчик 0 - slaw первый, счётчик 1 - slaw второй, ит. д.
почему же невозможно в обработчике? по счетчику можно и в обработчике.
но как я уже сказал, обработчик на фиг не нужен.
Satyr7 писал(а):И просто в основном цикле: старт адресация первого... стоп. Далее старт, адресация второго... стоп.
вот именно! без всякого обработчика по очереди всё прекрасно делается в основном цикле.
можно и в обработчике по счетчику, но с обработчиком - бессмысленное усложнение программы.
Мудрость приходит вместе с импотенцией...
Когда на русском форуме переходят на Вы, в реальной жизни начинают бить морду.
Satyr7
Родился
Сообщения: 15
Зарегистрирован: Вс янв 18, 2026 16:17:44

Re: Работа TWI по двум датчикам LM75

Сообщение Satyr7 »

Попробовал по счётчику, только напрасно вспотел, вероятно нужно хорошо понимать все тайминги. Прописал процедуру опроса как вы сказали, нормально скомпилировалось, но пока значения температуры не возвращается, читается только 1-й байт. Всё равно где-то накосячил.



.include "m16def.inc"
.list
.def temp = r16
.def razr1 = r17
.def razr2 = r18
.def razr3 = r19
.equ FREQ = 8000000 // Частота работы чипа 8 Мгц
.equ FreqSCL = 100000 // Максимальная частота работы I2C 400 КГц
.equ FreqTWBR = ((FREQ/FreqSCL)-16)/2 // В формуле учитывается Регистр TWPS == 0

.dseg
Term:
.byte 5

.cseg
.org 0x00
jmp inicio ; PC = 0x0000 RESET

inicio:
LDI R21, HIGH(RAMEND) ;Стек
OUT SPH, R21
LDI R21, LOW(RAMEND)
OUT SPL, R21

HERE:
rcall delay
CALL I2C_INIT ;Включение TWI
CALL I2C_START ;Отправка Старт
LDI R27, 0b10010000 ;SLA(0b1001000) + W(0)
CALL I2C_WRITE ;Отправка SLAW
LDI R27, 0b00000000 ;Задание значения Pointer
CALL I2C_WRITE ;Отправка Pointer
CALL I2C_START ;Рестарт
LDI R27, 0b10010001 ;SLA(0b1001000) + R(0)
CALL I2C_WRITE ;Отправка SLAR
CALL Read_byte1 ;Запись первого байта
nop
nop
CALL Read_byte2 ;Запись второго байта (температуры)
CALL I2C_STOP ;Стоп

RJMP HERE

;----------------------------I2C_INIT-----------------------------
I2C_INIT:
LDI R21, 0
OUT TWSR, R21
LDI R21, (1<<TWEN)
OUT TWCR, R21
RET

;----------------------------I2C_START-----------------------------
I2C_START:
LDI R21, (1<<TWINT)|1<<(TWSTA)|(1<<TWEN)
OUT TWCR, R21
WAIT1:
IN R21, TWCR
SBRS R21, TWINT
RJMP WAIT1
RET

;----------------------------I2C_WRITE -----------------------------
I2C_WRITE:
OUT TWDR, R27
LDI R21, (1<<TWINT)|(1<<TWEN)
OUT TWCR, R21
WAIT3:
IN R21, TWCR
SBRS R21, TWINT
RJMP WAIT3
RET

;----------------------------I2C_STOP------------------------------
I2C_STOP:
LDI R21, (1<<TWINT)|1<<(TWSTO)|(1<<TWEN)
OUT TWCR, R21
RET

Read_byte1:
ldi zh,high(term)
ldi zl,low(term)
in temp,TWDR
st z,temp
rcall TWI_ReciveAck
ret

TWI_ReciveAck:
ldi r16, 0b11000100
out TWCR, r16
ret

Read_byte2:
ldi zh,high(term+2)
ldi zl,low(term+2)
in temp,TWDR
st z,temp
rcall TWI_ReciveNack
ret

TWI_ReciveNack:
ldi r16, 0b10000100
out TWCR, r16
ret

Delay: //
ldi razr1, 255
ldi razr2, 255
ldi razr3, 20
PDelay:
dec razr1
brne PDelay
dec razr2
brne PDelay
dec razr3
brne PDelay
ret

Добавлено after 43 minutes 3 seconds:
Большое спасибо за урок, сделал больше задержку между Read_byte1 и Read_byte2 и нормализовалось, возвращаются оба значения.
Аватара пользователя
Starichok51
Модератор
Сообщения: 19039
Зарегистрирован: Сб авг 14, 2010 15:05:51
Откуда: г. Озерск, Челябинская обл.

Re: Работа TWI по двум датчикам LM75

Сообщение Starichok51 »

CALL Read_byte1 ;Запись первого байта
ты делаешь чтение, а в комментарии запись.

вообще не нужна отдельная подпрограмма I2C_INIT. бит TWEN записывается при каждом обращении.

не нужно делать отдельную задержку между чтениями, нужно делать также ожидание окончания операции.
и ожидание окончания лучше сделать подпрограммой, чтобы не повторять "тело" ожидания.
WAIT:
IN R21, TWCR
SBRS R21, TWINT
RJMP WAIT
RET
и будет просто CALL WAIT.
и кстати, в короткой программе следует применять команду относительного вызова RCALL.

Добавлено after 7 hours 6 minutes 51 second:
чтение байтов температуры у тебя сделано не правильно.
нужно сначала запросить передачу байта
rcall TWI_ReciveAck
а уж потом прочитать байт из регистра данных TWDR.

вот мои подпрограммы из моих проектов:

;--- отправка старта по I2C ---
set_start_I2C:
ldi R26, (1<<TWINT)|(1<<TWSTA)|(1<<TWEN)
out TWCR, R26
rcall wait_int_I2C
ret

;--- отправка данных по I2C ---
set_data_I2C:
out TWDR, R27
ldi R26, (1<<TWINT)|(1<<TWEN)
out TWCR, R26
rcall wait_int_I2C
ret

;--- прием данных по I2C ---
in_data_I2C:
ldi R26, (1<<TWINT)|(1<<TWEA)|(1<<TWEN)
out TWCR, R26
rcall wait_int_I2C
in R27, TWDR
ret

;--- ожидание окончания операции по I2C ---
wait_int_I2C:
in R26, TWCR
sbrs R26, TWINT
rjmp wait_int_I2C
in R26, TWSR
ret

я не заморачиваюсь для последнего принятого байта не передавать ответ (Nack). я делаю все чтения всегда с ответом.
и я не передаю стоп. просто последующие старты будут повторными. но ты можешь работать со стопом - на твоё усмотрение.

в подпрограмме ожидания я читаю статус
in R26, TWSR
чтобы проверить успешность операции.

если всегда чтение делать с ответом, то тогда у тебя должно получиться так:

:чтение двух байтов температуры
ldi zh,high(term)
ldi zl,low(term)
CALL Read_byte ; прочитали первый байт
st z+,temp ; сохранили первый байт
CALL Read_byte ; прочитали второй байт
st z+,temp ; сохранили второй байт

Read_byte:
ldi R16, (1<<TWINT)|(1<<TWEA)|(1<<TWEN)
out TWCR, R16
rcall wait
in temp, TWDR
ret

wait:
in R26, TWCR
sbrs R26, TWINT
rjmp wait
ret

как видишь, выглядит намного компактнее, чем твой избыточный код.
но если очень тебе хочется, можешь также две подпрограммы чтения сделать с передачей ответа (Ack) и без передачи ответа, как у тебя сейчас сделано.

и твоей подпрограммы большой задержки не нужно вообще.
Мудрость приходит вместе с импотенцией...
Когда на русском форуме переходят на Вы, в реальной жизни начинают бить морду.
Satyr7
Родился
Сообщения: 15
Зарегистрирован: Вс янв 18, 2026 16:17:44

Re: Работа TWI по двум датчикам LM75

Сообщение Satyr7 »

Спасибо большое. Я изначально всë сделал культурно, просто пока пыхтел с прерываниями снова понаделал всякой мешанины, предполагая, что если часть кода сделать в общей куче, то это должно как-то положительно отразиться. Все замечания исправлю. Способ выбора адресации слейвов в TWI пока отложил, т. к. моих познаний пока не хватает. Обрадовался, что получилось всё в цикле. Справлюсь с выводом на дисплей и вернусь к вопросу. Если я вам ещё не надоел, позже выложу свою стряпню. Спасибо.
Аватара пользователя
Starichok51
Модератор
Сообщения: 19039
Зарегистрирован: Сб авг 14, 2010 15:05:51
Откуда: г. Озерск, Челябинская обл.

Re: Работа TWI по двум датчикам LM75

Сообщение Starichok51 »

Satyr7 писал(а):Способ выбора адресации слейвов в TWI пока отложил, т. к. моих познаний пока не хватает.
тебе уже насколько раз сказали, что с адресацией проблем нет.
ты первому датчику задал "нулевой" адрес (000). второму датчику адресные входы подключи, например, 001. и обращайся по адресу 0b1001001 + бит записи или чтения.
Satyr7 писал(а):Если я вам ещё не надоел
не надоел.
вменяемым людям помогать даже приятно.
но, к сожалению, попадаются невменяемые...
Мудрость приходит вместе с импотенцией...
Когда на русском форуме переходят на Вы, в реальной жизни начинают бить морду.
Satyr7
Родился
Сообщения: 15
Зарегистрирован: Вс янв 18, 2026 16:17:44

Re: Работа TWI по двум датчикам LM75

Сообщение Satyr7 »

Невменяемые это такие бивни как я, потому-что именно так всё и делал. Я прекрасно знаю как притяжками задавать физический адрес. Здесь просто смешались понятия, задания адреса на ногах, и адресации слейва в обработчике. Сидит, например, какой-нибудь придурковатый нуб, читает даташит и чешет тупую репу, и думает что ему делать дальше. Дальше начинает методом насильного впихивания лепить в обработчике всякие рестарты, надеясь что этот TWI каким-то чудом заработает. А в итоге, делать ему остаëтся только одно - идти в ближайшую поликлинику и просить таблетку от критинизма.
Ответить

Вернуться в «AVR»