TODOPIC
Microcontroladores PIC => Lenguaje C para microcontroladores PIC => Mensaje iniciado por: fr4n en 30 de Mayo de 2011, 05:53:48
-
Hola a todos, estoy usando un PIC 18F4550. Programo en C usando CCS.
Mi PIC funciona a 48 MHz (usando un cristal de 20 MHz)
He estado buscando información el foro sobre el tema de los timers, pero no me queda claro.
Necesito una interrupción cada 16us (microsegundos) y he visto que se usa esta fórmula:
Fdesborde=Fosc/(4*preescaler*VAL)] en el caso del timer0.
Me da igual usar un timer u otro, solo necesito que se interrumpa cada 16us, pero no entiendo que valores debo meter para cargar ese tiempo.
No se que valor de prescaler poner ni de "VAL", no se si servirá de algo, pero tengo usando estos fuses, no se si alguno indica el prescaler que se está usando:
#FUSES LPT1OSC //Timer1 configured for low-power operation
#FUSES NOXINST //Extended set extension and Indexed Addressing mode disabled (Legacy mode)
#FUSES PLL5 //Divide By 5(20MHz oscillator input)
#FUSES CPUDIV1 //No System Clock Postscaler
#FUSES USBDIV //USB clock source comes from PLL divide by 2
¿Que valor le tengo que cargar? o como lo calculo realmente?
Muchas gracias!
-
Hola a todos, estoy usando un PIC 18F4550. Programo en C usando CCS.
Mi PIC funciona a 48 MHz (usando un cristal de 20 MHz)
He estado buscando información el foro sobre el tema de los timers, pero no me queda claro.
Necesito una interrupción cada 16us (microsegundos) y he visto que se usa esta fórmula:
Fdesborde=Fosc/(4*preescaler*VAL)] en el caso del timer0.
Me da igual usar un timer u otro, solo necesito que se interrumpa cada 16us, pero no entiendo que valores debo meter para cargar ese tiempo.
No se que valor de prescaler poner ni de "VAL", no se si servirá de algo, pero tengo usando estos fuses, no se si alguno indica el prescaler que se está usando:
#FUSES LPT1OSC //Timer1 configured for low-power operation
#FUSES NOXINST //Extended set extension and Indexed Addressing mode disabled (Legacy mode)
#FUSES PLL5 //Divide By 5(20MHz oscillator input)
#FUSES CPUDIV1 //No System Clock Postscaler
#FUSES USBDIV //USB clock source comes from PLL divide by 2
¿Que valor le tengo que cargar? o como lo calculo realmente?
Muchas gracias!
f4n mas allá del cálculo, tener una interrupción cada 16us a un micro andando a 48mhz, estamos hablando de algo así como 83nano segundos, eso te da unas 200 instrucciones (del assembly generado por el compilador) entre interrupción e interrupción lo cual es realmente muy poco si quieres hacer algo en el hilo principal del programa
No obstante ahi tienes el valor, si cargas el timer con un valor de 190 (ten en cuenta que tenes unas instrucciones para atendern al interrupcion y llegar al vector de atención del timer) debieras estar ok
-
Creo la formula se entiende mejor de la siguiente manera:
Temporización = Ciclo de instrucción. (256-TMR0) .Divisor de Frecuencia
Ciclo de instrucción es Fosc/4, Fosc= Frecuencia del oscilador (48Mhz en este caso)
Divisor de Frecuencia es el preescaler seleccionado, si no sabes que es hay que leer el datasheet o algún articulo donde explique como funciona el timer.
Este caso es configurando el timer a 8-bits más que suficiente para tu caso, pero analiza lo que te ha comentado maunix.
Saludos!
-
Es precisamente lo del prescaler lo que no entiendo en lo que he ido leyendo.
Respecto a la interrupción, una vez que la activo, el programa principal solo tiene que ir comprobando 4 cosas.
Gracias!
-
En resumen, el pre-escaler es un valor seleccionable según el timer seleccionado, que permite dividir la frecuencia se la señal que incrementa el conteo del timer. Entonces, si se coloca 8, deben pasar 8 clocks para que el timer se incremente en 1.
Revisa las figuras del datasheet, es un diagrama en bloques, donde primero se selecciona la fuente a contar, luego viene el pre-escaler y después el timer.
Saludos!
-
Entonces mi pre-escaler, deberá ser uno, porque si son periodos muy cortos de tiempo, no me interesa que tengan que pasar más clocks aun para que incremente, no?
Saludos!
-
Entonces mi pre-escaler, deberá ser uno, porque si son periodos muy cortos de tiempo, no me interesa que tengan que pasar más clocks aun para que incremente, no?
Saludos!
Es una opción, los cálculos lo confirmarán ;-)
-
Muchisimas gracias ;)
Y si quiero usar el timer1 en lugar del timer0? ¿cual es mas recomendable para este menester?
Saludos!
-
Muchisimas gracias ;)
Y si quiero usar el timer1 en lugar del timer0? ¿cual es mas recomendable para este menester?
Saludos!
El timer 2 :D Porque, fijas PR2 y no tienes que estar actualizando el valor del timer. En este timer el valor máximo lo fija PR2, o sea cuenta desde 0 hasta PR2 y se resetea y ocurre la interrupción.
Si ya lo utilizas para otra cosa, cualquiera de los 2 timer da igual.
Saludos!
-
Oye, muchas gracias por contesar tan rápido :)
No contemplé el uso del timer2, porque es el que menos entendí :oops:
Aun asi, con respecto al calculo del timer0, el valor que me sale es incoherente (256-3,3x10^-13):
Temporizacion=16us
Ciclo de instrucción=48Mhz (o quizás los 20Mhz del cristal que estoy usando?)
Divisor de frecuencia=1
¿Cual es el error? :oops:
-
Ciclo de instrucción=48Mhz (o quizás los 20Mhz del cristal que estoy usando?)
Ciclo de instrucción es Fosc/4, Fosc= Frecuencia del oscilador (48Mhz en este caso)
Estás implementando mal el calculo.
saludos!
-
Sigo implementandolo mal porque ahora me da 256-1,3x10^-12
No será?:
Ciclo de instrucción=4/Fosc? :shock:
bueno, el valor que me sale tomando como ciclo de instrucción=4/48Mhz, es TMR0=64, es coherente, pero ¿es correcto?
Gracias!^^
-
Ciclo de instrucción=4/Fosc? :shock:
:? ¡Es lo que estoy colocando!
Ahora podrías utilizar algunas herramientas como proteus o MPLAB SIM como para comprobar si lo que haz hecho corresponde... Es necesario entender como funciona el microcontrolador, lee el datasheet y los variados artículos que hay al respecto.
Saludos!
-
Ciclo de instrucción=4/Fosc? :shock:
:? ¡Es lo que estoy colocando!
Yo pensaba que decias lo inverso, Fosc/4... 8)
Creo la formula se entiende mejor de la siguiente manera:
Temporización = Ciclo de instrucción. (256-TMR0) .Divisor de Frecuencia
Ciclo de instrucción es Fosc/4, Fosc= Frecuencia del oscilador (48Mhz en este caso)
Divisor de Frecuencia es el preescaler seleccionado, si no sabes que es hay que leer el datasheet o algún articulo donde explique como funciona el timer.
Este caso es configurando el timer a 8-bits más que suficiente para tu caso, pero analiza lo que te ha comentado maunix.
Saludos!
Muchisimas gracias por responder! :)
investigaré para comprobar que no he metido la pata.
Por cierto el pres-escaler, en que parte o en que fuse se configura? solo en el "setup_timer_0()"?? en mi caso, como quedaria?
setup_timer_0(rtcc_external | rtcc_div_1);????
Muchas gracias!
Saludos!
-
Suku , fr4n tiene razón, le pifiaste al principio... la formula se puede expresar en una igualdad de frecuencias o en una igualdad de tiempos (períodos o ciclos) en tu caso fr4n como dices que quieres fijar 16us suky te expresó la fórmula en el dominio del tiempo por decirlo de alguna manera:
Temporización = Ciclo de instrucción. (256-TMR0) .Divisor de Frecuencia
despejando paso a paso...
(256-TMR0) = Temporización / (ciclo de instrucción * Divisor de frecuencia)
(256-TMR0) = Temporización / (4/Fosc * Divisor de frecuencia)
(256-TMR0) = Temporización * Fosc / (4 * Divisor de frecuencia)
TMR0 = 256 - ( Temporización * Fosc / (4 * Divisor de frecuencia) )
TMR0 = 256 - ( 16us * 48Mhz / (4 * 1) )
TMR0 = 256 - ( 768 / (4 * 1) )
TMR0 = 256 - ( 192) = 64
en teoría ese sería el valor a usar, pero pasa que desde que ocurre la interrupción hasta que se produce el salto a la subrutina y se carga nuevamente este valor pasan 2 o 3 ciclos de instrucción que "se pierden" es decir es tiempo que transcurre en el que no estás contándolo por ello se debe ajustar el valor y en lugar de 64 poner 66 es una opción pero no estoy muy seguro del valor de este ajuste y además depende de algunos otros aspectos como ser si el micro permite interumpir a una interrupción en el caso de que trabajes con más de un vector de interrupción y que lo primero que hagas en la subrutina sea cargar el nuevo valor del TMR0, además CCS incluye unos comandos para la atención de las interrupciones que se colocan previos a la subrutina que infieren en los tiempos finales.
-
Gracias!
64 es el valor que me salió a mi!
pero con respecto a la configuración (sobre todo en el tema del pre-escaler) ¿es correcto lo que puse o esta mal?
Saludos!
-
setup_timer_0(rtcc_external | rtcc_div_1);????
me parece que es correcto, creo, si mal no recuerdo que al timer0 lo podés llamar rtcc o timer0 por igual, da lo mismo, el compilador de ccs mantiene compatibilidad con esas sintaxis.
Si no necesitas mucha exactitud en los 16us que pongas 64 no afecta demasiado, igual yo pondría al menos 66
Saludos
-
Entonces el tema del pre-escaler no aparece en ningun tipo de fuse?
Gracias!
-
Tienen razón! Yo puse Fosc/4 y veia siempre 4/Fosc :shock: Y eso que es lunes! :z)
setup_timer_0(rtcc_external | rtcc_div_1);????
No, esta mal, o sea vas a usar los ciclos interno del microcontrolador y allí colocas externos. Además es necesario fijar en 8-bits al timer, revisa el archivo *.h del microcontrolador para ver las opciones y compáralo con lo que dice el datasheet. POR FAVOR LÉELO!!! :8}
Busca ejemplos en el foro, hay muchos!
Saludos!
-
Trato de leerlo, pero el inglés no es mi fuerte y busco ejemplos, por eso habia llegado a esa conclusión.
Ha puesto externo porque uso un cristal externo y no el interno, eso es lo que yo habia entendido :oops:
y no puse lo de 8 bits porque habia leido en otro hilo que por defecto eran 8 y que no hacia falta ponerlo... eso si, creo que se trabata de un pic16
estoy buscando y trato de aprender, muchas gracias por tener tanta paciencia conmigo :)
Gracias, saludos!
-
Tienen razón! Yo puse Fosc/4 y veia siempre 4/Fosc :shock: Y eso que es lunes! :z)
jajajaja como cuando busco las llaves y las tengo en las manos :D
Disculpen, suky tiene razón, sería así:
setup_timer_0(T0_INTERNAL | T0_DIV_1 | T0_8_BIT);
No llores suky, cuando se empieza la mayoría quiere volar sin chequear si se tienen alas y sin saber carretear siquiera, yo al menos también era así y sigo siéndolo cuesta ponerse por el camino lento pero seguro cuando quieres echar a andar algo YA!!!
Pero es lo mejor compañero pancho, el .h está en la carpeta de instalación del CCS (PICC\Device\18f4550.h) allí están todos los fuses válidos y todas las configuraciones posibles para los timer entre todas las demás cosas... y bueno el pdf del pic supongo que ya lo tienes, jeje.
-
Esta bien, el tema es que hay que separar lo que es configuración del oscilador principal del sistema y el timer. El timer puede utilizar los ciclos de reloj interno (Sin importar si se usa cristal externo o el oscilador interno) o contar eventos que sucedan externamente mediante un pin I/O. Por ejemplo para Timer0 es el pin RA4.
Entonces tu tienes que colocar interno, asegurarte que se ha 8-bits, pre-escaler en 1. Luego cargar TMR0 con 64, esperar que ocurra la interrupción y allí volver a cagar el timer con 64, así se produce cada ~16us según lo calculado.
Edit: Exactamente como indica Menta.
Saludos!
-
Muchas gracias a los 2!
Si, ya habia visto todos los fuses del .h, la cosa es que tenia un poco de lios con lo que ha explicado Suky y con el inglés, pues necesitaba aclararme un poco jeje
Saludos!
-
Hola amigos.
Por si ayuda. la traducción del Datasheet. No está completo pero va.
http://es.scribd.com/doc/50824079/datasheet-pic18f4550-espanol
Saludos.
Jukinch
-
Hola amigos.
Por si ayuda. la traducción del Datasheet. No está completo pero va.
http://es.scribd.com/doc/50824079/datasheet-pic18f4550-espanol
Saludos.
Jukinch
genial, es mi sueño!!
Muchas gracias! ^^