TODOPIC

Microcontroladores PIC => Lenguaje C para microcontroladores PIC => Mensaje iniciado por: PalitroqueZ en 25 de Abril de 2007, 15:31:38

Título: otra forma de generar retardos con el Timer
Publicado por: PalitroqueZ en 25 de Abril de 2007, 15:31:38
Introducción:

Después de leer varios post aquí en el foro acerca del tema, es hora de tomar conciencia y avanzar en cuanto a la forma de programar.

cuando uno se inicia en el mundo de los pic´s y llega un ejemplo que involucra retardos, lo primero que se usa el método fácil: el método del retardo cíclico  (por allí leí en un libro que lo llaman: delay loop method)

les confieso que hasta hace poco creía que los timer´s eran de poco uso, que se limitaba hacer labores de conteo externo (RTCC) y que usandolo como temporizador era innecesario debido al poco tiempo generado y que para ello estaban los codigos redundantes...

pués estaba equivocado. El hecho de que con el timer no se pueda lograr tiempos largos no quiere decir que no se usará. Una cosa que debe tener en cuenta el picmaníaco a la hora de escribir un código, es saber redistribuir los procesos en el tiempo. no importa en que intervalo de tiempo los haga, pero lo importante es que logre su cometido (pensando en asm).

Esto precisamente yo lo aplicaba en ensamblador cuando requería hacer varias cosas, pero nunca se me ocurrió aplicarlo a los retardos involucrados, por supuesto que el código parecerá complicado, pero mas eficiente en su ejecución. podemos ejecutar otros procesos en vez de estar perdiendo tiempo precioso. Esto se puede dar en varios casos, como también puede ocurrir que sea mejor aplicar el otro método. ejemplos particulares.

hasta aquí la introducción...

Después de pensar hacer un ejemplo donde se involucre un retardo grande y a la vez qu el pic ejecute otros procesos, se me ocurrió este:

- se tienen 5 led´s inicialmente apagado.
- hay 5 interruptores normalmente abiertos uno para cada led.

Sn -> Ln : para todo n perteneciente a [1,5]
Sn = interruptor (n)
Ln = Led (n)

- al presionar uno de los switche, se enciende su led coterráneo ej: S1 -> L1.
- el tiempo de encendido: 2 minutos.
- se pueden presionar otros S entre retardos.
- se repite el proceso descrito.

validación:
- si L1 está encendido cuando se presiona S1, se hará caso omiso, solo hasta que L1 <- Off.
- el debounce ó antirebote estará asegurado por una bandera (flag)

posible solución:

- para el retardo de 2 minutos: el Timer1
- se hará uso de interrupciones por desbordamiento del par TMRH:TMRL.

usando una temporización de 524,2 mS interrumpiendo ó desbordandose 229 veces tenemos ~ 120 S = 2 Minutos

para configurar el timer1, podemos usar la formula T = 65536 x 8 x 4 / 4MHZ

ó

podemos usar la herramienta PicMultiCalc (http://www.mister-e.org/) que ya nos dá el valor de acuerdo a nuestro cálculo

(http://img70.imageshack.us/img70/3741/usandotimercalchy5.jpg)

- para 'tratar' de optimizar el programa desde el punto de vista del C , se observa que se puede manejar las variables como un arreglo, ya que los interruptores y los pines de salida son contiguos. (mejor que mejor) :)

- en el bucle principal se estará preguntando por cada entrada de los Sn y a la vez el timer estará contando e interrumpiendo, en la rutina del servicio de interrupción se estará preguntando por los ~ 2 minutos necesarios para apagar el/los led(s) correspondiente(s).

esto se resuelve declarando un arreglo para los contadores de los 2 minutos y uno para la bandera.

la finalidad de las banderas es mantener la cuenta después que se activó un Sn y la de evitar reiniciar el retardo si se pulsa de nuevo Sn entre los 2 minutos

Código: C
  1. //---------------------------------------------
  2. // manejando retardos con el timer1
  3. // PalitroqueZ 25-Abr-07
  4. //---------------------------------------------
  5. #include <16F877.h>
  6.  
  7. #fuses XT,NOPROTECT,NOPUT,NOWDT,NOBROWNOUT,NOLVP,NOCPD,WRT
  8. #use delay (clock=4000000)
  9.  
  10. #byte portb=0x6
  11.  
  12. static int contador[5]; // contadores para generar los 2 minutos
  13. static int bandera;   // flag
  14.  
  15. #define bs(x) bit_test(bandera,x) //
  16. //*************************************************
  17. #INT_TIMER1  // rutina de servicio de interrupcion
  18. void mitimer(){
  19. int k;
  20.         for(k=0;k<5;k++){   // barrido
  21.                 if(contador[k]==228 && bs(k)){ // pasaron los 2 minutos?
  22.                         output_bit(48+k,0); // apaga el led correspondiente
  23.                         contador[k]=0;   // reinicia el contador
  24.                         bit_clear(bandera,k);  
  25.                         // libera el swuitche correspondiente
  26.                 }
  27.                 else{
  28.                         contador[k]++;
  29.                         // no llega a 2 minutos, continua la cuenta
  30.                         // igual cuenta si no hay pulsacion en las Sn
  31.                 }  
  32.         }
  33. }
  34. //*************************************************
  35. void main(){
  36.    int t;
  37.         set_tris_b(0x0);
  38.    set_tris_c(0b11111);
  39.    portb=0x0;
  40.    setup_timer_1(t1_internal | t1_div_by_8);
  41.    set_timer1(0);
  42.    enable_interrupts(INT_TIMER1);
  43.    enable_interrupts(GLOBAL);
  44.         while(1){ // bucle eterno
  45.                 for(t=0;t<5;t++){ // barrido
  46.                         if(input(56+t)){  // pregunta por el switche correspondiente
  47.                                 if(!bs(t)){   // para evitar reiniciar el temporizador en una cuenta
  48.                                         bit_set(bandera,t);  // se activa el flag correspondiente
  49.                                         output_bit(48+t,1); // se activa el led correspodiente
  50.                                         contador[t]=0; // se resetea el contador
  51.                                 } //fin del if2
  52.                         } // fin del if1
  53.                 } // fin del for
  54.         } // fin del while
  55. } // fin del main

como veran, estoy utilizando un timer para varios procesos, y estos procesos a su vez comparten la temporización del timer sin afectar al resto.

para aquellos que usen el Proteus, aquí va un pantallazo de simulación:

(http://img486.imageshack.us/img486/8471/ventanaproteusrk6.jpg)
   
cabe destacar que fué montado,cronometrado y comprobado fisicamente con resultados satisfactorios
   
este es un primer intento, les invito a que participen en la creación de otros ejemplos, para que así nos vayamos ejercitando y podamos dominar este método (para los que no sabemos  :P).
Título: Re: otra forma de generar retardos con el Timer
Publicado por: paco1980 en 30 de Abril de 2007, 14:39:16
hola palitroquez.
En tu ejemplo veo como utilizas  el timer 1 como temporizador interno del pic.
Pero, ¿ como has de configurarlo si lo que pretendieras es que funcionara como contador externo asincrono, poniendole un cristal en sus pines correspondientes?
Gracias
Un saludo
Título: Re: otra forma de generar retardos con el Timer
Publicado por: PalitroqueZ en 30 de Abril de 2007, 16:49:37
Hola paco1980

en el ejemplo puse al timer1 a trabajar como temporizador, mediante

setup_timer_1(t1_internal | t1_div_by_8);


la idea es que realice un retardo sumando cuentas hasta los 65535*8*4/4Mhz = 0.5 segundos antes de desbordarse.


Título: Re: otra forma de generar retardos con el Timer
Publicado por: PalitroqueZ en 02 de Mayo de 2007, 15:37:39
...
¿ como has de configurarlo si lo que pretendieras es que funcionara como contador externo asincrono, poniendole un cristal en sus pines correspondientes?
...

disculpa paco, no se en que planeta estaba cuando te respondí anteriormente   :z) esa parte no la ensayado todavía por la que no puedo darte una respuesta justa. lo que se, es la parte teorica que menciona la datasheet.

Título: Re: otra forma de generar retardos con el Timer
Publicado por: paco1980 en 04 de Mayo de 2007, 06:03:10
pues yo lo intento y lo intento, pero no doy con la tela, y no he encontrado ningún ejemplo por acá.
Un saludo.
Nota: si consigues algo, aqui te espero. Gracias.
Título: Re: otra forma de generar retardos con el Timer
Publicado por: zagoaristides en 08 de Agosto de 2007, 09:35:01
Muchas gracias. Lo voy a tratar de implementar en un proyectito que estoy haciendo de un sistema de control de acceso con alarma sonora y aviso sms. Un abrazo.
Título: Re: otra forma de generar retardos con el Timer
Publicado por: ESTECA55 en 08 de Agosto de 2007, 10:35:22
Muy buen ejemplo PalitroqueZ!!!

Yo suelo usar siempre el Timer  para retardos y demas, es mas suelo adosarle varias cosas, pero hasta ahora venia trabajando en asembler, y estoy empezando con el C, así que me viene de 10 para ir aprendiendo a como usar C en los pic jejejeje

Gracias por el aporte

Saludos
Título: Re: otra forma de generar retardos con el Timer
Publicado por: jeleee en 08 de Agosto de 2007, 16:00:45
  Solo una pregunta, de donde sacas el 56 y el 48?

       
Código: C
  1. if(input(56+t)){  // pregunta por el switche correspondiente                           
  2. if(!bs(t)){   // para evitar reiniciar el temporizador en una cuenta                                   
  3. bit_set(bandera,t);  // se activa el flag correspondiente                                      
  4. output_bit(48+t,1); //
Título: Re: otra forma de generar retardos con el Timer
Publicado por: PalitroqueZ en 09 de Agosto de 2007, 13:31:43
son los apuntadores en ccs del pin correspondiente,

48 = 6*8-> RB0
56 = 7*8-> RC0

como en C un arreglo se caracteriza por tener las direcciones contiguas, entonces para recorrer ambos puertos, bastaría:

48+t

56+t

Título: Re: otra forma de generar retardos con el Timer
Publicado por: Leon Pic en 10 de Octubre de 2007, 14:12:47
Hola PalitroqueZ. Pase el programa de c a asm. ¿Cómo? muy facil pero trabajoso. Primero copié el programa, lo abri en el Mplab, luego cree el prooyecto y una vez generado el hex, lo abrí con el ICPROG y este tiene una herramienta que lo pasa a asm (lee el hex y da el asm, obvio).
El problema que no es muy legible, ya que no da la primera columna con palabras que usa el usuario. Si alguien le interesa, lo subo al foro.

Saludos.  :-/ :-/
Título: Re: otra forma de generar retardos con el Timer
Publicado por: Rulo en 10 de Octubre de 2007, 14:46:23


         Tal vez ya lo sepan, pero si usan CCS una vez compilado el archivo en el menu compile se van a la opcion C/ASM List y obtienen tambien el codigo en ASM, una herramienta muy util tambien.

        (http://img402.imageshack.us/img402/3057/capturajr3.jpg)

                   Saludos  :-/
Título: Re: otra forma de generar retardos con el Timer
Publicado por: LABmouse en 10 de Octubre de 2007, 14:56:32
Rulo, y es mas potente que solo pasar de C a ASM, ya que te separa cada comando que escribiste en C y te dice el equivalente en ASM de el.

SALUDOS!!
Título: Re: otra forma de generar retardos con el Timer
Publicado por: Rulo en 10 de Octubre de 2007, 15:13:49


       Si lo se  :mrgreen: , mi intencion es que se anime a probarlo quien no lo haya hecho, insisto, es una herramienta muy util.


            Saludos  :-/
Título: Re: otra forma de generar retardos con el Timer
Publicado por: LABmouse en 10 de Octubre de 2007, 15:17:25
Rulo, yo tambien lo decía para los que no lo conocen..

SALUDOS!!  :-/
Título: Re: otra forma de generar retardos con el Timer
Publicado por: MGLSOFT en 11 de Octubre de 2007, 08:29:15
Muy bueno!!

Yo suelo utilizar un solo timer, con una base de tiempo definida y estable, y los tiempos de cada temporizador los programo en cantidad de interrupciones de este timer. Cuando los valores programados son sobrepasados pongo en uno la banderas de cada temporizador y pongo en cero su contador.

Algo muy similar a esto pero sin utilizar un array, que es una idea muy original por cierto !! :-/
Título: Re: otra forma de generar retardos con el Timer
Publicado por: PalitroqueZ en 11 de Octubre de 2007, 18:21:02
Hola PalitroqueZ. Pase el programa de c a asm. ¿Cómo? muy facil pero trabajoso. Primero copié el programa, lo abri en el Mplab, luego cree el prooyecto y una vez generado el hex, lo abrí con el ICPROG y este tiene una herramienta que lo pasa a asm (lee el hex y da el asm, obvio).
El problema que no es muy legible, ya que no da la primera columna con palabras que usa el usuario. Si alguien le interesa, lo subo al foro.

Saludos.  :-/ :-/

sip, Trabajoso, porque hay que estudiar el código y eliminar lo que sea redundante, también hay que tener la tabla de las direcciones de los SFR para saber quien es quien .

Rulo, y es mas potente que solo pasar de C a ASM, ya que te separa cada comando que escribiste en C y te dice el equivalente en ASM de el.

SALUDOS!!

útil en el sentido de que por ejemplo algo que no sepamos hacer en asm, y nos ponemos de tramposo y miramos el listado del ccs haber como lo hace él  :twisted:  :5}

Título: Re: otra forma de generar retardos con el Timer
Publicado por: PalitroqueZ en 29 de Abril de 2008, 16:47:58
Teoría:

se me ocurrió otro ejemplo para madurar la forma de utilizar retardos y a la vez hacer otras cosas.

una situación común es utilizar funciones de inicialización empezando el main, el contador de programas (CP) entra y sale de la función y contínua normalmente.

es posible que dentro de una función de inicialización tengamos que hacer un retardo, bien aplicando lo aprendido usamos el retardo por interrupción del timer. perooo.. hay un pequeño detalle: la función se debe ejecutar una sola vez y el CP no debe entrar mas a ella. ¿como hacemos?

bien la respuesta que he estudiado es usar banderas y bucles condicionales

supongamos que tenemos la función vIniciar(), si vIniciar posee un retardo, entonces

- se debe partir el código interno exactamente donde vá el retardo.
- encerrar ambos pedazos en 2 if.
- al final del primer if, configuramos el timer para el retardo.
- ambos if serán regidos por unas banderas previamente declaradas.
- para ejecutar vIniciar una sola vez, en el bucle principal, encerramos a vIniciar dentro de un condicional guiado por otra bandera.

- así en cada pasada del bucle eterno, se preguntará por dicha bandera (llamemosla fIniciar) y NO se ejecutará mas nunca vIniciar.


Aquí va un programa de ejemplo:

Código: C
  1. /* Generando Retardos con el timer. 2 Parte
  2.    Pedro - PalitroqueZ
  3.  */
  4.  
  5. #include <18F4550.h>
  6. #fuses XT,NOMCLR,NOWDT,NOPROTECT,NOLVP
  7. #fuses NODEBUG,NOPBADEN,CPUDIV1,NOVREGEN //,PLL1
  8. #use delay(clock=4M)
  9.  
  10. int8 iBanderas;    // variables globales
  11. #bit fIniciar = iBanderas.0
  12. #bit fDurante_Retardo = iBanderas.1
  13. #bit fFin_Retardo = iBanderas.2
  14.  
  15. //***************************************
  16. // servicio de interrupción
  17. //***************************************
  18. #int_timer0
  19. void  tmr0_isr(){
  20.    fDurante_Retardo=1;
  21.    fFin_Retardo=1;
  22.    disable_interrupts(INT_TIMER0);
  23.    // deselecciona la fuente de interrupción
  24.    // para no ejecutarla a posteriori
  25. }
  26. //***************************************
  27. void vIniciar(){
  28.    if(!fDurante_Retardo){
  29.       delay_us(10);  // simula tiempo de lineas de programas
  30.       fDurante_Retardo=1;
  31.       set_timer0(21); // retardo de ~ 15ms
  32.       enable_interrupts(GLOBAL);
  33.       return;
  34.    }
  35.    if(fFin_Retardo){ //la otra mitad del programa dentro de vIniciar
  36.       delay_us(80);  // simula tiempo de lineas de programas despues del retardo
  37.       fIniciar=0;
  38.       disable_interrupts(INT_TIMER0);
  39.    }
  40. }
  41.  
  42. //***************************************
  43. // programa principal
  44. //***************************************
  45. void  main(){
  46.    int16 t;
  47.    // ... aqui va config puertos, modulos, etc.  
  48.    iBanderas=0b00000001;
  49.    //fIniciar = 1;
  50.    //fDurante_Retardo = 0;
  51.    //fFin_Retardo=0;
  52.    
  53.    
  54.    setup_timer_0(RTCC_INTERNAL|RTCC_DIV_64|RTCC_8_BIT);
  55.    // configura el Timer0 base de tiempo interno, pre-escaler=1:64, contador de 8 bits
  56.    enable_interrupts(INT_TIMER0);
  57.    // selecciona la fuente de interrupción del timer0
  58.      
  59.    while(1){  // bucle eterno
  60.       delay_us(80);  // simula tiempo de otros procesos
  61.       if(fIniciar){ // pregunta para decidir si entrará o no a vIniciar
  62.          vIniciar();
  63.       }
  64.      
  65.       for(t=0;t<65000;t++){ // simula tiempo de otros procesos
  66.          delay_cycles(1);
  67.       }
  68.    }
  69. }

Ventajas:

- uuy muchas, principalmente se aprovecha el máximo tiempo permitido, la ejecución de multiples procesos.

- las interrupciones es lo mejor que hay.

- como quisiera que la gente de Microchip le fueran puesto interrupción a cada pin de los uCPIC


Desventajas:
- se estará preguntando si es posible la ejecución de una función en cada pasada del bucle eterno, pero si lo ven bien, no está mal perder unos cuantos ciclos, a que perder miles por un tonto retardo cíclico.

- si el CP dura mucho tiempo en volver al inicio del bucle, entonces vIniciar tomará mas tiempo en completar sus lineas de programa.

Eso depende de vIniciar. Si vIniciar requiere al menos retardo_calculado para funcionar correctamente, entonces no habrá problemas.

por el contrario, si retardo tiene que ser retardo_calculado y continuar las lineas faltantes inmediatamente, entonces hay que tomar medidas extremas como preguntar estrategicamente por la bandera fIniciar que rige a vIniciar. (calculando previamente los tiempos entre otros procesos para que cuadre el retardo de vIniciar)

- el programa se vuelve confuso si es largo, pero ¿quien ha dicho que lo óptimo es fácil?


corolarios de esta técnica:

- por cada retardo se usa 2 bandera + un condicional.
- se pueden reutilizar las banderas usadas en el timer.

Título: Re: otra forma de generar retardos con el Timer
Publicado por: marito en 29 de Marzo de 2012, 19:57:04
Hola Palitroquez!!!

Necesito hacerte una consulta acerca del Timer0. Lo he usado en el PIC16F876A, y me ha funcionado de manera correcta; pero al intentar usarlo en el 18F4550 no me ha resultado.

El código de mi aplicación es el que sigue

Código: [Seleccionar]
#include <18F4550.h>
#fuses HSPLL,NOMCLR,NOWDT,PROTECT,NOLVP,NODEBUG,USBDIV,PLL5,CPUDIV1,VREGEN
#use delay(clock=48000000)
#use rs232(baud=115200,xmit=pin_c6,rcv=pin_c7)//configuracion del puerto rs232 envia por pin_c6 y recibe por pin_c7
//#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7, parity=N, bits=8) //habilitacón y configuración del protocolo de comunicación RS232 a través del MAX232, usando el PIN_A1 para transmitir al PC y el PIN_A2 para recibir desde el pc

int ContadorGlobal=0;

//Interrupción por desbordamiento del Timer0 RTCC
#int_TIMER0
void TMR0_isr(void)
{
ContadorGlobal++;
clear_interrupt(int_RTCC);




void main()
{

//Configuración de las interrupciones
//SETUP_COUNTERS(RTCC_INTERNAL,RTCC_DIV_256); // TIMER0: Clock Interno, Presescaler 128
SETUP_TIMER_0(RTCC_INTERNAL|RTCC_DIV_256);
ENABLE_INTERRUPTS(INT_TIMER0);                // Habilito Interrupción RTCC
ENABLE_INTERRUPTS(GLOBAL);                // Habilito Interrupciones

float Tiempo,VarA;

while(true)
{
//Rutina para calcular el tiempo de ciclo y reseteo de variables para timer
printf(" Tiempo = %f", tiempo);//imprimo datos por el usb;
//delay_ms(100);
Tiempo=(float)(0.000000083*get_timer0()+0.005461333*ContadorGlobal);

VarA=get_timer0();
ContadorGlobal=0;
set_timer0(0);

       
}
}

Lo que intento hacer, es medir el tiempo de mi bucle, pero resulta que el contador global no se incrementa nunca, por lo cual supongo que no debe generarse la interrupción del Timer0. Lo he intentado con el contador RTCC y tampoco ha funcionado.

Se te ocurre alguna razón por la cual me suceda esto viendo el código?
Título: Re: otra forma de generar retardos con el Timer
Publicado por: AcoranTf en 30 de Marzo de 2012, 12:47:23
Muy buen hilo, precisamente ayer charlaba con Kallitos el modo de hacer algo parecido, utilizando un solo timer y sus interrupciones, controlar varios temporizadores.
Me llamo la atencion que siendo tan practico este hilo, haya quedado "olvidado" desde hace casi dos años.

Para Marito, creo que se te olvido crear la funcion de atencion a la interrupcion, aparte no veo claro el resto de tu programita.

Saludos.
Título: Re: otra forma de generar retardos con el Timer
Publicado por: marito en 30 de Marzo de 2012, 12:52:51
AcoranTf, atiendo la interrupción en esta parte:

Código: [Seleccionar]
 
#int_RTCC
void RTCC_isr(void)
{
ContadorGlobal++;
clear_interrupt(int_RTCC);
}  

 

Aqui incremento el contador global con el cual luego calculo el tiempo de ejecucion de mi bucle.

Te referías a eso?
Título: Re: otra forma de generar retardos con el Timer
Publicado por: AcoranTf en 30 de Marzo de 2012, 23:08:18
Si, me referia a eso, no lo habia visto. No obstante no te puedo ayudar, ya que yo estoy empezando con C y precisamente los timers e interrupciones aun no los domino.

Saludos.
Título: Re: otra forma de generar retardos con el Timer
Publicado por: Suky en 31 de Marzo de 2012, 00:10:02
Comparto la librería que desarrolle para C18: http://www.micros-designs.com.ar/c18-varias-temporizaciones-un-solo-timer/

Para ciertos proyectos es muy útil y se hace más practico y sencillo. Por ejemplo donde se necesiten activar alarmas temporizadas, que se activan si ocurre un evento por determinado tiempo, etc.. Para algo así la he utilizado con éxito  :)


marito, podes hacer un debug en Proteus o MPLAB SIM  ;-)


Saludos!
Título: Re: otra forma de generar retardos con el Timer
Publicado por: AcoranTf en 01 de Abril de 2012, 11:01:03
Gracias Suky, voy a estudiar tu libreria. ¿Hay muchas diferencias entre CCS y C18?. Pienso que estudiar codigo ya hecho, ayuda a aprender y en el caso de las librerias ayuda a entender distintas formas de hacer las cosas.

Saludos.
Título: Re: otra forma de generar retardos con el Timer
Publicado por: marito en 01 de Abril de 2012, 12:58:13
Hola Suky, estoy haciendo usando el debug en MPLAB Sim, pero todavía no consigo hacer que funcione el timer0. Tengo que seguir trabajando con esto!
Título: Re: otra forma de generar retardos con el Timer
Publicado por: marito en 01 de Abril de 2012, 13:28:17
He logrado medir el tiempo de mi ciclo de programa, pero solo con el preescaler del RTCC en 1.

Cual puede ser el motivo por el que sólo puedo usar el pre escaler en 1?

Código: [Seleccionar]
SETUP_TIMER_0(RTCC_DIV_1);
Título: Re: otra forma de generar retardos con el Timer
Publicado por: PalitroqueZ en 01 de Abril de 2012, 13:40:04
Hola marito

respecto a tu pregunta inicial, lo que se me ocurre es que te faltó añadir algo en la configuración del timer, porque en los 18F hay que añadir otros parámetros. no recuerdo bien, pero deberías averiguar si ese timer trabaja con 8bits o 16 bits

Título: Re: otra forma de generar retardos con el Timer
Publicado por: Suky en 01 de Abril de 2012, 14:30:46
Hola marito

respecto a tu pregunta inicial, lo que se me ocurre es que te faltó añadir algo en la configuración del timer, porque en los 18F hay que añadir otros parámetros. no recuerdo bien, pero deberías averiguar si ese timer trabaja con 8bits o 16 bits



Cierto, y en CCS en algunos casos si no se colocan todas las opciones del módulo se configura mal  :undecided:
Título: Re: otra forma de generar retardos con el Timer
Publicado por: marito en 01 de Abril de 2012, 16:48:14
Ok, voy a leer un poco el manual de CCS y las especificaciones del 18F4550. En un rato comento si encuentro algo!
Título: Re:otra forma de generar retardos con el Timer
Publicado por: mariacontenis en 03 de Enero de 2019, 12:36:55
Alguien se quedaría con la información de suky cuando puso es este mismo tema  http://www.micros-designs.com.ar/c18-varias-temporizaciones-un-solo-timer/     lo que pasa es que ya no está disponible esa í formación y me gustaría ver como lo pensó él hace tiempo para lograr el multi timer.
Título: Re:otra forma de generar retardos con el Timer
Publicado por: Mecátronica2012 en 02 de Agosto de 2019, 18:00:14
Desde hace algunos meses llevo implementando algo asi en mis programas con PIC, es algo similar a la funcion Mllis de arduino, incrementando una variable de tipo long, cada interrupcion del timer0, pero se me vienen varias interrogantes, es eficiente hacer esto? existira alguna otra alternativa para manejar eventos sin utilizar los dichosos delays()? Que pasaria por ejemplo si salta otra interrupcion distinta a la del timer0, podria afectarse mi medida de tiempo,?
Título: Re:otra forma de generar retardos con el Timer
Publicado por: KILLERJC en 02 de Agosto de 2019, 20:13:36
Contestando tus preguntas una a una:

es eficiente hacer esto?

- Siempre mas eficiente seria tener un Timer el cual pueda tener una interrupcion en el tiempo que desee como sucede en el caso de Timers de 32 bits. Tiene que tener algunas consideraciones, como carga o reset por hardware, y tambien estas sujeto a la frecuencia del cristal y su variacion.
Al no poseer un Timer que pueda interrumpir en esos tiempos, no queda otra que utilizar una base mas pequeña y contar las interrupciones.

Citar
existira alguna otra alternativa para manejar eventos sin utilizar los dichosos delays()?

- Varias cosas necesitan delays.. Especialmente las secuenciales, por ejemplo manejo el manejo del LCD, a no ser que tus señales sean lentas a comparacion del micro. Pero muchas veces se puede prescindir de estos con el costo agregado de mas programa. Por ejemplo si deseo enviar "HOLA" por UART, enves de enviar todo y quedarme esperando (tecnicamente no es un delay, pero si una espera hasta que termine) podrias hacer un buffer y que se maneje con la interrupcion de TX.
En caso de tener varias cosas con delays, si uno usa un RTOS, mientras una aplicacion pide un "delay" al OS, podria estar haciendo otra cosa...
Tambien es mejor tratar de crear un codigo que no requiera delays.... Por ejemplo si quisiera actualizar el LCD y luego cambiar el texto al segundo, entonces tener una funcion en el main
 que se encargue del LCD, adentro muestra lo que debe mostrar y acciona un mecanismo para que pregunte si paso el segundo (observando la variable del Timer) para volver a cambiar el LCD...
Como comente antes, a costa de la complejidad del programa.

Citar
Que pasaria por ejemplo si salta otra interrupcion distinta a la del timer0, podria afectarse mi medida de tiempo,?

Depende del microcontrolador que estes usando (marca y modelo)...

En un PIC16 es un poco mas complejo todas las posibilidades que podes tener.... El codigo de la interrupcion seria algo asi:

Si bandera Timer 0 = 1?
   -> Rutina de interrupcion Timer0
Si bandera RX UART = 1 ?
   -> Rutina de interrupcion RX UART

Las posibilidades son:
 - Ocurrio int de Timer0 y mientras esta ejecutandose Timer0 ocurre la de UART, no habria problema, ejecutaria una y luego la otra sin salir de la misma interrupcion
 - Ocurrio la de la UART y cuando esta haciendo la rutina ocurre la del Timer0, Cuando termina de la UART, sale de la interrupcion y vuelve a entrar para atender la del Timer0, ese es un poco de error que tendrias.

Si usas el modulo CCP, que te resetea el Timer, no tendrias que preocuparte por esto, y tenes una ventana entre interrupcion e interrupcion para hacer lo que debas hacer.

Si es un PIC18:

Tenes 2 prioridades, podes elegir que el Timer tenga prioridad alta, de esa forma si ocurre el 2do caso como en el PIC16, este se atienda sin falta, y luego siga la de baja prioridad como la de RX UART.. Si usas el modulo CCP, entonces no vas a tener problemas.

Si tenes un dsPIC/PIC32/STM32/etc

Ademas de tener MAS prioridades, tenes Timers que hacen lo que hacia el Timer+CCP en los PIC16/18 , por lo que resume mucho mas los problemas y errores.
Título: Re:otra forma de generar retardos con el Timer
Publicado por: Mecátronica2012 en 02 de Agosto de 2019, 21:53:00
Muchas gracias por la respuesta killerjc, tenía algún tiempo con esa duda, que pasaba si estando por ejemplo en la rutina de interrupción del tmr0, en ese instante se activará otra interrupción, gracias