Autor Tema: como se calcula, y configurar en C un antirrebote usandioun TIMER en HCS08,gcas  (Leído 4232 veces)

0 Usuarios y 1 Visitante están viendo este tema.

Desconectado cicloide2

  • PIC18
  • ****
  • Mensajes: 359
Hola solo eso quiero, realizar un antirebote para un pulsador pero lo quiero realizar con un TIMER de un HC9S08QG8, para aprender a utilizar el TIMER de éstos micros, como configurar registros, calcular los tiempos en función del oscilador interno,y saber serteramente que mi delay antirebotes es de tantos milisegundos (creo que aprendiendo a hacer esto con un timer, podría extrapolarlo a tiempos mayores mas adelante, pero por el momento con un antirrebote sin la famosa manera de la repetición sino utilizando un propiamente dicho TIMER, puesto en los MCU para muchas utilidades, una de ellas, generar tiempos precisos, como los que pretendo (solo para molestar, y aprender).

Gracias saludos cordiales. ;-)

Desconectado Freescalin

  • PIC10
  • *
  • Mensajes: 22
Re: como se calcula, y configurar en C un antirrebote usandioun TIMER en HCS08,gcas
« Respuesta #1 en: 07 de Diciembre de 2014, 15:19:55 »
Estimado... el tema de los Timer da para varias enciclopedias... pero tal vez lo más sencillo para comenzar a aprender a usarlos es hacer y probar algunas rutinas generando "períodos" con el Timer Overflow (TOF). El QG8 permite, con su Timer llamado TPM, generar interrupciones de TOF con un período programado por nosotros. Esto nos permitiría tener un "aviso" periódico de que ha transcurrido dicho tiempo, y a ese evento utilizarlo para otros fines. Esta forma básica sería entonces "algo que ocurre" cíclicamente, y como es por interrupción, el micro quedaría libre para otras tareas... y yo solo debo consultar en el lugar correcto del código, si ha pasado el tiempo programado o no. Es decir, si hubo TOF o no.
Voy a tratar de ejemplificarlo "en Español" y sin demasiados detalles de registros para que se entienda:
- Supongamos que se dejan los "seteos" de fábrica en cuanto a fuente de clock y valores de registros. El QG8 "arranca" con una Fbus de 4Mhz.
El ciclo de clock será de 0.25 uS y a esa velocidad se incrementará el contador "libre" del TPM (llamado TPMCNTH y L).

- Como el contador es de 2 bytes, el Overflow se producira cada 65535 * .25 uS = 16383.75 uS. Es decir cada 16.38 mS.
Para este caso, no puedo tener TOF para períodos mayores a ese, pero sí puedo programar períodos menores, y más exactos, que pueda luego utilizar.

- Cómo hago? Uso los registros TPMMOD (H:L). Este registro de 2 bytes me permite "recortar" la cuenta del contador libre, para que solo cuente hasta el valor "escrito" en el TPMMOD(H:L).

- Si para este caso (Fbus = 4mhz y Ciclo de .25 uS) hago que TPMMOD(H:L) = 40000, entonces el contador libre solo contará hasta 40000 y no hasta 65535, con lo cual el TOF se producirá cada 40000 cuentas de .25 uS, es decir, cada 10000 uS, o bien, 10 mS.
Esto solo por poner un ejemplo... podemos programar otros valores en TPMMOD(H:L), sin duda...

- Si habilitara la interrupción por TOF, ésta ocurrirá cada 10mS (para este ejemplo) y cada vez que ocurra un TOF, se llamaría la rutina de interrupción.
La interrupción por TOF se habilita escribiendo un "uno" en el bit TOIE del registro TPMSC. Debo tener encuenta que en los vectores de interrupción, debe estar escrito el correspondiente "nombre" (etiqueta) de mi interrupción, para que cuando esta ocurra, el programa acuda a atenderla, llamando dicha rutina.

- En la rutina de interrupción por TOF podemos hacer varias cosas, pero para comenzar a probar esto, si uno no lo utilizó nunca, lo mejor es "encender el típico led" para comprobar el funcionamiento de todo lo implementado. Algo así, por ejemplo... con un led en el bit 0 de PortA:

isrVtpmovf:
  ; Write your interrupt code here ...
*Se ha seteado Oscilador INTERNO y FLL enganchado, con Divisor igual a 2.
*Eso da una Fbus=4Mhz.
*Con TMOD=40000 (decimal) el TOF queda cada 10mS.
    PSHH                               ;Salvo el registro H en la pila (como en toda interrupción!!!)
    LDA      TPMSC                     ;Leo el TMPSC y le escribo un "cero" al bit TOF, para resetear la bandera TOF
    AND   #$7F                        ;y la interrupción por TOF.
    STA    TPMSC
    BRSET     0,PTAD,PONCERO   ;SI EL PTA(0) = 1, SALTO A PONERLE 0.
         BSET       0,PTAD                        ;...SI NO, LE PONGO "UNO" (prende led).
         BRA        XRUT                           ;Y SALTO A LA "SALIDA" DE ESTA RUTINA.
PONCERO:
         BCLR      0,PTAD                         ;LE PONGO CERO AL PTA(0) PARA APAGAR LED
XRUT    PULH                                          ;ESTA ES LA SALIDA DE LA RUTINA, DONDE RECUPERO
         RTI                                            ; EL REGISTRO H y hago el RTI.
; end of isrVtpmovf
           
- En conclusión, la rutina anterior haría que el led esté encendido 10mS, apagado 10 mS, y así sucesivamente... for ever.
Esto no es para mirar con los ojitos, para comprobarlo hace falta osciloscopio, cabe acotar.

Este sería "en criollo" un ejemplo bastante básico de cómo generar un período con el Timer... para usarlo luego en retardos, antirrebotes, relojes, etc.
Si me olvidé de algo, o hay algún error, por favor avisenme.
Si hay alguna duda, intentaré aclararla... pero PERDÓN: solo respondo en "Assembbler" (que es mi lenguaje materno-infantil  :D).
Saludos a todos, y especialmente al amigo Cicloide2, por generar esta pregunta.
Gracias.
"El Datasheet es al Programador lo que la Biblia al Predicador"

Desconectado cicloide2

  • PIC18
  • ****
  • Mensajes: 359
Re: como se calcula, y configurar en C un antirrebote usandioun TIMER en HCS08,gcas
« Respuesta #2 en: 07 de Diciembre de 2014, 18:29:27 »
Gracias Freescalin, (por lo visto muchos pasaron ver mi inquietud) es que realmente se sabe muy poco sobre Freescale, y mucho menos en C. Lo del Assembler, y bue, no todo debe ser servido, si no como se aprende no?, tratré de aplicar lo demostrado en la explicación (no en el ejemplo, ya que de Assembler cero), pero  lo que se me ocurre es tener que hacer una función con un tiempo X que no sabia como calcularlo hasta tu explicación.

Gracias mil, si logro hacer la función y configurar todos los bit del TPM la subo. Así me corrigen, y quizas le sirva a alguien mas, que les parece.

Saludos. ;-)

Desconectado juanml

  • PIC10
  • *
  • Mensajes: 30
Hola! No se si ya pudiste solucionar esto, pero te dejo un código en C que lo que hace es leer un switch conectado a PTAD0. No lo probé, pero creo que está bien!

Código: [Seleccionar]
#define sw PTAD_PTAD0

char cont;

void main(void)
{
SOPT1_COPE = 0; //Watchdog desactivado

//Inicializo pin al que esta conectado el switch
PTADD_PTADD0 = 0; //PTA0 como entrada

PTAPE_PTAPE0=1; //Configuro la resistencia pull-up de PTAD0, entonces si el switch no esta presionado, siempre lee un "1". Cuando esta presionado, lee un "0"

//Inicializo el timer
TPMSC = 0b00000000; //bit 6: Interrupciones desactivadas, bit 5: no PWM, bits 4-3: timer desactivado (por ahora), bits 2-1-0: Prescaler = 1

TPMMOD = 40000; //Numero hasta el que cuenta el timer. Este tiempo corresponde a un antirrebote de 10ms (10ms/0.25us = 40000), siendo 0.25us un ciclo de reloj para un clock de bus de 4MHz

for(;;)
{
if (!sw) //Si el switch esta presionado.
{
while (!sw) //Rutina antirrebotes
{
TPMSC_CLKSA = 1; //Activo el timer con clock igual a Bus clock (4MHz).
//Empieza a correr el timer
while (!TPMSC_TOF) //Mientras el bit de overflow es 0, espera.
{
}
                                                TPMSC_CLKSA = 0;
//Cuando cuenta hasta 40000 (10ms), sale del while y desactivo el timer.
}

//Aca escribo lo que quiero que pase cuando presiono el boton, por ejemplo, aumentar un contador.
cont++;

}

}
}

Desconectado cicloide2

  • PIC18
  • ****
  • Mensajes: 359
Hola! No se si ya pudiste solucionar esto, pero te dejo un código en C que lo que hace es leer un switch conectado a PTAD0. No lo probé, pero creo que está bien!

Código: [Seleccionar]
#define sw PTAD_PTAD0

char cont;

void main(void)
{
SOPT1_COPE = 0; //Watchdog desactivado

//Inicializo pin al que esta conectado el switch
PTADD_PTADD0 = 0; //PTA0 como entrada

PTAPE_PTAPE0=1; //Configuro la resistencia pull-up de PTAD0, entonces si el switch no esta presionado, siempre lee un "1". Cuando esta presionado, lee un "0"

//Inicializo el timer
TPMSC = 0b00000000; //bit 6: Interrupciones desactivadas, bit 5: no PWM, bits 4-3: timer desactivado (por ahora), bits 2-1-0: Prescaler = 1

TPMMOD = 40000; //Numero hasta el que cuenta el timer. Este tiempo corresponde a un antirrebote de 10ms (10ms/0.25us = 40000), siendo 0.25us un ciclo de reloj para un clock de bus de 4MHz

for(;;)
{
if (!sw) //Si el switch esta presionado.
{
while (!sw) //Rutina antirrebotes
{
TPMSC_CLKSA = 1; //Activo el timer con clock igual a Bus clock (4MHz).
//Empieza a correr el timer
while (!TPMSC_TOF) //Mientras el bit de overflow es 0, espera.
{
}
                                                TPMSC_CLKSA = 0;
//Cuando cuenta hasta 40000 (10ms), sale del while y desactivo el timer.
}

//Aca escribo lo que quiero que pase cuando presiono el boton, por ejemplo, aumentar un contador.
cont++;

}

}
}


Gracias juanml, a decir verdad tengo un poco abandonado los MCU, mas en Argentina que parece que perdieron espacio. (ocupado por PIC o Arduino).

Quisas vuelva a retomar para implementar tu esfuerzo por la duda de un desconocido. Tengo un cubo hecho 3x3x3 montado en el ecritorio con un QG8 (dip16), de la serie S08, podría intercalar tu aporte entre secuencia y secuencia (del cubo).

Gracias! ((:-)) :-) ((:-))
« Última modificación: 30 de Marzo de 2015, 22:14:41 por cicloide2 »