TODOPIC
Microcontroladores PIC => Lenguaje C para microcontroladores PIC => Mensaje iniciado por: c4_esp_VR en 18 de Agosto de 2009, 07:43:28
-
Hola compañeros:
Estoy usando CCS e intentando que el timer1 del pic levante un pulso con un ton de 1500us cada 5ms (periodo), pero resulta que me levanta un pulso con un ton de 4500 y un periodo de 15 ms, si os fijais en los datos anteriores es como si el timer tuviera un prescaler de 1:3 que en ningún momento lo pongo por código. Aqui os dejo el código que son 4 línas por si veis que puede ocurrir.
#include <18F13K50.h>
#fuses HS, NOWDT, NOPROTECT, NOLVP
#fuses USBDIV1 //USB clock source comes from PLL no divide
#fuses CPUDIV1 //No System Clock Postscaler
#use delay(clock=40000000)
#define UNO PIN_C4
const long desbordamiento = 15536;//5.0mS
long t = desbordamiento+15000;//1500us de ton
int1 flag_1 = 0;
int1 flagRTCC_1 = 0;
long valTIMER=0; //Tiene que ser un long debido a que el timer1 es un long, timer0 es un int
#int_timer1 //Subrutina de interrupción por TIMER1
void isr_timer1(void)
{
flagRTCC_1=1;
set_timer1(desbordamiento);
}
//PROGRAMA PRINCIPAL
void main(void) {
setup_timer_1 ( T1_INTERNAL | T1_DIV_BY_1);
enable_interrupts(INT_TIMER1);
set_timer1(desbordamiento);
setup_ccp1(CCP_PWM); //ccp1 modo PWM
enable_interrupts(global);// Habilita interrupciones
while (TRUE)
{
if(flagRTCC_1==1)
{
flagRTCC_1=0;
output_high(UNO);
flag_1=1;
}
if(flag_1==1)
{
valTIMER=get_TIMER1();
if(valTIMER>t)//1,5ms
{
output_low(UNO);
flag_1=0;
}
}
}//Fin while(TRUE)
}//Fin main(void)
Creo que será algo del PLL del USB pero no logro saber que es por más que cambio los fuses, en este caso no quiero usar el usb para nada.
Por otro lado el programa funciona perfectamente en proteus pero no funciona en la placa real que tiene un cristal extrerno de 40Mhz con sus respectivos condensadores.
Adjunto dos imágenes, una del buen funcionamiento en proteus con el osci digital y otra de la configuración de bit
Llevo una mañana con esto y no hay manera...cualquier ayuda sería de agradecer compañeros.
Un saludete.
-
... en la placa real que tiene un cristal extrerno de 40Mhz con sus respectivos condensadores.
...
mira una pregunta ¿estas seguro que ese pic aguanta cristales de 40Mhz?
-
mira una pregunta ¿estas seguro que ese pic aguanta cristales de 40Mhz?
Si que los aguanta, al menos eso pone en el datasheet.
Flexible Oscillator Structure:
• CPU divider to run the core slower than the USB
peripheral
• 16 MHz Internal Oscillator Block:
- Software selectable frequencies, 31 kHz to
16 MHz
- Provides a complete range of clock speeds
from 31 kHz to 32 MHz when used with PLL
- User tunable to compensate for frequency
drift
• Four Crystal modes, up to 48 MHz
• External Clock modes, up to 48 MHz
• 4X Phase Lock Loop (PLL)
-
Hola, está difícil de encontrar el problema.
¿Puedes probar con otro micro corriendo a 40MHz pero que no tenga USB?
-
¿Puedes probar con otro micro corriendo a 40MHz pero que no tenga USB?
La verdad es que no dispongo de ningún pic que no tenga usb :( :( :(
De todas formas, me interesa saber que datos podemos sacar con esta comparación???
Muchas gracias.
-
Ah, descartarías que algún fuse USB te esté dando problemas con el tiempo. Si no funcionara en el micro sin usb entonces el problema andaría por otro lado.
-
la otra prueba es usar un cristal de 20MHz y ver si el timer -previamente configurado para el cristal- funciona correctamente.
-
Se me ocurre otra idea que talvez sea absurda pero no quisiera dejar de mencionarla :D
Separa esta función en 2:
setup_timer_1 ( T1_INTERNAL | T1_DIV_BY_1);
setup_timer_1 ( T1_INTERNAL);
setup_timer_1 ( T1_DIV_BY_1);
-
Viendo el asm generado por el código y mirando el datasheet las configuraciones del timer son correctas. :? Yo haría lo que comenta PalitroqueZ, cambiar el cristal y probar.
Saludos!
-
Se me ocurre otra idea que talvez sea absurda pero no quisiera dejar de mencionarla lol
La he probado y sigue sin funcionar :?
Voy a probar lo del cristal a 12Mhz ya que no tengo el de 20Mhz, pero imagino que el resultado será el mismo ya que el micro soporta ambos cristales, vamos a desoldar el cristal, ahora os comento.
Un saludete.
-
la otra prueba es usar un cristal de 20MHz y ver si el timer -previamente configurado para el cristal- funciona correctamente.
PRUEBAS CRISTAL DE 12MHz
Acabo de probar el siguiente código con un cristal de 12MHz
#include <18F13K50.h>
#rom int8 0x300000 = {0x00}//Cambia los fuses del USB,
#rom int8 0x300001 = {0x32}//Cambia los fuses del cristal que es equivalente a poner #fuses HS, PLLEN, PCLKEN
#use delay(clock=12000000)
#use rs232(baud=115200, xmit=PIN_B7, rcv=PIN_B5, stream=PC)
#define UNO PIN_C4
const long desbordamiento = 50536;//5ms
long t = desbordamiento+4500;//1500us de ton
int1 flag_1 = 0;
int1 flagRTCC_1 = 0;
long valTIMER=0; //Tiene que ser un long debido a que el timer1 es un long, timer0 es un int
#int_timer1 //Subrutina de interrupción por TIMER1
void isr_timer1(void)
{
flagRTCC_1=1;
set_timer1(desbordamiento);
}
//PROGRAMA PRINCIPAL
void main(void) {
setup_timer_1 ( T1_INTERNAL | T1_DIV_BY_1);
enable_interrupts(INT_TIMER1);
set_timer1(desbordamiento); //Vtmr1 = 65536 - (1s * ( 12000000Hz / 4 ) / prescaler ) 200us -> Vtmr1=5536 set_timer1(0x15A0);
setup_ccp1(CCP_PWM); //ccp1 modo PWM //Si lo ponemos arriba me da que no funciona, siempre va primero la declaración de variables
enable_interrupts(global);// Habilita interrupciones
while (TRUE)
{
if(flagRTCC_1==1)
{
flagRTCC_1=0;
output_high(UNO);
flag_1=1;
}
if(flag_1==1)
{
valTIMER=get_TIMER1();
if(valTIMER>t)//1,5ms->10036 0.5ms->7036 0.1ms->5836 2.3ms->12436 set_timer1(0x15A0); MAX->33500 MIN->10500
{
output_low(UNO);
flag_1=0;
}
}
//Fin Para el servo1
}//Fin while(TRUE)
}//Fin main(void)
Dándome como resultado un ton de 370us y un periodo de 1250us. Lógicamente lo vuelvo a poner en el proteus pero esta vez con un cristal de 12MHz y funciona perfectamente...
Ahora probando el siguiente código, que es idéntico al anterior sólo que cambiando los fuses:
#include <18F13K50.h>
#fuses HS, NOWDT, NOPROTECT, NOLVP
#fuses USBDIV1 //USB clock source comes from PLL no divide
#fuses CPUDIV1 //No System Clock Postscaler
//Estos fuses son equivalentes a #rom int8 0x300000 = {0x00} y #rom int8 0x300001 = {0xC2}
#use delay(clock=12000000)
#use rs232(baud=115200, xmit=PIN_B7, rcv=PIN_B5, stream=PC)
#define UNO PIN_C4
const long desbordamiento = 50536;//5ms
long t = desbordamiento+4500;//1500us de ton
int1 flag_1 = 0;
int1 flagRTCC_1 = 0;
long valTIMER=0; //Tiene que ser un long debido a que el timer1 es un long, timer0 es un int
#int_timer1 //Subrutina de interrupción por TIMER1
void isr_timer1(void)
{
flagRTCC_1=1;
set_timer1(desbordamiento);
}
//PROGRAMA PRINCIPAL
void main(void) {
setup_timer_1 ( T1_INTERNAL | T1_DIV_BY_1);
enable_interrupts(INT_TIMER1);
set_timer1(desbordamiento); //Vtmr1 = 65536 - (1s * ( 12000000Hz / 4 ) / prescaler ) 200us -> Vtmr1=5536 set_timer1(0x15A0);
setup_ccp1(CCP_PWM); //ccp1 modo PWM //Si lo ponemos arriba me da que no funciona, siempre va primero la declaración de variables
enable_interrupts(global);// Habilita interrupciones
while (TRUE)
{
if(flagRTCC_1==1)
{
flagRTCC_1=0;
output_high(UNO);
flag_1=1;
}
if(flag_1==1)
{
valTIMER=get_TIMER1();
if(valTIMER>t)//1,5ms->10036 0.5ms->7036 0.1ms->5836 2.3ms->12436 set_timer1(0x15A0); MAX->33500 MIN->10500
{
output_low(UNO);
flag_1=0;
}
}
//Fin Para el servo1
}//Fin while(TRUE)
}//Fin main(void)
Funciona perfectamente con un cristal de 12MHz, es decir un ton=1500us y periodo=5000us
PRUEBAS CRISTAL DE 40MHz
#include <18F13K50.h>
#rom int8 0x300000 = {0x00}//Cambia los fuses del USB,
#rom int8 0x300001 = {0x32}//Cambia los fuses del cristal que es equivalente a poner #fuses HS, PLLEN, PCLKEN
#use delay(clock=40000000)
#use rs232(baud=115200, xmit=PIN_B7, rcv=PIN_B5, stream=PC)
#define UNO PIN_C4
const long desbordamiento = 15536;//5ms
long t = desbordamiento+15000;//1500us de ton
int1 flag_1 = 0;
int1 flagRTCC_1 = 0;
long valTIMER=0; //Tiene que ser un long debido a que el timer1 es un long, timer0 es un int
#int_timer1 //Subrutina de interrupción por TIMER1
void isr_timer1(void)
{
flagRTCC_1=1;
set_timer1(desbordamiento);
}
//PROGRAMA PRINCIPAL
void main(void) {
setup_timer_1 ( T1_INTERNAL | T1_DIV_BY_1);
enable_interrupts(INT_TIMER1);
set_timer1(desbordamiento); //Vtmr1 = 65536 - (1s * ( 12000000Hz / 4 ) / prescaler ) 200us -> Vtmr1=5536 set_timer1(0x15A0);
setup_ccp1(CCP_PWM); //ccp1 modo PWM //Si lo ponemos arriba me da que no funciona, siempre va primero la declaración de variables
enable_interrupts(global);// Habilita interrupciones
while (TRUE)
{
if(flagRTCC_1==1)
{
flagRTCC_1=0;
output_high(UNO);
flag_1=1;
}
if(flag_1==1)
{
valTIMER=get_TIMER1();
if(valTIMER>t)//1,5ms->10036 0.5ms->7036 0.1ms->5836 2.3ms->12436 set_timer1(0x15A0); MAX->33500 MIN->10500
{
output_low(UNO);
flag_1=0;
}
}
//Fin Para el servo1
}//Fin while(TRUE)
}//Fin main(void)
Dando como resultado un periodo de 3750us y un ton de 1125us
Con el siguiente código
#include <18F13K50.h>
#fuses NOWDT, NOPROTECT, NOLVP
#fuses HS
#fuses USBDIV1 //USB clock source comes from PLL no divide
#fuses CPUDIV1 //No System Clock Postscaler
#use delay(clock=40000000)
#use rs232(baud=115200, xmit=PIN_B7, rcv=PIN_B5, stream=PC)
#define UNO PIN_C4
const long desbordamiento = 15536;//5ms
long t = desbordamiento+15000;//1500us de ton
int1 flag_1 = 0;
int1 flagRTCC_1 = 0;
long valTIMER=0; //Tiene que ser un long debido a que el timer1 es un long, timer0 es un int
#int_timer1 //Subrutina de interrupción por TIMER1
void isr_timer1(void)
{
flagRTCC_1=1;
set_timer1(desbordamiento);
}
//PROGRAMA PRINCIPAL
void main(void) {
setup_timer_1 ( T1_INTERNAL | T1_DIV_BY_1);
enable_interrupts(INT_TIMER1);
set_timer1(desbordamiento); //Vtmr1 = 65536 - (1s * ( 12000000Hz / 4 ) / prescaler ) 200us -> Vtmr1=5536 set_timer1(0x15A0);
setup_ccp1(CCP_PWM); //ccp1 modo PWM //Si lo ponemos arriba me da que no funciona, siempre va primero la declaración de variables
enable_interrupts(global);// Habilita interrupciones
while (TRUE)
{
if(flagRTCC_1==1)
{
flagRTCC_1=0;
output_high(UNO);
flag_1=1;
}
if(flag_1==1)
{
valTIMER=get_TIMER1();
if(valTIMER>t)//1,5ms->10036 0.5ms->7036 0.1ms->5836 2.3ms->12436 set_timer1(0x15A0); MAX->33500 MIN->10500
{
output_low(UNO);
flag_1=0;
}
}
//Fin Para el servo1
}//Fin while(TRUE)
}//Fin main(void)
Dando como resultado un periodo de 15.000us y un ton de 4500us
Haciendo un resumen rápido de las pruebas realizadas:
12 MHz 40MHz
#rom int8 0x300000 = {0x00} ton=370us Periodo=1250us ton=1125us Periodo=3750us
#rom int8 0x300001 = {0x32}
#rom int8 0x300000 = {0x00} ton=1500us Periodo=5000us ton=4500us Periodo=15000us
#rom int8 0x300001 = {0xC2}
A este paso voy a tener que llamar a Fox Malder y a Dana Scully :( :( :(, no tengo ni idea de lo que puede estar pasando con el cristal de 40Mhz...
Cualquier sugerencia me vendría bien, lo malo es que me hace falta usar el de 40MHz para que el timer sea lo más preciso posible :? :?
Muchas gracias compañeros.
-
yo creo que la respuesta viene a que ese pic no acepta cristales de 40MHz, por aquí hay un post del amigo pocher que hizo unas pruebas con el 18F4550 y no pasó mas allá de 24MHz.
es decir el cristal solo no funcionará, para esa frecuencia debes usar una fuente de oscilación externa como por ejemplo un oscilador controlado por cristal XCO
-
yo creo que la respuesta viene a que ese pic no acepta cristales de 40MHz, por aquí hay un post del amigo pocher que hizo unas pruebas con el 18F4550 y no pasó mas allá de 24MHz.
es decir el cristal solo no funcionará, para esa frecuencia debes usar una fuente de oscilación externa como por ejemplo un oscilador controlado por cristal XCO
La verdad, es que no te entiendo porque tengo un cristal de cuarzo externo, no estoy usando el interno del PIC, aún así en el datasheet pone que aguanta hasta cristales de 48MHz...Pero de todas formas si puedes explicarme más detalladamente a que te refieres sería de agradecer.
Muchas gracias.
-
encontré el post de pocher:
http://www.todopic.com.ar/foros/index.php?topic=21474.0
yo leí el datasheet del 18F13K50 y no hallé donde dijera que se le puede conectar un cristal de 40MHz, eso que dice la datasheet es que puede llegar hasta 48MHz usando el PLL interno. (de hecho necesitarías un cristal de 12MHz para llegar a 48MHz que es el único en el rango de los 40MHz)
-
La verdad es que lo pone en varios sitios en el datasheet.
Sin ir más lejos en el resumen de las carateristicas del pic en la página 3 pone:
External Clock modes, up to 48 MHz
En el punto del usb hay una tabla que relaciona el clock con el PLL y una de ellas es poner un cristal externo de 48Mhz son PLL y sin usbdiv:
Clock Mode Clock Frequency 4x PLL Enabled CPUDIV<1:0> System Clock Frequency (MHz)
EC High 48 MHz No 00 48
01 24
10 16
11 12
Y otro punto que lo cita es en el 2.3.4 External clock que pone:
EC Low power 0 – 250 kHz
EC Medium power 250 kHz – 4 MHz
EC High power 4 – 48 MHz
Por lo que imagino que si soportará hasta 48MHz...
-
...
External Clock modes, up to 48 MHz
Clock Mode Clock Frequency 4x PLL Enabled CPUDIV<1:0> System Clock Frequency (MHz)
EC High 48 MHz No 00 48
01 24
10 16
11 12
Y otro punto que lo cita es en el 2.3.4 External clock que pone:
EC Low power 0 – 250 kHz
EC Medium power 250 kHz – 4 MHz
EC High power 4 – 48 MHz
...
ajá, exactamente. Observa que dice Clock Mode y no Crystal Mode. Clock mode significa que se puede conectar una fuente osciladora externa, es decir, el modulo oscilador interno cambiaría su circuito que usa con el cristal (el que forma el oscilador) y dejaría "una línea directa" para recibir el pulso de clock ya generado externamente.
por lo menos así lo entiendo yo, -espero no equivocarme jeje-
de todas formas usar un cristal de 40MHz yo lo veo como demasiado, si estas usando un timer que trabaja con el clock del CPU, entonces deberías usar el PLL. Es posible trabajar el pic a 48MHz y desactivar el modulo USB (aunque entiendo que quieres son 40Mhz y estaríamos volviendo al problema inicial) :(
-
Amigos, lo dice la datasheet, en su página 375: máximo cristal 20MHz, o sea, como en todos los PIC :mrgreen:
(http://img199.imageshack.us/img199/5752/oscilador40mhz.jpg)
-
gracias Manolo (intenté y no pude hallar ese dato) :)
-
Hola compañeros:
La verdad es que no sabia que diferencia había entre EC (External Clock) y el Oscilator frequency.
Entonces si yo pongo un cristal de 12MHz y le pongo un PLL x 4, el pic irá internamente a 48MHz, esto es, ejecutará una instrucción cada 4 ciclos de reloj es decir cada 83 ns ( 48/4 = 12MHz => 1/12MHz = 0.083 us = 83 ns ) o ¿ el PLL sólo sirve para el usb ?
En este caso lo que más me interesa es que el micro haga las intrucciones lo más rápido posible, con lo que ahora mismo ya no sé cual es la mejor posibilidad.
Muchas gracias por la ayuda e interes que estais mostrando, como siempre sois un gran foro.
Un saludete.
-
...Entonces si yo pongo un cristal de 12MHz y le pongo un PLL x 4, el pic irá internamente a 48MHz, esto es, ejecutará una instrucción cada 4 ciclos de reloj es decir cada 83 ns ( 48/4 = 12MHz => 1/12MHz = 0.083 us = 83 ns )
...
¡exactamente!, esa duda la tuve alguna vez:
http://www.todopic.com.ar/foros/index.php?topic=21033.msg162814#msg162814
la etapa del bloque oscilador se antepone al modulo USB y al CPU, el cpu es el PiC propiamente hablando.
-
Entonces, si lo he entendido bien, con esta afirmación entiendo que la CPU de nuestro micro será el puesto en código del CCS como
#use delay(clock=48000000)
Aunque le pongamos un cristal físico de 12MHz
¿He entendido bien?
Un saludete y gracias.
Acabo de probar un programa con un cristal de 12MHz, poniendole un 4xPLL y la instrucción en el código de #use delay(clock=48000000) y el temporizador va a la perfección con los datos puestos como si estubiese funcionando a una frecuencia de 48MHz.
-
Tuve un problema parecido con un 18F2550 al querer hacerlo correr a 48mhz sin usar su PLL interno (porque consume mas). Puse cristal de cuarzo de dos patas (el tipico) al pic y no funciono, luego me di cuenta que en el datasheet decia que SI acepta externo de 48mhz PERO externo externo xD, ocea de esos que son de 4 pines y uno de ellos va al pic: oscilador externo, no cristal.
Bueno pues eso, exitos.
Salu2.
-
Tuve un problema parecido con un 18F2550 al querer hacerlo correr a 48mhz sin usar su PLL interno (porque consume mas). Puse cristal de cuarzo de dos patas (el tipico) al pic y no funciono, luego me di cuenta que en el datasheet decia que SI acepta externo de 48mhz PERO externo externo xD, ocea de esos que son de 4 pines y uno de ellos va al pic: oscilador externo, no cristal.
Yo pensaba que esos de los 4 pines son osciladores como los de 2 pero que tienen una alimentación que les hacen ser más precisos incluso a temperaturas más altas...¿estaba equivocado entonces...?
-
Entonces, si lo he entendido bien, con esta afirmación entiendo que la CPU de nuestro micro será el puesto en código del CCS como
#use delay(clock=48000000)
Aunque le pongamos un cristal físico de 12MHz
¿He entendido bien?
...
sip, has entendido bien :)
-
Hola compañeros:
Ante todo muchas gracias por la ayuda. Ya me ha quedado mucho más claro el tema de los cristales de los micros y el porqué no me funcionaba el pic.
Como siempre estais aquí pa arrimar el hombro y compartir vuestras experiencias.
Un saludete foreros. :-/ :-/ :-/