Autor Tema: Timer "corrupto" en micros con USB SOLUCIONADO  (Leído 5747 veces)

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

Desconectado c4_esp_VR

  • Colaborador
  • PIC24F
  • *****
  • Mensajes: 735
    • www.muchotrasto.com
Timer "corrupto" en micros con USB SOLUCIONADO
« 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.

Código: [Seleccionar]
#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.
« Última modificación: 27 de Agosto de 2009, 18:38:18 por c4_esp_VR »

Desconectado PalitroqueZ

  • Moderadores
  • DsPIC33
  • *****
  • Mensajes: 5474
    • Electrónica Didacta
Re: Timer "corrupto" en micros con USB
« Respuesta #1 en: 18 de Agosto de 2009, 12:04:58 »
... 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?

La propiedad privada es la mayor garantía de libertad.
Friedrich August von Hayek

Desconectado c4_esp_VR

  • Colaborador
  • PIC24F
  • *****
  • Mensajes: 735
    • www.muchotrasto.com
Re: Timer "corrupto" en micros con USB
« Respuesta #2 en: 18 de Agosto de 2009, 14:54:39 »
Citar
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)

Desconectado migsantiago

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 8257
    • Sitio de MigSantiago
Re: Timer "corrupto" en micros con USB
« Respuesta #3 en: 19 de Agosto de 2009, 16:01:55 »
Hola, está difícil de encontrar el problema.

¿Puedes probar con otro micro corriendo a 40MHz pero que no tenga USB?

Desconectado c4_esp_VR

  • Colaborador
  • PIC24F
  • *****
  • Mensajes: 735
    • www.muchotrasto.com
Re: Timer "corrupto" en micros con USB
« Respuesta #4 en: 20 de Agosto de 2009, 02:54:12 »
Citar
¿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.

Desconectado migsantiago

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 8257
    • Sitio de MigSantiago
Re: Timer "corrupto" en micros con USB
« Respuesta #5 en: 20 de Agosto de 2009, 12:29:14 »
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.

Desconectado PalitroqueZ

  • Moderadores
  • DsPIC33
  • *****
  • Mensajes: 5474
    • Electrónica Didacta
Re: Timer "corrupto" en micros con USB
« Respuesta #6 en: 20 de Agosto de 2009, 17:29:53 »
la otra prueba es usar un cristal de 20MHz y ver si el timer -previamente configurado para el cristal- funciona correctamente.

La propiedad privada es la mayor garantía de libertad.
Friedrich August von Hayek

Desconectado migsantiago

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 8257
    • Sitio de MigSantiago
Re: Timer "corrupto" en micros con USB
« Respuesta #7 en: 20 de Agosto de 2009, 19:50:33 »
Se me ocurre otra idea que talvez sea absurda pero no quisiera dejar de mencionarla  :D

Separa esta función en 2:

Código: [Seleccionar]
setup_timer_1 ( T1_INTERNAL | T1_DIV_BY_1);
Código: [Seleccionar]
setup_timer_1 ( T1_INTERNAL);
setup_timer_1 ( T1_DIV_BY_1);

Desconectado Suky

  • Moderador Local
  • DsPIC33
  • *****
  • Mensajes: 6758
Re: Timer "corrupto" en micros con USB
« Respuesta #8 en: 20 de Agosto de 2009, 21:28:25 »
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!
No contesto mensajes privados, las consultas en el foro

Desconectado c4_esp_VR

  • Colaborador
  • PIC24F
  • *****
  • Mensajes: 735
    • www.muchotrasto.com
Re: Timer "corrupto" en micros con USB
« Respuesta #9 en: 21 de Agosto de 2009, 03:06:39 »
Citar
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.

Desconectado c4_esp_VR

  • Colaborador
  • PIC24F
  • *****
  • Mensajes: 735
    • www.muchotrasto.com
Re: Timer "corrupto" en micros con USB
« Respuesta #10 en: 21 de Agosto de 2009, 04:11:29 »
Citar
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

Código: [Seleccionar]
#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:

Código: [Seleccionar]
#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

Código: [Seleccionar]
#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

Código: [Seleccionar]
#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.


Desconectado PalitroqueZ

  • Moderadores
  • DsPIC33
  • *****
  • Mensajes: 5474
    • Electrónica Didacta
Re: Timer "corrupto" en micros con USB
« Respuesta #11 en: 21 de Agosto de 2009, 17:06:38 »
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 propiedad privada es la mayor garantía de libertad.
Friedrich August von Hayek

Desconectado c4_esp_VR

  • Colaborador
  • PIC24F
  • *****
  • Mensajes: 735
    • www.muchotrasto.com
Re: Timer "corrupto" en micros con USB
« Respuesta #12 en: 21 de Agosto de 2009, 17:14:02 »
Citar
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.

Desconectado PalitroqueZ

  • Moderadores
  • DsPIC33
  • *****
  • Mensajes: 5474
    • Electrónica Didacta
Re: Timer "corrupto" en micros con USB
« Respuesta #13 en: 21 de Agosto de 2009, 17:32:06 »
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 propiedad privada es la mayor garantía de libertad.
Friedrich August von Hayek

Desconectado c4_esp_VR

  • Colaborador
  • PIC24F
  • *****
  • Mensajes: 735
    • www.muchotrasto.com
Re: Timer "corrupto" en micros con USB
« Respuesta #14 en: 21 de Agosto de 2009, 18:35:08 »
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...