You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
517 lines
10 KiB
517 lines
10 KiB
.DEVICE ATtiny13
|
|
.LIST
|
|
.LISTMAC
|
|
;běží na 9.6MHz, ckdiv8=0 (zapnuto)
|
|
;avrdude příkaz pro FUSEs: -U lfuse:w:0x6a:m -U hfuse:w:0xff:m
|
|
;LFUSE: 0x6A
|
|
;HFUSE: 0xFF
|
|
|
|
;aliasy pointerů
|
|
.def ZH = r31
|
|
.def ZL = r30
|
|
.def YH = r29
|
|
.def YL = r28
|
|
.def XH = r27
|
|
.def XL = r26
|
|
|
|
|
|
|
|
|
|
.def ARG = r20 ;registr pro předání hodnoty rutinám
|
|
|
|
;počátek paměti SRAM pro uložení přečtené teploty (9 bajtů)
|
|
.equ SRAM_t_H = 0x00
|
|
.equ SRAM_t_L = 0x00
|
|
|
|
;komunikační kanál pro ds1820
|
|
.equ PORTn = PORTB
|
|
.equ PINn = PINB
|
|
.equ DDRn = DDRB
|
|
.equ n = 0 ;pin pro komunikaci s DS1820
|
|
|
|
; Č A S O V Á N Í
|
|
;délka 1 cyklu = T = 1/f
|
|
; tXXXu = [XXX / (4*T)] - 2
|
|
; (ldi, rcall a ret zabere 8 cyklů)
|
|
; nejnižší hodnota je 1 ... 12T čekání
|
|
; attiny13@9.6MHz+CKDIV8...T=0.83333us
|
|
.equ t480u = 142
|
|
.equ t410u = 120
|
|
.equ t70u = 19
|
|
.equ t64u = 17
|
|
.equ t60u = 16
|
|
.equ t54u = 14
|
|
.equ t10u = 1
|
|
|
|
;registry pro CRC rutinu
|
|
.def rChar = r19
|
|
.def rCount = r18 ;počet bajtů
|
|
.def rBitCount = r17
|
|
.def rTemp = r16
|
|
.def rCRC8 = r21 ;výsledek (musí být jiný než ARG)
|
|
|
|
.def R = r4
|
|
.def G = r5
|
|
.def B = r6
|
|
.def tL = r2
|
|
.def tH = r3
|
|
|
|
;6us je obvykle moc málo pro volání DELAY
|
|
.MACRO t6uDELAY
|
|
ldi r16,2 ;pro attiny13@9.6MHz+CKDIV8 je to 2 x 4T = 8T = 8 x 0.83333us = 6us čekání
|
|
t6u: nop ;pozor! některé překladače labely v makrech nepodporují!
|
|
dec r16
|
|
brne t6u
|
|
.ENDMACRO
|
|
|
|
;ovládání sběrnice
|
|
.MACRO BUS_L
|
|
cbi PORTn,n
|
|
sbi DDRn,n ;pin n výstupní, výstup 0
|
|
.ENDMACRO
|
|
|
|
.MACRO BUS_H
|
|
sbi PORTn,n
|
|
cbi DDRn,n ;pin n vstupní, pullup zapnutý (+ doporučeno 4.7k externí pullup)
|
|
.ENDMACRO
|
|
|
|
.MACRO RGB_OFF
|
|
cbi PORTB,1
|
|
cbi PORTB,2
|
|
cbi PORTB,3
|
|
.ENDMACRO
|
|
|
|
.MACRO RGB_ON
|
|
sbi PORTB,1
|
|
sbi PORTB,2
|
|
sbi PORTB,3
|
|
.ENDMACRO
|
|
|
|
.MACRO PWM_CYCLE
|
|
ldi r17,@0 ;1
|
|
PWM0: RGB_OFF ; 6
|
|
ldi r16,40 ; 1
|
|
PWM1: cp r16,R ; 1
|
|
brne PWM2 ; 1/2
|
|
sbi PORTB,1 ; 2
|
|
PWM2: cp r16,G ; 1
|
|
brne PWM3 ; 1/2
|
|
sbi PORTB,2 ; 2
|
|
PWM3: cp r16,B ; 1
|
|
brne PWM4 ; 1/2
|
|
sbi PORTB,3 ; 2
|
|
PWM4: dec r16 ; 1
|
|
brne PWM1 ; 1/2 (805)*r17+6
|
|
dec r17 ; 1
|
|
brne PWM0 ; 1/2
|
|
RGB_OFF ;6
|
|
.ENDMACRO
|
|
|
|
|
|
|
|
|
|
|
|
; Z A C A T E K P R O G R A M U
|
|
.org 0x0000 ;RESET
|
|
rjmp RESET ;skok na start po resetu
|
|
|
|
|
|
; začátek kódu
|
|
.org 0x0010
|
|
RESET: ldi r16,low(RAMEND) ;nastaví stack pointer
|
|
out SPL,r16
|
|
|
|
ldi r16,0b00011111 ;směr portu B - vše na výstup. Směr pinu n se bude měnit za chodu
|
|
out DDRB,r16
|
|
ldi r16,0b00000000 ;RGB=0b000, ledka zhasnuta
|
|
out PORTB,r16
|
|
|
|
;tělo programu
|
|
clr R
|
|
clr G
|
|
clr B
|
|
MainLoop:
|
|
rcall GET_T ;teplota do SRAM 0x00-0x08
|
|
|
|
cpi ARG, 0
|
|
brne MainLoop
|
|
|
|
;výpočet barvy
|
|
ldi ZH,SRAM_t_H ;počátek řetězce přijatých bajtů do Z
|
|
ldi ZL,SRAM_t_L
|
|
ld tL,Z+ ;načíst teplotu z paměti
|
|
ld tH,Z
|
|
ldi r16,40
|
|
mov R,r16 ;defaultní barva - bílá, 40 40 40
|
|
mov G,r16
|
|
mov B,r16
|
|
ldi r16,0
|
|
cpse tH,r16 ;pokud tH != 0x00, skoč na mínus
|
|
rjmp MINUS
|
|
;PLUS nebo NULA
|
|
ldi r16,21 ;tL >= 10.5? --> c10_20
|
|
cp tL,r16
|
|
brge c10_20
|
|
;0-blue,10-white
|
|
clr R
|
|
clr G
|
|
mov r16,tL
|
|
lsl r16
|
|
mov R,r16
|
|
mov G,r16
|
|
rjmp C_DONE
|
|
|
|
c10_20: ;10-white,20-yellow
|
|
ldi r16,41 ;tL >= 20.5? --> c20_30
|
|
cp tL,r16
|
|
brge c20_30
|
|
|
|
mov r16,tL
|
|
subi r16,20
|
|
lsl r16
|
|
sub B,r16
|
|
rjmp C_DONE
|
|
|
|
c20_30: ;20-yellow,30-red
|
|
ldi r16,61 ;tL >= 30.5? --> c30_40
|
|
cp tL,r16
|
|
brge c30_40
|
|
clr B
|
|
mov r16,tL
|
|
subi r16,40
|
|
lsl r16
|
|
sub G, r16
|
|
rjmp C_DONE
|
|
|
|
c30_40: ;30-red, 40-purple
|
|
ldi r16,81 ;tL >= 40.5? --> c40_50
|
|
cp tL,r16
|
|
brge c40_50
|
|
clr B
|
|
clr G
|
|
mov r16,tL
|
|
subi r16,60
|
|
lsl r16
|
|
add B, r16
|
|
rjmp C_DONE
|
|
|
|
c40_50: ;40-purple, 50-"UV"
|
|
ldi r16,101 ;tL >= 50.5? --> c50_hi
|
|
cp tL,r16
|
|
brge c50_hi
|
|
clr G
|
|
mov r16,tL
|
|
subi r16,80
|
|
sub R, r16
|
|
rjmp C_DONE
|
|
|
|
c50_hi:
|
|
clr G
|
|
ldi r16,20
|
|
mov R,r16
|
|
rjmp C_DONE
|
|
|
|
MINUS:
|
|
neg tL
|
|
ldi r16,21 ;-tL >= 10.5? --> cm10_20
|
|
cp tL,r16
|
|
brge cm10_20
|
|
mov r16,tL
|
|
lsl r16
|
|
clr R
|
|
clr G
|
|
add G,r16
|
|
rjmp C_DONE
|
|
|
|
cm10_20:
|
|
ldi r16,41 ;-tL >= 20? --> cm20_lo
|
|
cp tL,r16
|
|
brge cm20_lo
|
|
clr R
|
|
mov r16,tL
|
|
subi r16,20
|
|
lsl r16
|
|
sub B,r16
|
|
rjmp C_DONE
|
|
|
|
cm20_lo:
|
|
clr R ;-tL >= 20? --> cm40_lo
|
|
clr B
|
|
rjmp C_DONE
|
|
|
|
C_DONE:
|
|
|
|
; mov r16,R
|
|
; ldi r17,11
|
|
; rcall EEwrite
|
|
; mov r16,G
|
|
; ldi r17,12
|
|
; rcall EEwrite
|
|
; mov r16,B
|
|
; ldi r17,13
|
|
; rcall EEwrite
|
|
|
|
; ldi ZH, SRAM_t_H
|
|
; ldi ZL, SRAM_t_L
|
|
;NextEE: ld r16,Z
|
|
; mov r17, ZL
|
|
; rcall EEwrite
|
|
; inc ZL
|
|
; cpi ZL,2
|
|
; brlo NextEE
|
|
|
|
PWM_CYCLE 255
|
|
|
|
rjmp MainLoop
|
|
|
|
|
|
|
|
|
|
|
|
;G E T T E M P E R A T U R E
|
|
;Přečte 9 bajtů z teplotního čidla na pinu n (PINn, PORTn, DDRn) a uloží je do SRAM na adresu 0x00 až 0x08.
|
|
;status je uložen do ARG (ARG == 0 -> CRC se shoduje, OK; ARG != 0 -> CRC se neshoduje, chyba přenosu)
|
|
;
|
|
;SRAM po vykonání procedury GET_T:
|
|
; 0x00 temperature low byte - unit: 0.5°C
|
|
; 0x01 temperature high byte (sign, 0x00 = positive, 0xff = negative)
|
|
; 0x02 "user byte 1"
|
|
; 0x03 "user byte 2"
|
|
; 0x04 reserved, 0xFF
|
|
; 0x05 reserved, 0xFF
|
|
; 0x06 count remain (default 0x0C)
|
|
; 0x07 count per °C (fixed to 0x10)
|
|
; 0x08 CRC
|
|
;celá čtecí rutina trvá obvykle asi 550ms, max je asi 750ms. Během rutiny "W4C" může být prováděno něco jiného s pevnou délkou 700ms.
|
|
GET_T:
|
|
push r17 ;ulož používané registry do STACKu
|
|
|
|
rcall TxRESET ;RESET
|
|
ldi ARG,0xCC ;SKIP_ROM
|
|
rcall TxBYTE
|
|
ldi ARG,0x44 ;CONVERT_T
|
|
rcall TxBYTE
|
|
rcall W4C ;čekej na konverzi teploty
|
|
rcall TxRESET ;RESET
|
|
ldi ARG,0xCC ;SKIP_ROM
|
|
rcall TxBYTE
|
|
ldi ARG,0xBE ;READ_SCRATCHPAD
|
|
rcall TxBYTE
|
|
|
|
;přijmout 9 bajtů, uložit na 0x00 až 0x09 v SRAM
|
|
ldi ZH, SRAM_t_H
|
|
ldi ZL, SRAM_t_L
|
|
NEXT_B: rcall RxBYTE ;přijmi 1 bajt -> ARG
|
|
|
|
N_B3: st Z+,ARG ;do SRAM na adresu Z ulož výsledek. Z++
|
|
cpi ZL,9 ;je Z == 9?
|
|
brlo NEXT_B ;je-li menší, čti další bajt
|
|
|
|
;vypočítat CRC, pokud se shoduje s přečtenou hodnotou, r16=1, jinak r16=0
|
|
ldi XH,SRAM_t_H
|
|
ldi XL,SRAM_t_L
|
|
ldi rCount,9
|
|
rcall CRC8
|
|
mov ARG,rCRC8
|
|
|
|
pop r17
|
|
ret ;návrat, ARG==0 .. ok, ARG!=0 .. error
|
|
|
|
|
|
;D E L A Y
|
|
; r16 = d = poček čtyřkloků zmenšený o 2 (dva čtyřkloly se vykonají při nastavení r16 pomocí LDI (1T), RCALL (3T) a RET (4T))
|
|
DELAY: nop
|
|
dec r16
|
|
brne DELAY
|
|
nop
|
|
ret ; po návratu je r16 = 0
|
|
|
|
|
|
|
|
;R E S E T P U L S E
|
|
TxRESET:
|
|
BUS_L ;stáhni sběrnici
|
|
|
|
PWM_CYCLE 1
|
|
;ldi r16,t480u
|
|
;rcall DELAY ;480us čekání
|
|
|
|
BUS_H ;uvolni sběrnici
|
|
|
|
ldi r16,t70u
|
|
rcall DELAY ;70us čekání
|
|
|
|
sbic PINn,n
|
|
rjmp TxRESET ;není-li presence pulse, zopakuj TxRESET
|
|
|
|
;ldi r16,t410u
|
|
;rcall DELAY ;410T čekání
|
|
PWM_CYCLE 1
|
|
|
|
ret ;návrat
|
|
|
|
|
|
;T R A N S M I T B Y T E
|
|
; odešlou se data z ARG
|
|
TxBYTE: ldi r17,8 ;čítač bytů = 8
|
|
;nový bit
|
|
TxNB: lsr ARG ;nový bit; rotovat ARG: ARG.0 -> C
|
|
brcs Tx1 ;jednička - skok na Tx1, jinak pokračuj
|
|
|
|
;-- Odeslání 0 --
|
|
BUS_L ;stáhni sběrnici
|
|
|
|
ldi r16,t60u
|
|
rcall DELAY ;60us čekání
|
|
|
|
BUS_H ;uvolni sběrnici
|
|
|
|
ldi r16,t10u
|
|
rcall DELAY ;10us čekání
|
|
|
|
rjmp TxLOOP ;skok na konec rutiny
|
|
|
|
;-- Odeslání 1 --
|
|
Tx1: BUS_L ;stáhni sběrnici
|
|
|
|
t6uDELAY ;6us čekání
|
|
|
|
BUS_H ;uvolni sběrnici
|
|
|
|
ldi r16,t64u
|
|
rcall DELAY ;64us čekání
|
|
|
|
TxLOOP: dec r17 ;odečti 1 od čítače bitů
|
|
brne TxNB ;zbývají bity? ano -> TxNB
|
|
ret ;návrat
|
|
|
|
|
|
;R E C E I V E B Y T E
|
|
; do ARG se uloží přečtený byte
|
|
RxBYTE: ldi r17,8 ;čítač bitů
|
|
clr ARG ;vymaž ARG
|
|
;nový bit
|
|
RxNB: rcall RxBIT
|
|
|
|
ror ARG ;rotuj ARG C[=PINB.n] -> ARG.7, ARG.0 -> C
|
|
dec r17 ;odečti 1 od čítače bitů
|
|
brne RxNB ;zbývají bity? ano -> RxNB
|
|
ret ;návrat
|
|
|
|
|
|
;R E C E I V E S I N G L E B I T
|
|
RxBIT: BUS_L ;stáhni sběrnici
|
|
|
|
t6uDELAY ;6us čekání
|
|
|
|
BUS_H ;uvolni sběrnici
|
|
|
|
ldi r16,t10u
|
|
rcall DELAY ;10us čekání
|
|
|
|
sbic PINn,n ;PINB.n -> C
|
|
sec
|
|
sbis PINn,n
|
|
clc
|
|
|
|
ldi r16,t54u
|
|
rcall DELAY ;54us čekání
|
|
ret ;návrat
|
|
|
|
|
|
;Č E K Á N Í N A D O K O N Č E N Í K O N V E R Z E
|
|
;čekání na dokončení konverze teploty (nelze použít v parazitním režimu, v tom je třeba čekat 700ms.)
|
|
W4C: BUS_H
|
|
;až 700ms dlouhá čekací smyčka
|
|
W4C0: ldi r18,5
|
|
W4C1: PWM_CYCLE 200
|
|
dec r18
|
|
brne W4C1
|
|
|
|
rcall RxBIT ;přijmi bit do C.
|
|
brcc W4C0 ;C=0 -> čekej dál
|
|
|
|
ret ;návrat
|
|
|
|
|
|
;V Ý P O Č E T C R C
|
|
;XH,XL,rCount --> rCRC8
|
|
CRC8: push XH ;save XH
|
|
push XL ;save XL
|
|
push rChar ;save rChar
|
|
push rCount ;save rCount
|
|
push rBitCount ;save rBitCount
|
|
push rTemp ;save rTemp
|
|
|
|
clr rCRC8 ;start with a zero CRC-8
|
|
|
|
;begin loop to do each byte in the string
|
|
CRC8BYT:
|
|
ld rChar,X+ ;fetch next string byte and bump pointer
|
|
ldi rBitCount,8 ;load the bit-counter for this byte
|
|
|
|
;begin loop to do each bit in the byte
|
|
CRC8BIT:
|
|
mov rTemp,rChar ;get a temporary copy of current data
|
|
eor rTemp,rCRC8 ;XOR the data byte with the current CRC
|
|
lsr rCRC8 ;position to the new CRC
|
|
lsr rChar ;position to next bit of this byte
|
|
lsr rTemp ;get low bit of old result into c-bit
|
|
brcc CRC8NA ;br if low bit was clear (no adjustment)
|
|
ldi rTemp,$8C ;magical value needed for CRC-8s
|
|
eor rCRC8,rTemp ;fold in the magic CRC8 value
|
|
CRC8NA:
|
|
dec rBitCount ;count the previous bit done
|
|
brne CRC8BIT ;br if not done all bits in this byte
|
|
;end loop to do each bit in the byte
|
|
|
|
dec rCount ;count this byte done
|
|
brne CRC8BYT ;br if not done all bytes in the string
|
|
;end loop to do each byte in the string
|
|
|
|
pop rTemp ;restore rTemp
|
|
pop rBitCount ;restore rBitCount
|
|
pop rCount ;restore rCount
|
|
pop rChar ;restore rChar
|
|
pop XL ;restore XL
|
|
pop XH ;restore XH
|
|
ret ;return to caller
|
|
;
|
|
;END OF SUBROUTINE CRC8
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
;cteni z EEPROM, v [r17 je ADRESA], v (r16 se objeví DATA)
|
|
;EEread:
|
|
; sbic EECR,1
|
|
; rjmp EEread ;cekani dokud neni EEPROM ready
|
|
;
|
|
; out EEARL, r17 ;ulozit adresu z r17
|
|
; sbi EECR,0 ;nastavenim EERE zacina cteni
|
|
; in r16,EEDR ;cteni dat z EEDR do r16
|
|
;
|
|
; ret
|
|
|
|
|
|
;zapis do EEPROM, v [R17 je ADRESA], v [R16 jsou DATA]
|
|
EEwrite:
|
|
sbic EECR,EEPE
|
|
rjmp EEwrite ;cekani dokud neni EEPROM ready
|
|
|
|
cbi EECR,EEPM1 ;nastavit programovaci mod
|
|
cbi EECR,EEPM0
|
|
|
|
out EEARL, r17 ;dej adresu z r17 do EEARL
|
|
out EEDR, r16 ;dej data z r16 do EEDR
|
|
sbi EECR,EEMPE ;master program enable
|
|
sbi EECR,EEPE ;program enable
|
|
|
|
ret
|
|
|
|
|
|
|
|
|