Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- .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í
- ; [email protected]+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
- 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
Advertisement
Add Comment
Please, Sign In to add comment