==================
OPERANDO COM O TIMER-0
==================
TIMER-0
O timer-0 normalmente utilizo em meus projetos para fazer a base de tempo, ou seja, o relógio do projeto, como contar tempo para repetir ou considerar um evento. Sempre pensando em trabalhar em multi-tarefas, ou seja, não prender o processo em nenhum evento, mas simplesmente ver se é momento, e executa-lo ou não.
O timer-0 trabalha por interrupção, quando esta ocorrer o programa pula para o endereço 0x0006 e guarda onde estava no stack point para retornar.
.org 0x0006 ;Overflow0 Interrupt Vector Address
rjmp timer0
Ao iniciar o programa deve-se programar os registros operacionais para habilitar o timer-0.
ini_timer0:
ldi a,0x01 ; // 4MHZ/256 = 15K625Hz -> 64 us
out tccr0,a ; prescaling timer0
in a,timsk
ori a,0x02
out timsk,a ; over flow timer0
ret
Eu normalmente chamo esta de ini_timer0, inicializando o timer-0.
Devemos lembrar que sempre o timer-0 irá dividir o clock por 256, não tem opção é a construção deste. Depois posso escolher mais divisões, conforme se vê no manual. Eu escolhi dividir por 1, com o cristal de 4MHz, teremos interrupções a cada 4MHz/256 = 15K625Hz -> 64 us.
A cada 64us ele executará as instruções que estão no local timer0.
Dei nomes:
.def a = r16 ;reg
.def b = r17 ;reg
.def c = r18 ;reg
.def seg1 = r20 ;temporizador
.def seg2 = r21 ;temporizador
; ============================
;// I N T E R R U P T O V E R F L O W T I M E R - 0
; ============================
timer0: ;// 4MHZ/256 =15K625Hz -> 64 us soft prescaller 2 x /125
push a
in a,sreg
push a
push b
push c
antes de iniciar as operações, preciso salvar os registros que virão a ser utilizados aqui, pois antes de vir para cá ele estava executando alguma operação, que no momento desconheço, mas de qualquer forma preciso salvar estas, para repo-las quando retornar para o que estava fazendo, caso contrário ele executará procedimentos errados, tomar muito cuidado.
;
;
; aqui vem meu programa de timer0 ........
;
acabou de executar este, é hora de retornar ao que estava fazendo...
aqui preciso repor os registros que alterei, supondo que aqui utilizei os ;registros a, b, c , sreg, preciso voltar a estes seu valor original, de forma que ;a rotina que ele estava executando antes de vir para cá, não perceba nenhuma ;alteração.
O sreg é muito importante, é estão as bandeiras, resultados de operações. ;Imagine que antes de vir este estava fazendo : cpi a,4 comparar a com o ;numero para tomar uma decisão, na bandeira Z estava o resultado, ao vir para ;cá estas operações alteraram esta bandeira então é preciso repor o estado original.
tim0f:
pop c
pop b
pop a
out sreg,a
pop a
reti
Aonde digo "aqui vem o programa de timer0" poderia ser assim:
;// ---------------------------------------------
; // aqui tempo de 125Hz 8ms ->15k625/125(presc1)=125Hz
; // --------------------------------------------
dec presc1
brne tim0a
ldi a,125
mov presc1,a
estou fazendo um prescaller, um outro divisor, desta vez por soft e dividindo por 125, deforma a Ter uma base de tempo de 8 ms. Então ele só executara estas instruções abaixo quando o prec1 chegar a 0. A cada 15k625/125(presc1)=125Hz.
sbic pinb,2 ;remoto ligado?
rjmp tim0k
sbr flip,bits7
rjmp tim0m
tim0k:
cbr flip,bits7
observe que a cada 8 ms, ele verifica o pino 2 da porta B, caso este seja zero, ele set para 1 o bit 7 do registro flop ou caso contrário, este vale zero.
Esta é uma das maneiras classicas, de se fazer o debaucing de uma tecla, ou seja, tirar o ruido quando mecanico de aperto de tecla. É impossível uma lamina encostar em outra sem gerar ruído, mas desta forma nos só fazemos sua leitura a cada 8 ms, a probalidade de ruido é bem menor, tem outra forma melhor que passo a seguir.
;---------------------------
tim0m:
; key portb pb2=modo, pb4=mov dir, pb5=mov esq, pb6=wre2p
in a,pinb
andi a,0b01110100
cp a,keyr
breq get_key1
mov keyr,a
rjmp get_key2
get_key1:
mov key,keyr
get_key2:
aqui a porta B pinos 6,5,4 e 2 temos teclas simples ligadas e quando acionadas ligam para o terra ou seja zero, todas as entradas tem resistor (PULLUP) ligados em VCC.
Observe que pega a porta B, faz um and eliminando as que não interessam, depois compara com o valor lido anteriormente, se este for igual então esta alteração vale, passe para o valor para KEY mas caso seja diferente armazena no registro KEYR, para ser comparado novamente daqui a 8ms. Esta é a forma classica de eliminar ruído, veja que para uma alteração de teclas para ser válida ela deverá ser igual por duas leituras de 8 ms de intervalos. Funciona muito bem.
Fazendo bases de tempos:
No soft normal necessita-se de bases de tempo, por exemplo operando com step motors, dar um passo neste, mas quem faz a base de tempo de potencia aplicada, ou piscar um led, ou gerar um pulso de largura fixa....
Aqui poderia ser feito o seguinte, por exemplo um pulso de largura fixa: o soft normal faz uma saida ser alta e junto faz o registro Seg1=10, e ficara esperando o Seg ser zero, quando ocorrer faz a saida ser zero. Mas quem decrementa Seg1 é a timer0. E termos um pulso de 10x8ms=80ms na saída.
tst seg1
breq base1
dec seg1
base1:
Utilizando o mesmo procedimento de prescallers, pode-se expandir este para se conseguir base de tempos de 1 segundo, minutos, horas etc.... No caso:
4MHz/256 = 15625Hz, 15625/125(prec1) = 125Hz, 125/125(pres2) = 1Hz ou 1 Seg.
1Hz/60(prec3) = 0,008Hz ou 60min, .....
===========================================================================
Meu Site Eletrônica Index