Хабр Курсы для всех
РЕКЛАМА
Практикум, Хекслет, SkyPro, авторские курсы — собрали всех и попросили скидки. Осталось выбрать!
; задержка в 1 микросекунду (максимально достижимой точности!!!)
; учитывается длительность RCALL и RET
; НЕ ДОЛЖНА ИСПОЛЬЗОВАТЬ НИ ОДНОГО РЕГИСТРА !!!!
; для низкой тактовой частоты, возможно, придется заменить на макрос из NOP-ов
delay1us:
; +3
nop ;1
push r0 ;2
pop r0 ;2
push r0 ;2 рассчитано ДЛЯ 20МГц!!!!!!
pop r0 ;2
push r0 ;2
pop r0 ;2
ret ;4 = 20 тактов (1 микросекунда)
;-------------------------------------------------------------------------------
delay10us:
; Задержка в 10 микросекунд (основана на delay1us) - повышенной точности!
; + 3
push wiretemp ; 2
ldi wiretemp, 9 ; 1 << для 20МГц!!!
d_loop: ;
rcall delay1us ; 8
dec wiretemp ; 1
brne d_loop ; 2/1
pop wiretemp ; 2
nop ; 1
nop ; 1
nop ; 1
ret ; 4
;-------------------------------------------------------------------------------
; задержка в wiretemp десятков микросекунд - повышенной точности не требуется
; вход: WireTemp = число десятков микросекунд для задержки (регистр портится)
;-------------------------------------------------------------------------------
delayus:
dec wiretemp
delayus1:
rcall delay10us
dec wiretemp
brne delayus1
rcall delay1us
rcall delay1us
rcall delay1us
rjmp delay1us
;-------------------------------------------------------------------------------
; выполняет выдачу сброса в линию 1-wire и возврат состояния PRESENCE
; вход: ничего
; выход: флаг Z установлен, если был PRESENCE
; так как длительность RESET может быть любой, прерывания не запрещаются,
; если это не необходимо
;-------------------------------------------------------------------------------
reset1w:
wire1
sbis wirepin,wirebit ; проверим наличие 1 в линии
rjmp presence_fault ; если нет - это ошибка
wire0 ; давим линию в 0
ldi wiretemp,49
rcall delayus ; 480 микросекунд задержка
wire1 ; линию в 1
ldi wiretemp,6
rcall delayus ; 60 микросекунд задержка
; начинаем ждать PRESENCE
ldi wiretemp,250 ; ждем с запасом
rw1_wait:
sbis wirepin,wirebit
rjmp presence_ok
rcall delay1us
dec wiretemp
brne rw1_wait
presence_fault:
; сюда мы попадаем, если не дождались PRESENCE
clz ; сбрасываем Z-флаг
ret
presence_ok:
; PRESENCE получен
sez
ldi wiretemp,49
rcall delayus
ret ; Z-флаг и так стоит
;-------------------------------------------------------------------------------
; выполняет прием байта из линии
; вход: ничего
; выход: r0 - принятый байт
;-------------------------------------------------------------------------------
resive1w:
ser wiretemp
mov r0,wiretemp
;-------------------------------------------------------------------------------
; выполняет передачу байта в линию
; вход: R0 - выводимый байт
; выход: R0 - то, что удалось ВВЕСТИ из линии
; портит: R0
; примечание: если делать ВЫВОД 0хFF, то на выходе будет ПРИНЯТЫЙ байт
;-------------------------------------------------------------------------------
send1w:
ldi wiretemp,8 ; число битов в байте (надо же :) )
sw1_next: ; сохраним флаги,
pushf ; т.к. будем запрещать прерывания
cli ; запрещаем прерывания
wire0 ; давим линию в 0
rcall delay1us ; 1 мкс задержки
ror r0 ; выталкиваем выводимый бит
brcc s0 ; если бит C = 0 - обход
wire1 ; линию в 1
s0:
push wiretemp
ldi wiretemp,9 ; в некоторых случаях может потребоваться
; увеличить это значение, но не более 13!
sw1_wait:
rcall delay1us
dec wiretemp
brne sw1_wait
clc
sbic wirepin,wirebit
sec
ror wireres
ldi wiretemp,9
rcall delayus ; 90 микросекунд - длительность тайм-слота
wire1
pop wiretemp
popf
dec wiretemp
brne sw1_next
mov r0,wireres
ret
;-------------------------------------------------------------------------------
; считывает 9 байтов в буфер, подсчитывает CRC
; портит r0 и SREG, регистры X и Z
;-------------------------------------------------------------------------------
readbytes1w:
clr wiretemp
sts CRC,wiretemp ; обнуляем CRC
ldiX Buffer
ldi wiretemp,9
r1w_next:
push wiretemp
rcall resive1w ; считываем 1 байт
; r0=считанному байту, начинаем подсчет CRC
st X+,r0 ; сохраняем принятый байт
rcall crc8 ; считаем контрольную сумму
pop wiretemp
dec wiretemp
brne r1w_next
ret
;-------------------------------------------------------------------------------
; выполняет подсчет CRC по алгоритму 1-Wire
; вход: r0 - считанный байт
; выход: CRC - содержит подсчитанную сумму
; портит: регистр Z
; примечание: перед первым вызовом CRC необходимо обнулить
;-------------------------------------------------------------------------------
crc8:
push r0
ldi wiretemp,8
mov wireres,wiretemp
r1w_loop_crc:
lds wiretemp,CRC
eor r0,wiretemp
ror r0
mov r0,wiretemp
brcc zero
ldi wiretemp,0x18
eor r0,wiretemp
zero:
ror r0
sts CRC,r0
pop r0
; 4 следующие команды делают циклический сдвиг r0
push r0
ror r0
pop r0
ror r0
; сдвиг закончен - очень удобно, не правда ли?!
push r0
dec wireres
brne r1w_loop_crc
pop r0
lds r0,CRC
ret
;-------------------------------------------------------------------------------
; Выбор датчика. Ссылка на массив с уникальным ID в Z
;-------------------------------------------------------------------------------
sel_sensor:
Send_1w CMD_MATCH_ROM ; Обращение к конкретному устройству
ldi r16,8
ss01:
lpm r0,Z+
rcall Send1w
dec r16
brne ss01
ret

int state = 3; // просто индикатор состояния кнопки
int one_wire = 5; //"1 вайр"
// the setup routine runs once when you press reset:
void setup() {
// initialize the digital pin as an output.
pinMode(state, OUTPUT);
pinMode(one_wire, OUTPUT);
digitalWrite(one_wire, LOW);
}
// the loop routine runs over and over again forever:
void loop() {
pinMode(one_wire, INPUT);
digitalWrite(state, !digitalRead(one_wire));
pinMode(one_wire, OUTPUT);
delay(20);
}
В чем проблема цапануть +12В под приборкой для постоянной индикации без всяких выкрутасов?
«1-wire» для кнопок с индикацией