domenica 6 giugno 2010

Progr x PIC - Telestart lato arrivo

;cronometro per gare di atletica
;26/05/08
;PIC16F648A
;clock 4 MHz INTOSC (oscillatore interno)
;
;stand-by: led rosso acceso
;
;RadioStart:    riconoscimento con comparatori interni
;
;crono run: base dei tempi 1 millisecondo, no interrupt
; flash 0.5Hz su led verde
;
;crono stop: fotocellula
;
;crono reset: reset di sistema (pulsante)
;
;display LCD: formato h:mm:ss:dcm
; overflow a 2:00:00:000 (2 ore)
; risoluzione 1 millisecondo

;definizioni sfr

status equ 03h
trisa equ 85h
trisb equ 86h
porta equ 05h
portb equ 06h
cmcon equ 01fh

;definizione gpr

millesimi equ 20h
centesimi equ 21h
decimi equ 22h
secondi equ 23h
decsec equ 24h
min equ 25h
decmin equ 26h
ore equ 27h
ContaMicro equ 28h
millis equ 29h

org 2ah

tmpLcdRegister  res     2
msDelayCounter  res     2

;Linee di controllo dell'LCD

LCD_RS          equ     2       ;Register Select
LCD_E           equ     3       ;Lcd Enable

;LCD data line bus

LCD_DB4         equ     4       ;LCD data line DB4
LCD_DB5         equ     5       ;LCD data line DB5
LCD_DB6         equ     6       ;LCD data line DB6
LCD_DB7         equ     7       ;LCD data line DB7

;macro per LCD

SET_EN        MACRO
                bsf  PORTB,LCD_E
              ENDM

CLEAR_EN      MACRO
                bcf  PORTB,LCD_E
              ENDM

EN_STROBE MACRO
                SET_EN
                nop
                CLEAR_EN
              ENDM

errorlevel 2

org 0

;direzione pin: ra0, ra1, ra2 in input
; rb0, rb1 in output

resetta bsf status,5
bsf trisa,0 ;ra0 in input
bsf trisa,1 ;ra1 in input
bsf trisa,2 ;ra2 in input
clrf trisb
bcf status,5

;inizializzazione modulo comparatori
;comparatori connnessi con: RA2 = Vin+ in comune
; RA0 = Vin- comp1
; RA1 = Vin- comp2

movlw 03h
movwf cmcon

;inizializza variabili cronometro a zero

clrf millesimi
clrf centesimi
clrf decimi
clrf secondi
clrf decsec
clrf min
clrf decmin
clrf ore

;Inizializza il display LCD

                call    LcdInit

;Posiziona il cursore dell'LCD in posizione 0,0

                movlw   0x00
                call    LcdLocate

;LCD, visualizza zero (reset)

call visualizzatempo

;entra stand-by: accendi rosso, spegni verde

bcf portb,1
bsf portb,0 ;rosso

;attesa di un radiostart

RxStart btfss cmcon,6 ;RxStart>VS1(3.1V)?
goto RxStart ;no, attendi per...

;radiostart rilevato, misura il semip. alto

treno1000Hz clrf ContaMicro
contaalto incf ContaMicro
btfsc cmcon,7 ;RxStart<VS2(1.9V)?
goto contaalto ;no, misura semip. alto

;semip. alto misurato, verifica se 1000 o 1500Hz

movlw .100
subwf ContaMicro
btfss status,0
goto cronostart ;è 1500, vai a gestire cronometro

;è 1000Hz,misura il semip. basso

clrf ContaMicro
contabasso incf ContaMicro
btfss cmcon,6 ;RxStart>VS1(3.1V)?
goto contabasso ;no, misura semip. basso

;semip. basso misurato, verifica se 1000 o 1500Hz

movlw .100
subwf ContaMicro
btfss status,0
goto cronostart ;è 1500, vai a gestire cronometro
goto treno1000Hz ;è 1000, ricomincia da capo

;CRONOSTART: precarica cronometro con 1 secondo

cronostart bsf secondi,0

;fine stand-by, modo RUN

bsf portb,1 ;modo RUN, accendi verde
bcf portb,0

;chiama base dei tempi da 1 millisecondo

cronorun call millisecondo

;polling fotocellula STOP

btfss porta,3
goto cronostop

;conta millesimi in bcd n.i.

incf millesimi
movlw .10
subwf millesimi,0
btfss status,2
goto cronorun
clrf millesimi

;conta centesimi in bcd n.i.

incf centesimi
movlw .10
subwf centesimi,0
btfss status,2
goto cronorun
clrf centesimi

;conta decimi in bcd n.i.

incf decimi
movlw .10
subwf decimi,0
btfss status,2
goto cronorun
clrf decimi

;conta secondi in BCD n.i.

incf secondi
;flash 0.5Hz su led verde
btfss secondi,0
goto spegni
bsf portb,1
goto BCD_sec
spegni bcf portb,1
BCD_sec movlw .10
subwf secondi,0
btfss status,2
goto cronorun
clrf secondi

;conta decsec in bcd n.i.

incf decsec
movlw .6
subwf decsec,0
btfss status,2
goto cronorun
clrf decsec

;conta minuti in bcd n.i.

incf min
movlw .10
subwf min,0
btfss status,2
goto cronorun
clrf min

;conta decmin in bcd n.i.

incf decmin
movlw .6
subwf decmin,0
btfss status,2
goto cronorun
clrf decmin

;conta ore in bcd n.i.

incf ore
movlw .2
subwf ore,0
btfss status,2
goto cronorun
clrf ore

;OVERFLOW, resetta il sistema

goto resetta

;STOP CRONOMETRO FOTOCELLULA

cronostop bsf portb,0 ;STAND-BY, accendi rosso
bcf portb,1

;Posiziona il cursore dell'LCD in posizione 0,0

                movlw   0x00
                call    LcdLocate

;visualizza tempo finale su LCD
;converti variabili cronometro da BCD n.i. in ASCII --> LCD

call visualizzatempo

;loop infinito, attesa per un reset

loop goto loop

;FINE MAIN, inizio procedure

;routine millisecondo

millisecondo movlw .246
movwf millis
nop
nop
ciclo1 nop
decfsz millis
goto ciclo1
return

;*****************************************************************************
 
                INCLUDE         "P16F84.INC"

;procedura conversione BCD n.i. in ASCII e stampa tempo su LCD

visualizzatempo movfw ore
addlw 30h
                call    LcdSendData

movlw ':'
call LcdSendData

                movfw   decmin
addlw 30h
                call    LcdSendData

                movfw   min
addlw 30h
                call    LcdSendData

movlw ':'
call LcdSendData

                movfw   decsec
addlw 30h
                call    LcdSendData

                movfw   secondi
addlw 30h
                call    LcdSendData

movlw ':'
call LcdSendData

                movfw   decimi
addlw 30h
                call    LcdSendData

                movfw   centesimi
addlw 30h
                call    LcdSendData

                movfw   millesimi
addlw 30h
                call    LcdSendData

return

;**********************************************************************
; Routine di ritardo
;
; W = Ritardo richiesto in ms (con quarzo a 4MHz)
;**********************************************************************

msDelay
                movwf   msDelayCounter+1
                clrf    msDelayCounter+0

                ; Loop interno da circa 1 ms
msDelayLoop
                nop
                decfsz  msDelayCounter+0
                goto    msDelayLoop
                nop

                decfsz  msDelayCounter+1
                goto    msDelayLoop

                return

;**********************************************************************
; Inizializza il display LCD
; Questa funzione deve essere chiamata prima di ogni altra funzione
; di gestione dell'LCD
;**********************************************************************

LcdInit
                bcf     portb,LCD_E     ;Disabilita l'LCD
                bcf     portb,LCD_RS    ;Mette l'LCD in modo comando

                movlw   250
                call    msDelay

                movlw   250
                call    msDelay

                movlw   250
                call    msDelay

                movlw   250
                call    msDelay


                ; Invia all'LCD la sequenza di reset


                bsf     portb,LCD_DB4
                bsf     portb,LCD_DB5
                bcf     portb,LCD_DB6
                bcf     portb,LCD_DB7

                EN_STROBE

                movlw   2
                call    msDelay

                EN_STROBE

                movlw   2
                call    msDelay

                EN_STROBE

                movlw   2
                call    msDelay

;--------------------------------

                bcf     portb,LCD_DB4
                bsf     portb,LCD_DB5
                bcf     portb,LCD_DB6
                bcf     portb,LCD_DB7

                EN_STROBE

                movlw   2
                call    msDelay

                ;Configura il bus dati a 4 bit

                movlw   0x28
                call    LcdSendCommand

                ;Entry mode set, increment, no shift

                movlw   0x06
call    LcdSendCommand

                ;Display ON, Curson OFF, Blink OFF

                movlw   0x0E
                call    LcdSendCommand

                movlw   0x01
                call    LcdSendCommand

                return


;**********************************************************************
; Clear LCD
;**********************************************************************

LcdClear
                movlw   0x01
                call    LcdSendCommand

                movlw   2
                call    msDelay

                ;DD RAM address set 1st digit

                movlw   0x80
                call    LcdSendCommand

                return

;**********************************************************************
; Locate cursor on LCD
; W = D7-D4 row, D3-D0 col
;**********************************************************************

LcdLocate
                movwf   tmpLcdRegister+0

                movlw   0x80
                movwf   tmpLcdRegister+1

                movf    tmpLcdRegister+0,0
                andlw   0x0F
                iorwf   tmpLcdRegister+1

                btfsc   tmpLcdRegister+0,4
                bsf     tmpLcdRegister+1,6

                movf    tmpLcdRegister+1,0
                call    LcdSendCommand

                return


;**********************************************************************
; Send a data to LCD
;**********************************************************************

LcdSendData

                bsf     portb,LCD_RS
                call    LcdSendByte
                return

;**********************************************************************
; Send a command to LCD
;**********************************************************************

LcdSendCommand
                bcf     portb,LCD_RS
                call    LcdSendByte
                return

;**********************************************************************
; Send a byte to LCD by 4 bit data bus
;**********************************************************************

LcdSendByte
                ;Save value to send

                movwf   tmpLcdRegister

                ;Invia i quattro bit piu' significativi

                bcf     portb,LCD_DB4
                bcf     portb,LCD_DB5
                bcf     portb,LCD_DB6
                bcf     portb,LCD_DB7

                btfsc   tmpLcdRegister,4
                bsf     portb,LCD_DB4
                btfsc   tmpLcdRegister,5
                bsf     portb,LCD_DB5
                btfsc   tmpLcdRegister,6
                bsf     portb,LCD_DB6
                btfsc   tmpLcdRegister,7
                bsf     portb,LCD_DB7

                EN_STROBE

                movlw   2
                call    msDelay

                ;Send lower four bits

                bcf     portb,LCD_DB4
                bcf     portb,LCD_DB5
                bcf     portb,LCD_DB6
                bcf     portb,LCD_DB7

                btfsc   tmpLcdRegister,0
                bsf     portb,LCD_DB4
                btfsc   tmpLcdRegister,1
                bsf     portb,LCD_DB5
                btfsc   tmpLcdRegister,2
                bsf     portb,LCD_DB6
                btfsc   tmpLcdRegister,3
                bsf     portb,LCD_DB7

                EN_STROBE

                movlw   2
                call    msDelay

                return

                END

Nessun commento: