Você está na página 1de 19

;**************************************************

; Relógio digital LCD com PIC v1.1


; PICrelogiodigitalasm.txt
;
; (c) 2002 Elias Jahn
; (elias_jahn@clix.pt)
; 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
Time 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á alarme
Alarmcnt RES 1 ;"contador" para ver se alarme de 60
segundos chegou ao fim
Counterstat 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 contar
Counter RES 4 ;vai conter o valor do contador
universal crescente/decrescente
Zero RES 1 ;é para saber se algum dos digitos do
countdown estiver em zero
Counterzero RES 1 ;é para saber se algum dos digitos do
contador estiver em zero

wtemp RES 1
statustemp RES 1
Timervalue RES 1 ;variavel para efeitos de ajuste da
precisão do relogio
Compensate RES 1 ;variavel para efeitos de ajuste da
precisão do relogio
Compensating 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
return
TheDigit3
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 verify
Zeroclock ;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 verify
checkitout
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 Countdown
Zerostpw
movlw 0
movwf Stpwtime+4
movwf Stpwtime+5
;aqui vem as cenas da contagem
decrescente
Countdown
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 exitint
SecondZero
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 exitint
ThirdZero
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 minutos
Whatever
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 Finish
Countermode ;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 Finish
SecondCounterzero
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 Finish
ThirdCounterzero
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 Finish
FourthCounterzero ;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 PrepareIdle
Skip
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 Main
PrepareIdle ;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 PrepareIdle
Minutes ;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 PrepareIdle
Alarmmin ;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 PrepareIdle
Stopit ;pâra a contagem do cronometro
bcf Stpwstat,0
goto PrepareIdle
Checknext
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 PrepareIdle
Checkalarm
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 PrepareIdle
Noalarm
bcf Alarmstat,0
bcf Modus,Alarm
bsf Modus,Ck
goto PrepareIdle

END

Você também pode gostar