Как ни странно, возникла необходимость считать ID из DS1990 Я сделал маленький макет ридера, который читает «таблетку» и передаёт по UART-у ASCII кодом (4800 бод 8N1). Вот маленькая схемка макета.

Ниже привожу текст прошивки переходника.
;* ************************************************************************ *
;* ib2uart.avr, iButton-reader *
;* ************************************************************************ *
.include "tn13def.inc"
; опции программирования
; BODLEVEL1=BODLEVEL0=SUT0=CKSEL0=0
.set VERSION = 0x0100
; * описание портов контроллера *
; выходной интерфейс управления реле/ключом
.equ CTBout = PORTB ; выходной порт
.equ CTBcfg = DDRB ; порт конфигурации выходов
.equ CTBin = PINB ; порт конфигурации выходов
.equ ledpin = 0 ; LED
.equ ibpin = 1 ; ib-вход/выход
.equ ouart = 4 ; UART-выход
.equ CTB_CFG = (1<<ouart)|(1<<ledpin)|(0<<ibpin) ; константа cfg порта
.equ CTB_OUT = (1<<ouart)|(1<<ledpin)|(0<<ibpin) ; константа out порта
; тактовая частота МГц
#define XCLK 9.6
.equ CN2MKS = INT((2*XCLK-7)/3) ; константа 2мкс
.equ CN5MKS = INT((5*XCLK-9)/3) ; константа 5мкс
.equ CN10MKS = INT((10*XCLK-9)/3) ; константа 10мкс
.equ CN50MKS = INT((50*XCLK-9)/3) ; константа 50мкс
; * назначение переменных *
.def cnt = R19
.def tmp1 = R20 ; переменная общего пользования
.def tmp2 = R21 ; переменная общего пользования
.def tmp3 = R22 ; переменная общего пользования
.def tmp4 = R23 ; переменная общего пользования
.equ store = SRAM_START ; указатель на память
; кодовый сегмент
.cseg ; CODE segment
;______________________________________________________________
; таблица
.org 0
rjmp main_rstcold ; вектор сброса
.org INT0addr
reti ; External Interrupt 0
.org PCI0addr
reti ; External Interrupt Request 0
.org OVF0addr
reti ; Timer/Counter0 Overflow
.org ERDYaddr
reti ; EEPROM Ready
.org ACIaddr
reti ; Analog Comparator
.org OC0Aaddr
reti ; Timer/Counter0 Compare Match 0A
.org OC0Baddr
reti ; Timer/Counter Compare Match B
.org WDTaddr
reti ; Watchdog Time-out
.org ADCCaddr
reti ; ADC Conversion Complete
;______________________________________________________________
uart_del:
; полубитная задержка
ldi tmp3,251 ; загрузка счетчика задержки
uart_dlp:
nop ; пустой такт
dec tmp3 ; декремент счётчика задержки
brne uart_dlp ; закрытие цикла ожидания
ret ; выход
;______________________________________________________________
pr_hex:
push tmp1 ;
swap tmp1 ;
rcall pr_dig ;
pop tmp1 ;
pr_dig:
andi tmp1,0x0F ;
cpi tmp1,0x0A ;
ldi tmp2,0x30 ;
brcs prhx_coring ;
ldi tmp2,0x37 ;
prhx_coring:
add tmp1,tmp2 ;
;______________________________________________________________
putchar:
; функция передачи байта TxByte
; IN - tmp1
; OUT - нет
; CHG - нет
push tmp1 ;
push tmp2 ;
push tmp3 ;
ldi tmp2,1+8+1 ; 1+8+1
com tmp1 ;
sec ; установка старт-бита
putc_pblm:
brcc putc_psbm ; переход на установку лог.1, если C==0
cbi CTBout,ouart ; установка лог.0
rjmp putc_pbdm ; переход к битовой задержке
putc_psbm:
sbi CTBout,ouart ; установка лог.1
nop ; тактовое уравнивание
putc_pbdm:
rcall uart_del ;
rcall uart_del ;
lsr tmp1 ; получение в C след.бита
dec tmp2 ; декремент счетчика битов
brne putc_pblm ; проверка закрытия цикла посылки битов
pop tmp3 ;
pop tmp2 ;
pop tmp1 ;
ret ; выход
;______________________________________________________________
; вектор сброса, вход в основную петлю программы
main_rstcold:
; инициализация сторожевого таймера
cli ; запрет всех прерываний
; установка стека
ldi tmp1,low(RAMEND); загрузка указателя стека
out SPL,tmp1 ; запись указателя
; начальная установка конфигурации порта B
; PB5 PB4 PB3 PB2 PB1 PB0
; LED RSL RSH
; in in in out out out
ldi tmp1,CTB_OUT ; значение выходов порта
out CTBout,tmp1 ; запись состояния выходов в порт
ldi tmp1,CTB_CFG ; значение выходов порта B
out CTBcfg,tmp1 ; запись I/O конфигурации
; разрешаем внешние прерывания по фронту/срезу
ldi tmp1,(1<<ISC00) ; значение для int0 по фронту/срезу
out MCUCR,tmp1 ; запись в регистр
ldi tmp1,(0<<INT0) ; значение для разрешения int0
out GIMSK,tmp1 ; разрешение прерываний int0
sei ; разрешение всех прерываний
main_loop:
rcall ib_reset ; сброс i-button
brts main_present ; переход, если i-button ответил
rjmp main_loop ; зацикливание
main_present:
ldi tmp1,0x33 ; код команды чтения ID DS1990
rcall ib_write ; передача команды в i-button
ldi ZL,low(store) ; мл.байта указателя на массив, куда будет запоминаться ID
ldi ZH,high(store) ; ст.байта указателя на массив, куда будет запоминаться ID
ldi tmp4,0x08 ; кол-во байт ID
main_rdlp:
push tmp4 ; сохраняем счётчик
rcall ib_read ; читаем данные из i-button
pop tmp4 ; восстанавливаем счётчик байтов
push tmp4 ; опять сохраняем счётчик
cpi tmp4,8 ; проверяем, 1й ли байт считан
brne main_famskp ; переход, если не 1й
cpi tmp1,0x00 ; значение 1го байта ==0?
brne main_famskp ; если !=0, то продолжаем чтение (считан тип ИМС)
rjmp main_loop ; если ==0, то это просто замкнули контакты
main_famskp:
st Z+,tmp1 ; запоминаем байт в памяти
pop tmp4 ; восстанавливаем счётчик байтов
dec tmp4 ; декремент счётчика
brne main_rdlp ; закрываем цикл чтения ID
; проверка CRC
ldi ZL,low(store) ; мл.байта указателя на массив ID
ldi ZH,high(store) ; ст.байта указателя на массив ID
clr tmp2 ; сброс начального значения CRC
ldi tmp4,0x07 ; кол-во байт, по которым считается CRC
main_crclp:
ld tmp1,Z+ ; загружаем очередной байт
rcall update_crc ; вычисляем очередное значение CRC
dec tmp4 ; декрементируем счётчик байтов
brne main_crclp ; закрытие цикла подсчёта CRC
ld tmp1,Z ; загружаем CRC, которое считано из i-button
eor tmp1,tmp2 ; сравниваем с CRC, которое вычислили сами
breq main_crcok ; переход, если CRC совпали
rjmp main_loop ; если ошибка CRC - возвращаемся в основную петлю
main_crcok:
ldi ZL,low(store) ; мл.байта указателя на массив ID
ldi ZH,high(store) ; ст.байта указателя на массив ID
ldi tmp4,0x08 ; установка кол-ва байтов, которые будут переданы по UART
cli ; запрет прерываний
main_txlp:
push tmp4 ; сохранение счётчика
ld tmp1,Z+ ; загрузка очередного байта ID из памяти
rcall pr_hex ; вывод байта по UART
ldi tmp1,0x20 ; установка кода пробела
rcall putchar ; вывод символа по UART
pop tmp4 ; восстановление счётчика
dec tmp4 ; декремент
brne main_txlp ; закрытие петли передачи ID
ldi tmp1,0x0D ; установка кода "\r"
rcall putchar ; вывод символа по UART
ldi tmp1,0x0A ; установка кода "\n"
rcall putchar ; вывод символа по UART
sei ; разрешение прерываний
cbi CTBout,ledpin ; включение светодиода
ldi tmp3,0x02 ; установка ст.байта задержки
ledp_lph:
clr tmp2 ;~1, установка "среднего" байта задержки
ledp_lpm:
clr tmp1 ;~1, установка "младшего" байта задержки
ledp_lpl:
nop ;~1, пустые такты, чтобы задержка тянулась медленнее :)
nop ;
dec tmp1 ;~1, декремент мл.счётчика задержки
brne ledp_lpl ;~2/1, закрытие мл.цикла
dec tmp2 ;~1, декремент ср.счётчика задержки
brne ledp_lpm ;~2/1, закрытие ср.цикла
dec tmp3 ;~1, декремент ст.счётчика задержки
brne ledp_lph ;~2/1, закрытие ст.цикла
sbi CTBout,ledpin ; выключение светодиода
rjmp main_loop ; возврат в основную петлю
;______________________________________________________________
; задержка 50мкс, 3(rcall)+2(rjmp) + 3*n+4(ret)
del50mks:
ldi tmp4,CN50MKS ;~1, установка константы 50мкс
rjmp del2_lp ;~2, переход на петлю задержки
;______________________________________________________________
; задержка 10мкс, 3(rcall)+2(rjmp) + 3*n+4(ret)
del10mks:
ldi tmp4,CN10MKS ;~1, установка константы 10мкс
rjmp del2_lp ;~2, переход на петлю задержки
;______________________________________________________________
; задержка 5мкс, 3(rcall)+2(rjmp) + 3*n+4(ret)
del5mks:
ldi tmp4,CN5MKS ;~1, установка константы 5мкс
rjmp del2_lp ;~2, переход на петлю задержки
;______________________________________________________________
; задержка 2мкс, 3(rcall)+2(rjmp) + 3*n+4(ret)
del2mks:
ldi tmp4,CN2MKS ;~1, установка константы 5мкс
del2_lp:
dec tmp4 ;~1, декремент счётчика задержки
brne del2_lp ;~2/1, закрытие цикла
ret ;~4, выход
;______________________________________________________________
; задержка 90мкс
del90mks:
rcall del10mks ; 10mks
rcall del10mks ; 10mks
rcall del10mks ; 10mks
rcall del10mks ; 10mks
rjmp del50mks ; 50mks
;______________________________________________________________
; задержка 100мкс
del100mks:
rcall del50mks ; 50mks
rjmp del50mks ; 50mks
;______________________________________________________________
; задержка 500мкс
del500mks:
rcall del100mks ; 100mks
rcall del100mks ; 100mks
rcall del100mks ; 100mks
rcall del100mks ; 100mks
rjmp del100mks ; 100mks
;______________________________________________________________
; чтение/запись байта в i-button; запись 0xFF - это чтение
; из i-button, таймслоты те же
ib_read:
ldi tmp1,0xFF ; установка константы для чтения
ib_write:
mov tmp2,tmp1 ; установка параметра (здесь tmp2 рабочий регистр)
ldi tmp3,8 ; установка счётчика битов
rwloop:
sbi CTBcfg,ibpin ; опускаем линию i-button в 0
rcall del2mks ; маленькая задержка 2мкс
ror tmp2 ; бит, который будем передавать толкаем в C
brcc wrzero ; если бит ==0, то оставляем линию i-button ==0
cbi CTBcfg,ibpin ; если бит ==0, то переводим линию i-button ==1
wrzero:
rcall del10mks ; маленькая задержка, чтобы вывод перешёл в 1
clc ; в C будет значение бита, посланного i-button
sbic CTBin,ibpin ; читаем значение вывода i-button
sec ; устанавливаем C==1, если вывод i-button==1
ror tmp1 ; записываем считанное значение в tmp1
rcall del50mks ; выдерживаем до конца время тайм-слота
cbi CTBcfg,ibpin ; поднимаем (отпускаем) линию i-button:
rcall del2mks ; маленькая задержка 2мкс, чтобы линия поднялась
dec tmp3 ; декремент счётчика битов
brne rwloop ; закрытие цикла чтения 8ми битов
ret ; выход
;______________________________________________________________
; сброс i-button и чтение импульса "присутствия" i-button на линии,
; результат возвращается в T
ib_reset:
sbi CTBcfg,ibpin ; линия i-button ==0
rcall del500mks ; большая задержка: i-button обесточивается
cbi CTBcfg,ibpin ; поднимаем линию i-button
rcall del90mks ; ждём заряда внутреннего конденсатора i-button
clt ; сброс T
sbis CTBin,ibpin ; проверяем состояние линии: если i-button присутствует,
; то он в этот момент должен удерживать линию в 0
set ; если линия удерживается в 0, то T==1, i-button на линии
rcall del500mks ; ждём пока i-button отпустит линию
ret ; выход
;______________________________________________________________
; подсчёт байта CRC
; в tmp1 байт, который надо добавить в CRC, в tmp2 уже накопленный CRC8
; алгоритм списан из спецификации на DS1990
update_crc:
push tmp3 ;
push tmp4 ;
ldi tmp4,8 ;
upcr_lp:
mov tmp3,tmp2 ;
eor tmp3,tmp1 ;
sbrs tmp3,0 ;
rjmp upcr_zbit ;
ldi tmp3,0x18 ;
eor tmp2,tmp3 ;
lsr tmp2 ;
sbr tmp2,(1<<7) ;
rjmp upcr_shift ;
upcr_zbit:
lsr tmp2 ;
upcr_shift:
lsr tmp1 ;
dec tmp4 ;
brne upcr_lp ;
pop tmp4 ;
pop tmp3 ;
ret ; выход