MightyPork

avr color thermometer

May 9th, 2014
246
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. .DEVICE ATtiny13
  2. .LIST
  3. .LISTMAC
  4. ;běží na 9.6MHz, ckdiv8=0 (zapnuto)
  5. ;avrdude příkaz pro FUSEs: -U lfuse:w:0x6a:m -U hfuse:w:0xff:m
  6. ;LFUSE: 0x6A
  7. ;HFUSE: 0xFF
  8.  
  9. ;aliasy pointerů
  10. .def    ZH      = r31
  11. .def    ZL      = r30
  12. .def    YH      = r29
  13. .def    YL      = r28
  14. .def    XH      = r27
  15. .def    XL      = r26
  16.  
  17.  
  18.  
  19.  
  20. .def    ARG     = r20       ;registr pro předání hodnoty rutinám
  21.  
  22. ;počátek paměti SRAM pro uložení přečtené teploty (9 bajtů)
  23. .equ    SRAM_t_H    = 0x00
  24. .equ    SRAM_t_L    = 0x00
  25.  
  26. ;komunikační kanál pro ds1820
  27. .equ    PORTn       = PORTB
  28. .equ    PINn        = PINB
  29. .equ    DDRn        = DDRB
  30. .equ    n       = 0         ;pin pro komunikaci s DS1820
  31.  
  32. ; Č A S O V Á N Í
  33. ;délka 1 cyklu = T = 1/f
  34. ;    tXXXu  = [XXX / (4*T)] - 2
  35. ; (ldi, rcall a ret zabere 8 cyklů)
  36. ; nejnižší hodnota je 1 ... 12T čekání
  37. ; [email protected]+CKDIV8...T=0.83333us
  38. .equ    t480u       = 142
  39. .equ    t410u       = 120
  40. .equ    t70u        = 19
  41. .equ    t64u        = 17
  42. .equ    t60u        = 16
  43. .equ    t54u        = 14
  44. .equ    t10u        = 1
  45.  
  46. ;registry pro CRC rutinu
  47. .def    rChar       = r19
  48. .def    rCount      = r18       ;počet bajtů
  49. .def    rBitCount   = r17
  50. .def    rTemp       = r16
  51. .def    rCRC8       = r21       ;výsledek (musí být jiný než ARG)
  52.  
  53. .def    R       = r4
  54. .def    G       = r5
  55. .def    B       = r6
  56. .def    tL      = r2
  57. .def    tH      = r3
  58.  
  59. ;6us je obvykle moc málo pro volání DELAY
  60. .MACRO t6uDELAY
  61.     ldi r16,2           ;pro [email protected]+CKDIV8 je to 2 x 4T = 8T = 8 x 0.83333us = 6us čekání
  62. t6u:    nop             ;pozor! některé překladače labely v makrech nepodporují!
  63.     dec r16
  64.     brne t6u
  65. .ENDMACRO
  66.  
  67. ;ovládání sběrnice
  68. .MACRO BUS_L
  69.     cbi PORTn,n
  70.     sbi DDRn,n          ;pin n výstupní, výstup 0
  71. .ENDMACRO
  72.  
  73. .MACRO BUS_H
  74.     sbi PORTn,n
  75.     cbi DDRn,n          ;pin n vstupní, pullup zapnutý (+ doporučeno 4.7k externí pullup)
  76. .ENDMACRO
  77.  
  78. .MACRO RGB_OFF
  79.     cbi PORTB,1
  80.     cbi PORTB,2
  81.     cbi PORTB,3
  82. .ENDMACRO
  83.  
  84. .MACRO RGB_ON
  85.     sbi PORTB,1
  86.     sbi PORTB,2
  87.     sbi PORTB,3
  88. .ENDMACRO
  89.  
  90. .MACRO PWM_CYCLE
  91.     ldi r17,@0          ;1
  92. PWM0:   RGB_OFF             ; 6
  93.     ldi r16,40          ; 1
  94. PWM1:   cp r16,R            ; 1
  95.     brne PWM2           ; 1/2
  96.     sbi PORTB,1         ; 2
  97. PWM2:   cp r16,G            ; 1
  98.     brne PWM3           ; 1/2
  99.     sbi PORTB,2         ; 2
  100. PWM3:   cp r16,B            ; 1
  101.     brne PWM4           ; 1/2
  102.     sbi PORTB,3         ; 2
  103. PWM4:   dec r16             ; 1
  104.     brne PWM1           ; 1/2 (805)*r17+6
  105.     dec r17             ; 1
  106.     brne PWM0           ; 1/2
  107.     RGB_OFF             ;6
  108. .ENDMACRO
  109.  
  110.  
  111.  
  112.  
  113.  
  114. ; Z A C A T E K   P R O G R A M U
  115. .org    0x0000              ;RESET
  116.     rjmp RESET          ;skok na start po resetu
  117.  
  118.  
  119. ; začátek kódu
  120. .org    0x0010
  121. RESET:  ldi r16,low(RAMEND)     ;nastaví stack pointer
  122.     out SPL,r16
  123.    
  124.     ldi r16,0b00011111      ;směr portu B - vše na výstup. Směr pinu n se bude měnit za chodu
  125.     out DDRB,r16
  126.     ldi r16,0b00000000      ;RGB=0b000, ledka zhasnuta
  127.     out PORTB,r16
  128.  
  129. ;tělo programu
  130.     clr R
  131.     clr G
  132.     clr B
  133. MainLoop:
  134.     rcall GET_T         ;teplota do SRAM 0x00-0x08
  135.  
  136.     cpi ARG, 0
  137.     brne MainLoop
  138.  
  139.     ;výpočet barvy
  140.     ldi ZH,SRAM_t_H         ;počátek řetězce přijatých bajtů do Z
  141.     ldi ZL,SRAM_t_L
  142.     ld tL,Z+            ;načíst teplotu z paměti
  143.     ld tH,Z
  144.     ldi r16,40
  145.     mov R,r16           ;defaultní barva - bílá, 40 40 40
  146.     mov G,r16
  147.     mov B,r16
  148.     ldi r16,0
  149.     cpse tH,r16         ;pokud tH != 0x00, skoč na mínus
  150.     rjmp MINUS
  151. ;PLUS nebo NULA
  152.     ldi r16,21          ;tL >= 10.5? --> c10_20
  153.     cp tL,r16
  154.     brge c10_20
  155.     ;0-blue,10-white
  156.     clr R
  157.     clr G
  158.     mov r16,tL
  159.     lsl r16
  160.     mov R,r16
  161.     mov G,r16
  162.     rjmp C_DONE
  163.    
  164. c10_20: ;10-white,20-yellow
  165.     ldi r16,41          ;tL >= 20.5? --> c20_30
  166.     cp tL,r16
  167.     brge c20_30
  168.    
  169.     mov r16,tL
  170.     subi r16,20
  171.     lsl r16
  172.     sub B,r16
  173.     rjmp C_DONE
  174.  
  175. c20_30: ;20-yellow,30-red
  176.     ldi r16,61          ;tL >= 30.5? --> c30_40
  177.     cp tL,r16
  178.     brge c30_40
  179.     clr B
  180.     mov r16,tL
  181.     subi r16,40
  182.     lsl r16
  183.     sub G, r16
  184.     rjmp C_DONE
  185.  
  186. c30_40: ;30-red, 40-purple
  187.     ldi r16,81          ;tL >= 40.5? --> c40_50
  188.     cp tL,r16
  189.     brge c40_50
  190.     clr B
  191.     clr G
  192.     mov r16,tL
  193.     subi r16,60
  194.     lsl r16
  195.     add B, r16
  196.     rjmp C_DONE
  197.  
  198. c40_50: ;40-purple, 50-"UV"
  199.     ldi r16,101         ;tL >= 50.5? --> c50_hi
  200.     cp tL,r16
  201.     brge c50_hi
  202.     clr G
  203.     mov r16,tL
  204.     subi r16,80
  205.     sub R, r16
  206.     rjmp C_DONE
  207.  
  208. c50_hi:
  209.     clr G
  210.     ldi r16,20
  211.     mov R,r16
  212.     rjmp C_DONE
  213.  
  214. MINUS:
  215.     neg tL
  216.     ldi r16,21          ;-tL >= 10.5? --> cm10_20
  217.     cp tL,r16
  218.     brge cm10_20
  219.     mov r16,tL
  220.     lsl r16
  221.     clr R
  222.     clr G
  223.     add G,r16
  224.     rjmp C_DONE
  225.  
  226. cm10_20:
  227.     ldi r16,41          ;-tL >= 20? --> cm20_lo
  228.     cp tL,r16
  229.     brge cm20_lo
  230.     clr R
  231.     mov r16,tL
  232.     subi r16,20
  233.     lsl r16
  234.     sub B,r16
  235.     rjmp C_DONE
  236.  
  237. cm20_lo:
  238.     clr R           ;-tL >= 20? --> cm40_lo
  239.     clr B
  240.     rjmp C_DONE
  241.    
  242. C_DONE:
  243.  
  244. ;   mov r16,R
  245. ;   ldi r17,11
  246. ;   rcall EEwrite
  247. ;   mov r16,G
  248. ;   ldi r17,12
  249. ;   rcall EEwrite
  250. ;   mov r16,B
  251. ;   ldi r17,13
  252. ;   rcall EEwrite
  253.  
  254. ;   ldi ZH, SRAM_t_H
  255. ;   ldi ZL, SRAM_t_L
  256. ;NextEE:    ld r16,Z
  257. ;   mov r17, ZL
  258. ;   rcall EEwrite
  259. ;   inc ZL
  260. ;   cpi ZL,2
  261. ;   brlo NextEE
  262.  
  263.     PWM_CYCLE 255
  264.  
  265.     rjmp MainLoop
  266.  
  267.  
  268.  
  269.  
  270.  
  271. ;G E T   T E M P E R A T U R E
  272. ;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.
  273. ;status je uložen do ARG (ARG == 0 -> CRC se shoduje, OK; ARG != 0 -> CRC se neshoduje, chyba přenosu)
  274. ;
  275. ;SRAM po vykonání procedury GET_T:
  276. ;   0x00    temperature low byte - unit: 0.5°C
  277. ;   0x01    temperature high byte (sign, 0x00 = positive, 0xff = negative)
  278. ;   0x02    "user byte 1"
  279. ;   0x03    "user byte 2"
  280. ;   0x04    reserved, 0xFF
  281. ;   0x05    reserved, 0xFF
  282. ;   0x06    count remain (default 0x0C)
  283. ;   0x07    count per °C (fixed to 0x10)
  284. ;   0x08    CRC
  285. ;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.
  286. GET_T:
  287.     push r17            ;ulož používané registry do STACKu
  288.  
  289.     rcall TxRESET           ;RESET
  290.     ldi ARG,0xCC            ;SKIP_ROM
  291.     rcall TxBYTE
  292.     ldi ARG,0x44            ;CONVERT_T
  293.     rcall TxBYTE
  294.     rcall W4C           ;čekej na konverzi teploty
  295.     rcall TxRESET           ;RESET
  296.     ldi ARG,0xCC            ;SKIP_ROM
  297.     rcall TxBYTE
  298.     ldi ARG,0xBE            ;READ_SCRATCHPAD
  299.     rcall TxBYTE
  300.  
  301.     ;přijmout 9 bajtů, uložit na 0x00 až 0x09 v SRAM
  302.     ldi ZH, SRAM_t_H
  303.     ldi ZL, SRAM_t_L
  304. NEXT_B: rcall RxBYTE            ;přijmi 1 bajt -> ARG
  305.    
  306. N_B3:   st Z+,ARG           ;do SRAM na adresu Z ulož výsledek. Z++
  307.     cpi ZL,9            ;je Z == 9?
  308.     brlo NEXT_B         ;je-li menší, čti další bajt
  309.    
  310.     ;vypočítat CRC, pokud se shoduje s přečtenou hodnotou, r16=1, jinak r16=0
  311.     ldi XH,SRAM_t_H
  312.     ldi XL,SRAM_t_L
  313.     ldi rCount,9
  314.     rcall CRC8
  315.     mov ARG,rCRC8
  316.    
  317.     pop r17
  318.     ret             ;návrat, ARG==0 .. ok, ARG!=0 .. error
  319.  
  320.  
  321. ;D E L A Y
  322. ; 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))
  323. DELAY:  nop
  324.     dec r16
  325.     brne DELAY
  326.     nop
  327.     ret ; po návratu je r16 = 0
  328.  
  329.  
  330.  
  331. ;R E S E T   P U L S E
  332. TxRESET:
  333.     BUS_L               ;stáhni sběrnici
  334.  
  335.     PWM_CYCLE 1
  336.     ;ldi r16,t480u
  337.     ;rcall DELAY            ;480us čekání
  338.  
  339.     BUS_H               ;uvolni sběrnici
  340.  
  341.     ldi r16,t70u
  342.     rcall DELAY         ;70us čekání
  343.  
  344.     sbic PINn,n
  345.     rjmp TxRESET            ;není-li presence pulse, zopakuj TxRESET
  346.  
  347.     ;ldi r16,t410u
  348.     ;rcall DELAY            ;410T čekání
  349.     PWM_CYCLE 1
  350.  
  351.     ret             ;návrat
  352.  
  353.  
  354. ;T R A N S M I T   B Y T E
  355. ; odešlou se data z ARG
  356. TxBYTE: ldi r17,8           ;čítač bytů = 8
  357. ;nový bit
  358. TxNB:   lsr ARG             ;nový bit; rotovat ARG: ARG.0 -> C
  359.     brcs Tx1            ;jednička - skok na Tx1, jinak pokračuj
  360.  
  361.                     ;-- Odeslání 0 --
  362.     BUS_L               ;stáhni sběrnici
  363.  
  364.     ldi r16,t60u
  365.     rcall DELAY         ;60us čekání
  366.  
  367.     BUS_H               ;uvolni sběrnici
  368.  
  369.     ldi r16,t10u
  370.     rcall DELAY         ;10us čekání
  371.  
  372.     rjmp TxLOOP         ;skok na konec rutiny
  373.  
  374.                     ;-- Odeslání 1 --
  375. Tx1:    BUS_L               ;stáhni sběrnici
  376.  
  377.     t6uDELAY            ;6us čekání
  378.  
  379.     BUS_H               ;uvolni sběrnici
  380.  
  381.     ldi r16,t64u
  382.     rcall DELAY         ;64us čekání
  383.  
  384. TxLOOP: dec r17             ;odečti 1 od čítače bitů
  385.     brne TxNB           ;zbývají bity? ano -> TxNB
  386.     ret             ;návrat
  387.  
  388.  
  389. ;R E C E I V E   B Y T E
  390. ; do ARG se uloží přečtený byte
  391. RxBYTE: ldi r17,8           ;čítač bitů
  392.     clr ARG             ;vymaž ARG
  393. ;nový bit
  394. RxNB:   rcall RxBIT
  395.  
  396.     ror ARG             ;rotuj ARG C[=PINB.n] -> ARG.7, ARG.0 -> C
  397.     dec r17             ;odečti 1 od čítače bitů
  398.     brne RxNB           ;zbývají bity? ano -> RxNB
  399.     ret             ;návrat
  400.  
  401.  
  402. ;R E C E I V E   S I N G L E   B I T
  403. RxBIT:  BUS_L               ;stáhni sběrnici
  404.  
  405.     t6uDELAY            ;6us čekání
  406.  
  407.     BUS_H               ;uvolni sběrnici
  408.  
  409.     ldi r16,t10u
  410.     rcall DELAY         ;10us čekání
  411.  
  412.     sbic PINn,n         ;PINB.n -> C
  413.     sec
  414.     sbis PINn,n
  415.     clc
  416.  
  417.     ldi r16,t54u
  418.     rcall DELAY         ;54us čekání
  419.     ret             ;návrat
  420.  
  421.  
  422. ;Č E K Á N Í   N A   D O K O N Č E N Í   K O N V E R Z E
  423. ;čekání na dokončení konverze teploty (nelze použít v parazitním režimu, v tom je třeba čekat 700ms.)
  424. W4C:    BUS_H
  425. ;až 700ms dlouhá čekací smyčka
  426. W4C0:   ldi r18,5
  427. W4C1:   PWM_CYCLE 200
  428.     dec r18
  429.     brne W4C1
  430.    
  431.     rcall RxBIT         ;přijmi bit do C.
  432.     brcc W4C0           ;C=0 -> čekej dál
  433.  
  434.     ret             ;návrat
  435.  
  436.  
  437. ;V Ý P O Č E T   C R C
  438. ;XH,XL,rCount --> rCRC8
  439. CRC8:   push    XH          ;save XH
  440.     push    XL          ;save XL
  441.     push    rChar           ;save rChar
  442.     push    rCount          ;save rCount
  443.     push    rBitCount       ;save rBitCount
  444.     push    rTemp           ;save rTemp
  445.  
  446.     clr rCRC8           ;start with a zero CRC-8
  447.  
  448.     ;begin loop to do each byte in the string
  449. CRC8BYT:
  450.     ld  rChar,X+        ;fetch next string byte and bump pointer
  451.     ldi rBitCount,8     ;load the bit-counter for this byte
  452.  
  453.     ;begin loop to do each bit in the byte
  454. CRC8BIT:
  455.     mov rTemp,rChar     ;get a temporary copy of current data
  456.     eor rTemp,rCRC8     ;XOR the data byte with the current CRC
  457.     lsr rCRC8           ;position to the new CRC
  458.     lsr rChar           ;position to next bit of this byte 
  459.     lsr rTemp           ;get low bit of old result into c-bit
  460.     brcc    CRC8NA          ;br if low bit was clear (no adjustment)
  461.     ldi rTemp,$8C       ;magical value needed for CRC-8s
  462.     eor rCRC8,rTemp     ;fold in the magic CRC8 value
  463. CRC8NA:
  464.     dec rBitCount       ;count the previous bit done
  465.     brne    CRC8BIT         ;br if not done all bits in this byte
  466.     ;end loop to do each bit in the byte
  467.  
  468.     dec rCount          ;count this byte done
  469.     brne    CRC8BYT         ;br if not done all bytes in the string
  470.     ;end loop to do each byte in the string
  471.  
  472.         pop rTemp           ;restore rTemp
  473.         pop rBitCount       ;restore rBitCount
  474.     pop rCount          ;restore rCount
  475.     pop rChar           ;restore rChar
  476.     pop XL          ;restore XL
  477.     pop XH          ;restore XH
  478.     ret             ;return to caller
  479. ;
  480. ;END OF SUBROUTINE CRC8
  481.  
  482.  
  483.  
  484.  
  485.  
  486.  
  487.  
  488.  
  489. ;cteni z EEPROM, v [r17 je ADRESA], v (r16 se objeví DATA)
  490. ;EEread:
  491. ;   sbic EECR,1
  492. ;   rjmp EEread         ;cekani dokud neni EEPROM ready
  493. ;
  494. ;   out EEARL, r17      ;ulozit adresu z r17
  495. ;   sbi EECR,0          ;nastavenim EERE zacina cteni
  496. ;   in r16,EEDR         ;cteni dat z EEDR do r16
  497. ;
  498. ;   ret
  499.  
  500.  
  501. ;zapis do EEPROM, v [R17 je ADRESA], v [R16 jsou DATA]
  502. EEwrite:
  503.     sbic EECR,EEPE
  504.     rjmp EEwrite            ;cekani dokud neni EEPROM ready
  505.  
  506.     cbi EECR,EEPM1          ;nastavit programovaci mod
  507.     cbi EECR,EEPM0
  508.  
  509.     out EEARL, r17          ;dej adresu z r17 do EEARL
  510.     out EEDR, r16           ;dej data z r16 do EEDR
  511.     sbi EECR,EEMPE          ;master program enable
  512.     sbi EECR,EEPE           ;program enable
  513.  
  514.     ret
Advertisement
Add Comment
Please, Sign In to add comment