23
;************************************************** ; Relógio digital LCD com PIC v1.1 ; PICrelogiodigitalasm.txt ; ; (c) 2002 Elias Jahn ; ([email protected]) ; http://xelectronicax.no.sapo.pt ;************************************************** PROCESSOR 16F84A RADIX DEC INCLUDE "p16f84a.inc" ERRORLEVEL -302 ;os bits de configuração do PIC a ser programado tem que ser ajustados no seu programador para: ;POWERUPTIMER: ENABLED (1) ;WATCHDOGTIMER: ENABLED (1) ;CODE PROTECT: DISABLED (0) ;OSCILLATOR: XT Digit3 EQU 4 Digit2 EQU 5 Digit1 EQU 6 Digit0 EQU 7 Mode EQU 0 Hr EQU 1 Min EQU 2 Stp EQU 4 Out EQU 3 Counterm EQU 5 ;definição dos bits para os modos com nomes... Alarm EQU 4 Settime EQU 3 Cntdn EQU 2 Stpw EQU 1 Ck EQU 0 ORG 0Ch Value RES 4 ;variavel que vai ficar com o valor de cada digito que é para ser mostrado no display Idle RES 2 ;variavel usada para fazer um efeito de "estado de espera" quando uma tecla foi premida Loopc RES 3 Loopd RES 2 Modus RES 1 ;variavel que diz, dependendo de qual o bit que está em 1, qual o Modo -> os modos para cada Bit: veja acima

Relógio digital LCD com PIC v1

  • Upload
    ritoca

  • View
    457

  • Download
    1

Embed Size (px)

Citation preview

Page 1: Relógio digital LCD com PIC v1

;**************************************************; Relógio digital LCD com PIC v1.1; PICrelogiodigitalasm.txt;; (c) 2002 Elias Jahn; ([email protected]); http://xelectronicax.no.sapo.pt;**************************************************

PROCESSOR 16F84A RADIX DEC INCLUDE "p16f84a.inc" ERRORLEVEL -302

;os bits de configuração do PIC a ser programado tem que ser ajustados no seu programador para:

;POWERUPTIMER: ENABLED (1);WATCHDOGTIMER: ENABLED (1);CODE PROTECT: DISABLED (0);OSCILLATOR: XT

Digit3 EQU 4Digit2 EQU 5Digit1 EQU 6Digit0 EQU 7

Mode EQU 0Hr EQU 1Min EQU 2Stp EQU 4Out EQU 3

Counterm EQU 5 ;definição dos bits para os modos com nomes...Alarm EQU 4 Settime EQU 3Cntdn EQU 2Stpw EQU 1Ck EQU 0

ORG 0ChValue RES 4 ;variavel que vai ficar com o valor de cada digito que é para ser mostrado no displayIdle RES 2 ;variavel usada para fazer um efeito de "estado de espera" quando uma tecla foi premidaLoopc RES 3 Loopd RES 2Modus RES 1 ;variavel que diz, dependendo de qual o bit que está em 1, qual o Modo -> os modos para cada Bit: veja acimaTime RES 6 ;vai conter a hora (+0 = Segundos, +1 = dezenas segundos, +2 = minutos, etc...)Stpwtime RES 6 ;vai conter a hora do stopwatch (min, hr, etc: como Time)Cdntime RES 4 ;vai conter a "hora" da contagem decrescente (+0 = segundos, +1 = dezenas segundos, +2 = minutos, e assim em diante)Alarmtime RES 4 ;vai conter a hora de alarme (+0 = minutos, +1 = dezenas minutos, +2 = horas, etc.)Stpwstat RES 1 ;Estado do Stopwatch: Bit 0 = 0: parado, Bit 0 = 1: a contar,

Page 2: Relógio digital LCD com PIC v1

;Bit 1 = 0: não em zero, Bit 1 = 1 em zero

;Bit 2 = 0: mostrar segundos e minutos, Bit 2 = 1: Horas e minutos (este bit tb vale para o relogio normal)Cdnstat RES 1 ;Estado do Countdown: Bit 0 = 0: parado, Bit 0 = 1: a contar,Alarmstat RES 1 ;Estado do Alarme: Bit 0 = 0: alarme não activado, Bit 0 = 1: alarme activado, Bit 1 = 0: não há alarme, Bit 1 = 1: há alarmeAlarmcnt RES 1 ;"contador" para ver se alarme de 60 segundos chegou ao fimCounterstat RES 1 ;Estado do contador: Bit 0 = 0: contar para cima, Bit 0 = 1: contar para baixo Bit1 = 0: inibido de contar por já ter contado o impulso, Bit1 = 1: já pode contarCounter RES 4 ;vai conter o valor do contador universal crescente/decrescenteZero RES 1 ;é para saber se algum dos digitos do countdown estiver em zeroCounterzero RES 1 ;é para saber se algum dos digitos do contador estiver em zero

wtemp RES 1statustemp RES 1Timervalue RES 1 ;variavel para efeitos de ajuste da precisão do relogioCompensate RES 1 ;variavel para efeitos de ajuste da precisão do relogioCompensating RES 1 ;variavel para efeitos de ajuste da precisão do relogio

ORG 00h goto begin ;vai para o inicio do programa

ORG 04h ;se houver um interrupt, o programa salta para aqui

goto Ints ;e pula até a marca "Ints" ;estas são as subrotinas do programa que são chamados no

programa principal e que se encarreguem de fazer aparecer os numeros no display de forma multiplexada e com ajuda duma tabela, claro..Displaydelay ;rotina de delay para o display movlw 255

movwf Loopc movlw 8 movwf Loopc+1

Loopit decfsz Loopc,F

goto Loopit decfsz Loopc+1,F goto Loopit return

TheDigit0 ;aqui vai o truque do display multiplexado movf Value,W

call Table ;ver na tabela qual o valor para as saidas... movwf PORTB ;por este nas saidas

bcf PORTB,Digit0 ;ligar digito 0

Page 3: Relógio digital LCD com PIC v1

bsf PORTB,Digit3 ;desligar digito 3 e assim em diante...

bsf PORTB,Digit2 bsf PORTB,Digit1 return

TheDigit1 movf Value+1,W call Table movwf PORTB

bcf PORTB,Digit1 bsf PORTB,Digit0 bsf PORTB,Digit2 bsf PORTB,Digit3 return

TheDigit2 movf Value+2,W call Table

movwf PORTB bcf PORTB,Digit2 bsf PORTB,Digit1 bsf PORTB,Digit3 bsf PORTB,Digit0

returnTheDigit3

movf Value+3,W call Table

movwf PORTB bcf PORTB,Digit3 bsf PORTB,Digit2 bsf PORTB,Digit1 bsf PORTB,Digit0

return

Table ;Tabela addwf PCL,1 ;o truque conhecido retlw B'00000000' ;return with literal in W retlw B'00001000' retlw B'00000100' retlw B'00001100' retlw B'00000010' retlw B'00001010' retlw B'00000110' retlw B'00001110' retlw B'00000001' retlw B'00001001'

Ints ;16 us para o contador contar +1, quando estiver em FFh e mudar para ;00h acontece uma interrupção, isso tudo dá no total 4,096 ms.

;Mas como precisamos de 1 segundo e não 4,096 ms, vamos deixar acontecer

;a interrupção 244 vezes (= 999,424 ms. Essas 244 vezes conta-se com a variavel Timervalue).

;Mas como a precisão ainda não chega, temos que usar 245 (que dá 1003,52 ms)

;após termos usado 6 vezes 244... (dá: 6 * 999,424 = 5996,544 ms + 1 * 1003,52 = 7000,064. Isto é a teoria.

Page 4: Relógio digital LCD com PIC v1

;Mas na prática é diferente: como as instruções da ISR e tudo o mais adicionadas dão alguns segundos por dia, temos que improvisar...

;Fazemos isso usando o valor 8 em vez de 6 para Compensate, ou seja, ficamos com as contas: 8 * 999,424 = 7995,392 + 1 * 1003,52 = 8998,912.

;Eu testei este valor exaustivamente e cheguei á conclusão que com estes valores todos (prescaler=16, 244 * 8, 245 * 1) o relógio em 24 horas apenas se adianta em 4 segundos. Portanto +4 segundos por dia. Isso é bastante bom. Mas para compensar isso, fiz o seguinte:

; implementei uma rotina que verifica se após chegar aos 00:00:00 os segundos já estão em 4 e se sim, faz os regressar a 00, o que faz com que o relógio tenha uma precisão quase total medido em 24 horas.

;se alguem for capaz de conseguir aumentar a precisão, de modo a que esta correcção de 4 segundos se torna desnecessaria,

;usando por exemplo valores diferentes de FFh para carregar o TMR (é que não o carrego, deixo o correr...), que me envie o programa alterado fazfavor, já que até agora ainda não fui capaz de conseguir isso...

;(é que há aquele problema de o contador não contar durante umas vezes após se ter carregado um valor nele, e não consegui calcular isso tudo ;-)

movwf wtemp ;guarda os valores do W e do

STATUS para uso após o interrupt.. swapf STATUS,W movwf statustemp

btfss INTCON,T0IF ;interrupt do timer0?? goto exitint ;não??!! que é isso! não deve

haver outra interrupção pra além da do timer, mas pronto, pode haver esta excepção por causa de alguma falha de sistema, e temos que estar preparados para isso...

decfsz Timervalue,F ;decrementa timervalue e vê se já

chegamos ao valor devido (244) goto exitint decfsz Compensate,F ;decrementa a tal "compensação

das 8 vezes" goto Notyet movlw 8 ;é tempo! bora lá usar 245 movwf Compensate movlw 245 movwf Timervalue goto Yet

Notyet ;vamos usar 244, claro

movlw 244 movwf Timervalue

Yet btfsc Modus,Settime ;aqui começa a sério...!! estamos

no modo de ajuste do relogio? é que ai o relogio n deve avançar... goto Stopwatch

incf Time,F ;não? ok, então bora lá incrementar os segundos, minutos, horas, etc... é o que fazem as seguintes instruções todas, só vou explicar uma, as outras são iguais

movf Time,W ;Time -> W sublw 10 ;W - 10 = ?

Page 5: Relógio digital LCD com PIC v1

btfss STATUS,Z ;0? então: goto checkitout ;não 0, sai daqui movlw 0 ;sim, foi 0, continua, Time = 0 movwf Time incf Time+1,F ;incrementa Time+1 movf Time+1,W sublw 6 btfss STATUS,Z goto checkitout movlw 0 movwf Time+1 incf Time+2,F movf Time+2,W sublw 10 btfss STATUS,Z goto verify movlw 0 movwf Time+2 incf Time+3,F movf Time+3,W sublw 6 btfss STATUS,Z goto verify movlw 0 movwf Time+3 incf Time+4,F movf Time+4,W sublw 4 btfss STATUS,Z goto Normalclock movf Time+5,W sublw 2 btfsc STATUS,Z goto Zeroclock

Normalclock movf Time+4,W

sublw 10 btfss STATUS,Z goto verify movlw 0 movwf Time+4 incf Time+5,F

goto verifyZeroclock ;chegou a vinte e quatro horas, tem q ser posto em 00:00 horas movlw 0

movwf Time+4 movwf Time+5 btfsc Cdnstat,0 goto verify ;isso aqui é para verificar se

o countdown está a contar, se sim, não há necessidade de corrigir 4 segundos por dia, pois este "atrasa" o relógio um bocado...

bsf Compensating,0 ;á partir de agora é para vigiar os segundos, para ver quando chegarem á 4...

goto verifycheckitout btfss Compensating,0

goto verify movlw 4 ;os segundos chegaram á 4? subwf Time,W btfss STATUS,Z

Page 6: Relógio digital LCD com PIC v1

goto verify movlw 0 ;sim? então põe os em 00 movwf Time movwf Time+1 bcf Compensating,0 goto verify

verify ;isso aqui tem tudo a ver com o alarme...

btfsc Modus,Cntdn goto Stopwatch btfsc Alarmstat,1 ;houve alarme?? goto Alarmed ;se sim, vamos para "Alarmed" btfss Alarmstat,0 ;não? mas, será que o alarme

pelo menos está activado? goto Stopwatch ;não? então já não há nada

mais que fazer cá movf Time,W ;estas cenas servem para ver

se tamos na hora do alarme sublw 0 btfss STATUS,Z goto Stopwatch movf Alarmtime,W subwf Time+2,W btfss STATUS,Z goto Stopwatch movf Alarmtime+1,W subwf Time+3,W btfss STATUS,Z goto Stopwatch movf Alarmtime+2,W subwf Time+4,W btfss STATUS,Z goto Stopwatch movf Alarmtime+3,W subwf Time+5,W btfss STATUS,Z goto Stopwatch

bsf PORTA,Out ;tá na hora!! bora lá fazer soar o alarme

movlw 60 ;mas apenas durante 60 segundos

movwf Alarmcnt bcf Alarmstat,0 ;não,agora não pode haver

alarme activado, já que estamos em pleno alarme... bsf Alarmstat,1 ;alarme!!! ;)

Alarmed decfsz Alarmcnt,F ;vai-se aqui se há alarme, decrementar Alarmcnt e ver se os 60 segundos chegaram ao fim...

goto Stopwatch bcf PORTA,Out ;alarme, pâra de soar! bsf Alarmstat,0 ;alarme activado outra vez bcf Alarmstat,1 ;mas já não há alarme

Stopwatch ;estas são as cenas relacionadas com o cronômetro

btfss Stpwstat,0 ;está parado ou a contar? goto Countdown

incf Stpwtime,F ;se está a contar, continua aqui, e incrementa a hora do cronometro

movf Stpwtime,W sublw 10 btfss STATUS,Z

Page 7: Relógio digital LCD com PIC v1

goto Countdown movlw 0 movwf Stpwtime incf Stpwtime+1,F movf Stpwtime+1,W sublw 6 btfss STATUS,Z goto Countdown movlw 0 movwf Stpwtime+1 incf Stpwtime+2,F movf Stpwtime+2,W sublw 10 btfss STATUS,Z goto Countdown movlw 0 movwf Stpwtime+2 incf Stpwtime+3,F movf Stpwtime+3,W sublw 6 btfss STATUS,Z goto Countdown movlw 0 movwf Stpwtime+3 incf Stpwtime+4,F movf Stpwtime+4,W sublw 4 btfss STATUS,Z goto Normalstpw movf Stpwtime+5,W sublw 2 btfsc STATUS,Z goto Zerostpw

Normalstpw movf Stpwtime+4,W

sublw 10 btfss STATUS,Z goto Countdown movlw 0 movwf Stpwtime+4 incf Stpwtime+5,F

goto CountdownZerostpw

movlw 0 movwf Stpwtime+4 movwf Stpwtime+5

;aqui vem as cenas da contagem decrescenteCountdown btfss Cdnstat,0

goto exitint btfsc Zero,0 ;digito 0 tá em zero??

goto Zero1 ;então vai para Zero1 decfsz Cdntime,F ;não? então decrementa goto exitint ;se não está zero, sai daqui bsf Zero,0 ;está zero? então Zero(+0) = 1 goto exitint Zero1 btfsc Zero,1 ;e o digito 1?? está em zero tambem? goto SecondZero ;sim, então checke isso

Page 8: Relógio digital LCD com PIC v1

bcf Zero,0 ;não? então este digito 0 já vai deixar de estar em zero, por isso Zero(+0) = 0 movlw 9 ;depois do zero vem o que? resposta: nove! ;-) movwf Cdntime decfsz Cdntime+1,F ;decrementa o outro digito!! goto exitint bsf Zero,1 ;mas n me digas que está em zero já! Zero,1 = 1 goto exitintSecondZero btfsc Zero,2 ;bem, dois digitos já estão em zero, falta ver o terceiro goto ThirdZero ;tambem?! bcf Zero,0 bcf Zero,1 movlw 9 ;e como dois digitos estavam em zero... vamos pô-los em em 59 movwf Cdntime

movlw 5 movwf Cdntime+1 decfsz Cdntime+2,F ;e decrementar o terceiro digito goto exitint bsf Zero,2 ;já tá em zero?! então Zero,2 = 1 goto exitintThirdZero btfsc Zero,3 ;e o ultimo digito? já tá em zero?

goto Fourthzero bcf Zero,0 bcf Zero,1

bcf Zero,2 movlw 9 ;os outros tem que ficar com x9:59 movwf Cdntime movwf Cdntime+2 movlw 5

movwf Cdntime+1 decfsz Cdntime+3,F ;decrementa o quarto digito goto exitint bsf Zero,3 ;zero! goto exitint

Fourthzero bcf Cdnstat,0 ;acabou-se, tá tudo em zero!

bsf PORTA,Out ;faz explodir a bomba que está ligada ao Out (tou a brincar!!!, ahahahaha) ;-))

goto exitint exitint

bcf INTCON,T0IF ;acabou se o interrupt do timer bsf INTCON,T0IE ;mas volta a permitir novas

interrupções

swapf statustemp,W ;restauração dos valores antigos para o W e status

movwf STATUS swapf wtemp,F swapf wtemp,W retfie ;sai da interrupção e volta para o

sitio do programa normal onde aconteceu a interrupção

Page 9: Relógio digital LCD com PIC v1

begin ;aqui começa o programa normal finalmente!

bcf STATUS,RP0 ;preparar as cenas... clrf TMR0 bsf STATUS,RP0 movlw B'00010111' ;configura PORTA movwf TRISA movlw B'00000000' ;configura PORTB movwf TRISB clrwdt ;Procedimento necessario para não

haver resets continuos... movlw B'00000011' ;prescaler do tmr0 = 16 movwf OPTION_REG movlw B'00100000' movwf INTCON bcf STATUS,RP0

bsf PORTB,Digit0 ;display desligado bsf PORTB,Digit1 bsf PORTB,Digit2 bsf PORTB,Digit3 bcf PORTA,Out movlw 0 movwf Idle ;inicializar as variaveis todas... movwf Value movwf Value+1 movwf Stpwtime movwf Stpwtime+1 movwf Stpwtime+2 movwf Stpwtime+3 movwf Stpwtime+4

movwf Stpwtime+5 movwf Cdntime movwf Cdntime+1 movwf Cdntime+2 movwf Cdntime+3 movwf Alarmtime movwf Alarmtime+1 movwf Alarmtime+2 movwf Alarmtime+3 movwf Counter movwf Counter+1 movwf Counter+2 movwf Counter+3 movwf Time movwf Time+1 movwf Time+2 movwf Time+3 movlw 2 ;com 12:00 Horas no relogio.

Aliás, quem é que perguntou certa vez porque é que todos os relógios começam sempre em 12:00? Bem, deve ser, porque quem fez o primeiro relogio digital tava com falta de imaginação... e toda a gente depois imitou-o... incluindo-me a mim, ehehe!!

movwf Value+2 movwf Time+4 movlw 1 movwf Time+5 movwf Value+3 movlw B'00000001' ;e modo "Ck" (relogio) movwf Modus bcf Idle+1,0

Page 10: Relógio digital LCD com PIC v1

bcf Stpwstat,0 bsf Stpwstat,1 bcf Cdnstat,0 bsf Zero,0 bsf Zero,1 bsf Zero,2 bsf Zero,3 bsf Counterzero,0 bsf Counterzero,1 bsf Counterzero,2 bsf Counterzero,3 bcf Stpwstat,2 bcf Alarmstat,0 bcf Counterstat,0 bcf Compensating,0 movlw 0 movwf Alarmcnt movlw 244 movwf Timervalue movlw 8 movwf Compensate bcf Alarmstat,1 bsf INTCON,GIE ;desinibir interrupts bsf INTCON,T0IE ;desinibir interrupt do TMR0 clrf TMR0 ;resetar tmr0 , isto é, a partir

daqui o relogio começa a "funcionar"Main

call TheDigit0 ;estas cenas fazem aparecer os numeros no display

call Displaydelay call TheDigit1 call Displaydelay call TheDigit2 call Displaydelay

call TheDigit3 call Displaydelay

Clockmode btfss Modus,Settime ;estamos no modo de ajuste do relogio?

goto Whatever bcf Stpwstat,2 ;se sim, convém estarmos a mostrar

horas e minutos, e não segundos e minutosWhatever btfsc Modus,Stpw ;será que estamos no modo do cronometro?

goto Stopwmode btfsc Modus,Cntdn ;ou no do countdown? goto Countdmode btfsc Modus,Alarm ;ou no do alarme? goto Alarmmode btfsc Modus,Counterm ;ou no do contador? goto Countermode btfsc Stpwstat,2 ;então só podemos estar no modo do

relógio! mas se eles querem segundos e minutos, vamos para outro lado goto Showseconds movf Time+2,W ;não? então por os valores da hora

e dos minutos nos variaveis que são mostrados no display depois movwf Value movf Time+3,W movwf Value+1 movf Time+4,W

Page 11: Relógio digital LCD com PIC v1

movwf Value+2 movf Time+5,W movwf Value+3 goto Gohere

Showseconds ;por os valores dos segundos e minutos nos variaveis que são mostrados no display movf Time,W

movwf Value movf Time+1,W movwf Value+1 movf Time+2,W movwf Value+2 movf Time+3,W movwf Value+3 goto Gohere

Alarmmode ;por os valores do alarme nos variaveis que são mostrados no display movf Alarmtime,W

movwf Value movf Alarmtime+1,W movwf Value+1 movf Alarmtime+2,W movwf Value+2 movf Alarmtime+3,W movwf Value+3 goto Gohere

Stopwmode ;por os valores do stopwatch nos variaveis que são mostrados no display

btfsc Stpwstat,2 goto Moredigits movf Stpwtime,W movwf Value movf Stpwtime+1,W movwf Value+1 movf Stpwtime+2,W movwf Value+2 movf Stpwtime+3,W movwf Value+3 goto Gohere

Moredigits ;fazer isso se é para mostrar horas e minutos e não segundos e minutos... movf Stpwtime+2,W

movwf Value movf Stpwtime+3,W movwf Value+1 movf Stpwtime+4,W movwf Value+2 movf Stpwtime+5,W movwf Value+3 goto Gohere

Countdmode ;por os valores do countdown nos variaveis que são mostrados no display movf Cdntime,W

movwf Value movf Cdntime+1,W movwf Value+1 movf Cdntime+2,W

Page 12: Relógio digital LCD com PIC v1

movwf Value+2 movf Cdntime+3,W movwf Value+3 goto Gohere

Makeitclear bsf Counterstat,1

goto FinishCountermode ;ai estamos no modo do contador? pois, neste caso tudo é diferente.. btfsc PORTA,Stp ; então vê se há sinal...

goto Makeitclear ;não? então da proxima já se pode contar!

btfss Counterstat,1 ;podemos contar este impulso, ou já foi contado?

goto Finish ;já foi, por isso sai daqui bcf Counterstat,1 ;ainda não foi, por isso continua

e Counterstat,1=0 para dizer que já foi contado btfsc Counterstat,0 ;para cima ou para baixo? goto Down

bcf Counterzero,0 ;a partir daqui vão as instruções para contar para cima

incf Counter,F movf Counter,W sublw 10 btfss STATUS,Z goto Finish bsf Counterzero,0 movlw 0 movwf Counter bcf Counterzero,1 incf Counter+1,F movf Counter+1,W sublw 10 btfss STATUS,Z goto Finish bsf Counterzero,1 movlw 0 movwf Counter+1 bcf Counterzero,2 incf Counter+2,F movf Counter+2,W sublw 10 btfss STATUS,Z goto Finish bsf Counterzero,2 movlw 0 movwf Counter+2 bcf Counterzero,3 incf Counter+3,F movf Counter+3,W sublw 10 btfss STATUS,Z goto Finish bsf Counterzero,3 bsf Counterzero,2 bsf Counterzero,1 bsf Counterzero,0 movlw 0 movwf Counter movwf Counter+1

Page 13: Relógio digital LCD com PIC v1

movwf Counter+2 movwf Counter+3 goto Finish

Down ;e a partir daqui para contar para baixo btfsc Counterzero,0 ;digito 0 (mais direito) tá em zero?? goto CounterZero1 ;então vai para CounterZero1 decfsz Counter,F ;não? então decrementa goto Finish ;se não está zero, volta ao inicio bsf Counterzero,0 ;está zero? então Counterzero,0 = 1 goto Finish CounterZero1 btfsc Counterzero,1 ;e o digito 1?? está em zero tambem? goto SecondCounterzero ;sim, então checke isso bcf Counterzero,0 ;não? então este digito 0 já vai deixar de estar em zero, por isso Zero(+0) = 0 movlw 9 ;depois do zero vem o que? resposta: nove! ;-) movwf Counter decfsz Counter+1,F ;decrementa o outro digito!! goto Finish bsf Counterzero,1 ;mas n me digas que está em zero já! Counterzero,1 = 1 goto FinishSecondCounterzero btfsc Counterzero,2 ;bem, dois digitos já estão em zero, falta ver o terceiro goto ThirdCounterzero ;tambem?! bcf Counterzero,0

bcf Counterzero,1 movlw 9 ;e como dois digitos estavam em zero... vamos pô-los em 99 movwf Counter

movwf Counter+1 decfsz Counter+2,F ;e decrementar o terceiro digito goto Finish bsf Counterzero,2 ;já tá em zero?! então Counterzero,2 = 1 goto FinishThirdCounterzero btfsc Counterzero,3

goto FourthCounterzero bcf Counterzero,0 ;carecem de explicação,

pois após x000 vem o que? x999, claro! bcf Counterzero,1 bcf Counterzero,2 movlw 9 movwf Counter movwf Counter+2

movwf Counter+1 decfsz Counter+3,F ;decrementa o quarto

digito goto Finish bsf Counterzero,3

Page 14: Relógio digital LCD com PIC v1

goto FinishFourthCounterzero ;tudo estava em zero? então vamos por isso em 9999... movlw 9

movwf Counter movwf Counter+1 movwf Counter+2 movwf Counter+3 bcf Counterzero,0 bcf Counterzero,1 bcf Counterzero,2 bcf Counterzero,3 goto Finish

Finish movf Counter,W ;e por os valores do contador nas variaveis que são mostradas no display

movwf Value movf Counter+1,W movwf Value+1 movf Counter+2,W movwf Value+2 movf Counter+3,W movwf Value+3

Gohere ;aqui é uma especie de ponto de encontro (devia ter chamado "Roma" a este Label, pois "todos os caminhos levam a Roma" disse-se antigamente... ;-))

btfss Idle+1,0 ;há retardo ainda? (para possibilitar o uso das teclas.... se não houvesse isso, não dava nada, é que isso só após a 20ª ida (-> veja em "PrepareIdle") a Gohere (após ter premido alguma tecla) ele permite que seja premida uma nova tecla

goto Start ;não há retardo, então vamos para Start para fazer o "polling" ás teclas..

decfsz Idle,F ;há retardo, então decrementa goto Main btfsc Modus,Counterm ;isso aqui é para evitar que no

modo do contador haja problemas... goto Skip

btfss PORTA,Stp ;chegou á 0? então acabar com o estado de espera!

goto PrepareIdleSkip btfss PORTA,Mode

goto PrepareIdle btfss PORTA,Min goto PrepareIdle btfss PORTA,Hr goto PrepareIdle

bcf Idle+1,0 goto Main

Start btfss PORTA,Mode ;isso tudo carece de explicação! (bem, não sou assim tão mau ;) : aqui é visto se há alguma tecla premida e se sim, salta para a respectiva parte do programa...)

goto SetMode btfss PORTA,Hr goto Hour btfss PORTA,Min goto Minutes btfsc Modus,Counterm ;para evitar problemas fatais no

modo do contador... goto Main

Page 15: Relógio digital LCD com PIC v1

btfss PORTA,Stp goto StartStopIt

goto MainPrepareIdle ;preparar estado de espera! (retardo) bsf Idle+1,0

movlw 10 ;ai, você quer ajustar a hora mais depressa do que isso?? então ponha ai um valor mais pequeno do que 10, mas não recomendo isso muito...

movwf Idle goto Main

SetMode ;tecla "mode" foi premida, então faz um "rlf" (rotate left through carry) com a variavel Modus, isso é , aquilo faz mudar para o proximo modo! é muita giro isso, né? ehehehe =PP bcf STATUS,C

rlf Modus,F btfss Modus,6 goto PrepareIdle bcf Modus,6 bsf Modus,Ck goto PrepareIdle

Hour ;tecla "hour" foi premida, esta pode: ou ajustar a hora do relogio, do alarme, ou os minutos do countdown (é o que é verificado logo de seguida) ou pôr em reset o cronometro ou mudar entre "contar para cima ou contar para baixo" do contador btfss Modus,Settime

goto Check incf Time+4,F ;aqui é ajustado o relogio movf Time+4,W sublw 4 btfss STATUS,Z goto Goon movf Time+5,W sublw 2 btfss STATUS,Z goto Goon movlw 0 movwf Time+4 movwf Time+5 goto PrepareIdle

Goon movf Time+4,W sublw 10 btfss STATUS,Z goto PrepareIdle movlw 0 movwf Time+4 incf Time+5,F goto PrepareIdle

Check btfss Alarmstat,1

goto Not bcf Alarmstat,1 ;se o alarme estiver a soar, e a

tecla Hour for premida, o alarme é interrompido e a função alarme é inibida, até nova activação pelo utilizador no modo alarme.

bcf Alarmstat,0 bcf PORTA,Out

Not btfsc Modus,Cntdn

Page 16: Relógio digital LCD com PIC v1

goto Cdnhours btfss Modus,Stpw goto Alarmhour btfss Modus,Stpw ;aqui é resetado o stopwatch goto PrepareIdle btfsc Stpwstat,0 goto PrepareIdle bsf Stpwstat,1 goto Delstptime

Cdnhours ;aqui é ajustado a hora do countdown btfsc Cdnstat,0

goto PrepareIdle bcf PORTA,Out bcf Zero,2 incf Cdntime+2,F movf Cdntime+2,W sublw 10 btfss STATUS,Z goto PrepareIdle bsf Zero,2 bcf Zero,3 movlw 0 movwf Cdntime+2 incf Cdntime+3,F movf Cdntime+3,W sublw 6 btfss STATUS,Z goto PrepareIdle bsf Zero,3 movlw 0 movwf Cdntime+3 movwf Cdntime+2 goto PrepareIdle

Alarmhour ;aqui é ajustada a hora do alarme btfss Modus,Alarm

goto Counterupdown bcf Alarmstat,0 incf Alarmtime+2,F movf Alarmtime+2,W sublw 4 btfss STATUS,Z goto Alarmgoon movf Alarmtime+3,W sublw 2 btfss STATUS,Z goto Alarmgoon movlw 0 movwf Alarmtime+2 movwf Alarmtime+3 goto PrepareIdle

Alarmgoon movf Alarmtime+2,W sublw 10 btfss STATUS,Z goto PrepareIdle movlw 0 movwf Alarmtime+2 incf Alarmtime+3,F goto PrepareIdle

Page 17: Relógio digital LCD com PIC v1

Counterupdown ;e aqui é mudado a maneira como o contador conta: se foi para cima, agora já conta para baixo, se foi para baixo, agora vai contar para cima btfss Counterstat,0

goto Setit bcf Counterstat,0 goto PrepareIdle

Setit bsf Counterstat,0

goto PrepareIdleMinutes ;a "tecla dos minutos" foi premida! pode ajustar o relogio, o countdown (só que neste caso ajusta os segundos), o alarme ou pôr em zero o contador ou mudar entre mostrar hora e minutos e mostrar segundos e minutos btfss Modus,Settime

goto Checkagain incf Time+2,F ;ajusta os minutos do relogio movf Time+2,W sublw 10 btfss STATUS,Z goto PrepareIdle movlw 0 movwf Time+2 incf Time+3,F movf Time+3,W sublw 6 btfss STATUS,Z goto PrepareIdle movlw 0 movwf Time+3 movwf Time+2 goto PrepareIdle

Checkagain btfss Modus,Cntdn

goto Checktwice btfsc Cdnstat,0 ;ajusta o countdown goto PrepareIdle bcf PORTA,Out bcf Zero,0 incf Cdntime,F movf Cdntime,W sublw 10 btfss STATUS,Z goto PrepareIdle bsf Zero,0 bcf Zero,1 movlw 0 movwf Cdntime incf Cdntime+1,F movf Cdntime+1,W sublw 6 btfss STATUS,Z goto PrepareIdle bsf Zero,1 movlw 0 movwf Cdntime+1 movwf Cdntime goto PrepareIdle

Checktwice btfsc Modus,Alarm

Page 18: Relógio digital LCD com PIC v1

goto Alarmmin btfsc Modus,Counterm goto Counterreset btfsc Stpwstat,2 ;muda entre "horas e minutos" e

"minutos e segundos" goto Clear bsf Stpwstat,2 goto PrepareIdle

Clear bcf Stpwstat,2

goto PrepareIdleAlarmmin ;ajusta o alarme btfss Modus,Alarm

goto PrepareIdle bcf Alarmstat,0 incf Alarmtime,F movf Alarmtime,W sublw 10 btfss STATUS,Z goto PrepareIdle movlw 0 movwf Alarmtime incf Alarmtime+1,F movf Alarmtime+1,W sublw 6 btfss STATUS,Z goto PrepareIdle movlw 0 movwf Alarmtime+1 movwf Alarmtime goto PrepareIdle

Counterreset ;reseta o contador movlw 0

movwf Counter movwf Counter+1 movwf Counter+2 movwf Counter+3 bsf Counterzero,0 bsf Counterzero,1 bsf Counterzero,2 bsf Counterzero,3 goto PrepareIdle

StartStopIt ;tecla StartStop foi premida! esta serve ou para start/stop o cronometro ou o countdown ou para resetar o contador ou para activar o alarme

btfss Modus,Stpw ;inicia a contagem do cronometro goto Checknext btfsc Stpwstat,0 goto Stopit bsf Stpwstat,0 btfss Stpwstat,1 goto PrepareIdle bcf Stpwstat,1

Delstptime ;põe os valores do cronometro em zero movlw 0

movwf Stpwtime movwf Stpwtime+1 movwf Stpwtime+2 movwf Stpwtime+3 movwf Stpwtime+4

movwf Stpwtime+5

Page 19: Relógio digital LCD com PIC v1

goto PrepareIdleStopit ;pâra a contagem do cronometro

bcf Stpwstat,0 goto PrepareIdleChecknext btfss Modus,Cntdn

goto Checkalarm ;inicia o countdown btfsc Cdnstat,0 goto Stopcdn bsf Cdnstat,0 goto PrepareIdle

Stopcdn bcf Cdnstat,0 ;pâra o countdown

goto PrepareIdleCheckalarm btfss Modus,Alarm ;activa ou desactiva o alarme

goto PrepareIdle btfsc Alarmstat,0

goto Noalarm bsf Alarmstat,0 bcf Modus,Alarm bsf Modus,Ck ;e muda o modo para o modo de

relogio para demonstrar ao utilizador que o estado do alarme mudou de activado para desactivado ou ao contrario

goto PrepareIdleNoalarm bcf Alarmstat,0

bcf Modus,Alarm bsf Modus,Ck goto PrepareIdle

END