relógio digital lcd com pic v1
TRANSCRIPT
;**************************************************; 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,
;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
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.
;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 = ?
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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