Работа TWI по двум датчикам LM75
Работа TWI по двум датчикам LM75
Здравствуйте! В программировании ботаник, пробую поизучать работу шины I2C. Прописал на ассемблере работу автомата по прерываниям для atmega16 и датчика lm75ad. Всё скомпилировалось и работает в протеусе. И всё бы ничего, но добавил второй lm75 и упëрся как баран. Не пойму как их опросить обоих. Шпаргалки в даташите для опроса одного. Можно пожалуйста попросить пример опроса двух слейвов, хотябы понять как это делается. В обработчике после считывания первого делать рестарт по второму, или выходить из обработчика и инициировать работу автомата по второму? Вообще не понимаю ни первого ни второго. Все попытки ничего не дают. Спасибо если кто-то подскажет.
Re: Работа TWI по двум датчикам LM75
Все устройства на шине и2ц должны иметь уникальный адрес (надеюсь, это обеспечено). Работа программы с одним устройством в принципе не должна отличаться от работы с другим устройством ничем, кроме выбора адреса устройства. Иными словами, можно просто вызывать одну и ту же функцию опроса, передавая ей разные адреса слейвов.
Re: Работа TWI по двум датчикам LM75
Именно это и не понимаю как выполнить. Пытался перед стопом в обработчике сделать рестарт с другим адресом слейва , и пробовал вообще выходить из прерывания и делать по счëтчику входов некое подобие мультиплексора. Ни то ни другое не выходит. Понимаю что делаю что-то неправильно. Шпаргалки нигде не нахожу на ассемблере, хотя вопрос как бы действительно не сложный.
- Starichok51
- Модератор
- Сообщения: 19039
- Зарегистрирован: Сб авг 14, 2010 15:05:51
- Откуда: г. Озерск, Челябинская обл.
Re: Работа TWI по двум датчикам LM75
Satyr7, как у тебя в программе записаны адреса датчиков?
адрес должен выглядеть так: 1001-А2-А1-А0-Х
Х - это бит для обозначения записи (0) или чтения (1).
если ты точно задал датчикам разные адреса, то работать должно без проблем с каждым адресом.
адрес должен выглядеть так: 1001-А2-А1-А0-Х
Х - это бит для обозначения записи (0) или чтения (1).
если ты точно задал датчикам разные адреса, то работать должно без проблем с каждым адресом.
Мудрость приходит вместе с импотенцией...
Когда на русском форуме переходят на Вы, в реальной жизни начинают бить морду.
Когда на русском форуме переходят на Вы, в реальной жизни начинают бить морду.
Re: Работа TWI по двум датчикам LM75
Вот код опроса единичного датчика. Адрес в 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
.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 раз.
Re: Работа TWI по двум датчикам LM75
[uquote="Satyr7",url="/forum/viewtopic.php?p=4781136#p4781136"]... Пытался перед стопом в обработчике сделать рестарт с другим адресом слейва , и пробовал вообще выходить из прерывания и делать по счëтчику входов некое подобие мультиплексора. Ни то ни другое не выходит. Понимаю что делаю что-то неправильно...[/uquote] Может приведете код инициализации, если не секрет. Чтобы увидеть уставку частоты SCL, например.
Re: Работа TWI по двум датчикам LM75
да уж и схему бы заодно, а то кофейная гуща почти закончиласьakl писал(а):приведете код инициализации
Re: Работа TWI по двум датчикам LM75
Схема в протеус - контроллер и датчик, и подтяжка типовая. Код выше добавил. Изначально сделал библиотеку для дисплея 44760 на I2C и датчика и понял что поженить эти две библиотеки не могу. Стал пробовать на двух датчиках без дисплея. Подскажите пожалуйста хотябы принцип. Если правильно понял - TWI умеет делать опрос нескольких устройств, но мне непонятен способ обращения к нескольким слейвам.
- Starichok51
- Модератор
- Сообщения: 19039
- Зарегистрирован: Сб авг 14, 2010 15:05:51
- Откуда: г. Озерск, Челябинская обл.
Re: Работа TWI по двум датчикам LM75
что тут не понятно?Satyr7 писал(а):но мне непонятен способ обращения к нескольким слейвам.
обращаешься к каждому устройству по его адресу.
ты в своем коде показал один адрес датчика (0b10010000).
а какой адрес ты установил у второго датчика?
а может, ты и у первого датчика адресные входы никуда не подключал?
Мудрость приходит вместе с импотенцией...
Когда на русском форуме переходят на Вы, в реальной жизни начинают бить морду.
Когда на русском форуме переходят на Вы, в реальной жизни начинают бить морду.
Re: Работа TWI по двум датчикам LM75
Вопрос не в адресе, он задаëтся любым. Мне непонятно как после опроса первого датчика сделать опрос второго. Например: Опрос первого - старт в основном цикле, далее в обработчике прерываний slaw, данные, рестарт, slar, запись температуры, стоп. А что дальше? Как со вторым? Или не делать стоп и в обработчике снова сделать рестарт и slaw второго? Или вообще по-другому? Например делать в основном цикле старт и там же slaw первого? Мне здесь всё непонятно.
-
veso74
- Поставщик валерьянки для Кота
- Сообщения: 1902
- Зарегистрирован: Сб май 05, 2012 20:24:52
- Откуда: KN34PC, Болгария
- Контактная информация:
Re: Работа TWI по двум датчикам LM75
Slave устройства I2C отвечают, когда их выбирают по адресу (и не отвечают на запросы по другим адресам). I2C - по двум проводам напр. 128 устройств (с исключениями). Вызываете первый датчик по его адресу, считываете температуру, вызываете второй датчик по адресу (другому), считываете температуру... С помощью выводов программного адреса количество датчиков может достигать 8.
Re: Работа TWI по двум датчикам LM75
Я это понимаю, не понимаю какова процедура на практике. Инициация TWI производится стартом, далее в обработчике производится адресация - это я так сделал, но понимаю, что сделал неправильно, хотя код и работает по одному датчику.
- Starichok51
- Модератор
- Сообщения: 19039
- Зарегистрирован: Сб авг 14, 2010 15:05:51
- Откуда: г. Озерск, Челябинская обл.
Re: Работа TWI по двум датчикам LM75
вообще не нужно создавать прерывание по TWI - всё прекрасно делается в основном цикле.
сначала делаешь все процедуры по первому датчику, потом - по второму.
я не знаю, какую запись можно или нужно делать в эти датчики.
а чтение делается так:
1. старт.
2. адрес с битом чтения.
3. чтение байтов температуры.
4. стоп.
делаешь эти 4 пункта для первого датчика, потом делаешь эти 4 пункта для второго датчика.
сначала делаешь все процедуры по первому датчику, потом - по второму.
я не знаю, какую запись можно или нужно делать в эти датчики.
а чтение делается так:
1. старт.
2. адрес с битом чтения.
3. чтение байтов температуры.
4. стоп.
делаешь эти 4 пункта для первого датчика, потом делаешь эти 4 пункта для второго датчика.
Мудрость приходит вместе с импотенцией...
Когда на русском форуме переходят на Вы, в реальной жизни начинают бить морду.
Когда на русском форуме переходят на Вы, в реальной жизни начинают бить морду.
Re: Работа TWI по двум датчикам LM75
Спасибо большое. Понял. Т. е. - делается всё не на прерываниях по кодам статусного регистра, а упрощëнно без проверок. И просто в основном цикле: старт адресация первого... стоп. Далее старт, адресация второго... стоп. Если правильно понял - в обработчике TWSI, как прописано выше в коде, вообще невозможно адресовать больше одного устройства. Просто я предполагал, что можно как-то задать выбор адресов. К примеру: счëтчик 0 - slaw первый, счётчик 1 - slaw второй, ит. д. Но лично у меня этого не получилось.
- Starichok51
- Модератор
- Сообщения: 19039
- Зарегистрирован: Сб авг 14, 2010 15:05:51
- Откуда: г. Озерск, Челябинская обл.
Re: Работа TWI по двум датчикам LM75
почему же невозможно в обработчике? по счетчику можно и в обработчике.Satyr7 писал(а):сли правильно понял - в обработчике TWSI, как прописано выше в коде, вообще невозможно адресовать больше одного устройства. Просто я предполагал, что можно как-то задать выбор адресов. К примеру: счётчик 0 - slaw первый, счётчик 1 - slaw второй, ит. д.
но как я уже сказал, обработчик на фиг не нужен.
вот именно! без всякого обработчика по очереди всё прекрасно делается в основном цикле.Satyr7 писал(а):И просто в основном цикле: старт адресация первого... стоп. Далее старт, адресация второго... стоп.
можно и в обработчике по счетчику, но с обработчиком - бессмысленное усложнение программы.
Мудрость приходит вместе с импотенцией...
Когда на русском форуме переходят на Вы, в реальной жизни начинают бить морду.
Когда на русском форуме переходят на Вы, в реальной жизни начинают бить морду.
Re: Работа TWI по двум датчикам LM75
Попробовал по счётчику, только напрасно вспотел, вероятно нужно хорошо понимать все тайминги. Прописал процедуру опроса как вы сказали, нормально скомпилировалось, но пока значения температуры не возвращается, читается только 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 и нормализовалось, возвращаются оба значения.
.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
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) и без передачи ответа, как у тебя сейчас сделано.
и твоей подпрограммы большой задержки не нужно вообще.
ты делаешь чтение, а в комментарии запись.
вообще не нужна отдельная подпрограмма 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) и без передачи ответа, как у тебя сейчас сделано.
и твоей подпрограммы большой задержки не нужно вообще.
Мудрость приходит вместе с импотенцией...
Когда на русском форуме переходят на Вы, в реальной жизни начинают бить морду.
Когда на русском форуме переходят на Вы, в реальной жизни начинают бить морду.
Re: Работа TWI по двум датчикам LM75
Спасибо большое. Я изначально всë сделал культурно, просто пока пыхтел с прерываниями снова понаделал всякой мешанины, предполагая, что если часть кода сделать в общей куче, то это должно как-то положительно отразиться. Все замечания исправлю. Способ выбора адресации слейвов в TWI пока отложил, т. к. моих познаний пока не хватает. Обрадовался, что получилось всё в цикле. Справлюсь с выводом на дисплей и вернусь к вопросу. Если я вам ещё не надоел, позже выложу свою стряпню. Спасибо.
- Starichok51
- Модератор
- Сообщения: 19039
- Зарегистрирован: Сб авг 14, 2010 15:05:51
- Откуда: г. Озерск, Челябинская обл.
Re: Работа TWI по двум датчикам LM75
тебе уже насколько раз сказали, что с адресацией проблем нет.Satyr7 писал(а):Способ выбора адресации слейвов в TWI пока отложил, т. к. моих познаний пока не хватает.
ты первому датчику задал "нулевой" адрес (000). второму датчику адресные входы подключи, например, 001. и обращайся по адресу 0b1001001 + бит записи или чтения.
не надоел.Satyr7 писал(а):Если я вам ещё не надоел
вменяемым людям помогать даже приятно.
но, к сожалению, попадаются невменяемые...
Мудрость приходит вместе с импотенцией...
Когда на русском форуме переходят на Вы, в реальной жизни начинают бить морду.
Когда на русском форуме переходят на Вы, в реальной жизни начинают бить морду.
Re: Работа TWI по двум датчикам LM75
Невменяемые это такие бивни как я, потому-что именно так всё и делал. Я прекрасно знаю как притяжками задавать физический адрес. Здесь просто смешались понятия, задания адреса на ногах, и адресации слейва в обработчике. Сидит, например, какой-нибудь придурковатый нуб, читает даташит и чешет тупую репу, и думает что ему делать дальше. Дальше начинает методом насильного впихивания лепить в обработчике всякие рестарты, надеясь что этот TWI каким-то чудом заработает. А в итоге, делать ему остаëтся только одно - идти в ближайшую поликлинику и просить таблетку от критинизма.