Escolar Documentos
Profissional Documentos
Cultura Documentos
PROCESSOR 16F84A
RADIX DEC
INCLUDE "p16f84a.inc"
ERRORLEVEL -302
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
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
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'
exitint
bcf INTCON,T0IF ;acabou se o interrupt do timer
bsf INTCON,T0IE ;mas volta a permitir novas
interrupções
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