<$BlogRSDURL$>
timer0
Monday, April 19, 2004
 

==================
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 
alvaro luiz stendardi fontes

ARCHIVES
04/01/2004 - 05/01/2004 /


Powered by Blogger