TODOPIC

Microcontroladores PIC => dsPIC => Mensaje iniciado por: venturi en 04 de Octubre de 2012, 10:23:35

Título: dsPIC33FJ256GP710 No obedece bien al tiempo de interrupción
Publicado por: venturi en 04 de Octubre de 2012, 10:23:35
Hola a todos. Estoy empezando con los dspic y tengo el siguiente problema a ver si alguien me puede ayudar.

Como no entiendo muy bien como se hace la configuración del oscilador cojí la común que viene de microchip para funcionar a 40 MIPS. A la hora de comprobar que el dsPIC33FJ256GP710 funcionaba correctamente programé un reloj en tiempo real, pero me variaba del orden de un segundo cada dos minutos.

Para comprobar que ocurría hice el siguiente programa en donde cada 10 us el led se enciende y se apaga en una placa EXPLORER 16. Lo monitoricé con el osciloscopio y me salía que en vez de cada 10 us se encendía y se apagaba cada 12 us. Me parece que un error del 20% es una pasada para un XT y más cuando en un 18F4550 el reloj en tiempo real se me iba del orden de dos segundos al día. En el MPLAB SIM me simula bien.

Me gustaría que alguien me dijera si hay un error en el programa o que pudiera comprobar si a él le ocurre lo mismo en la realidad.

Gracias de antemano.



#include <p33FJ256GP710.h>

//Primera parte de la configuración del oscilador a 40 Mips. Esta copiada pero no está entendida del todo. Para entenderla mirar el fichero de cabecera del pic
_FOSCSEL(FNOSC_FRC); // Internal FRC oscillator
_FOSC(FCKSM_CSECMD & OSCIOFNC_OFF & POSCMD_NONE); // Clock Switching is enabled and Fail Safe Clock Monitor is disabled
// OSC2 Pin Function: OSC2 is Clock Output
// Primary Oscillator Mode: XT Crystanl

/* Esto de abajo no funciona
int8 FOSCSEL=0b00000011;                              //1ª parte de la configuración del oscilador para obtener 40 MIPS
int8 FOSC=0b11000001;
*/


 //INTERRUPCIÓN DEL TIMER1
void __attribute__((interrupt,no_auto_psv)) _T1Interrupt( void )
{
   LATAbits.LATA0=~LATAbits.LATA0;
   IFS0bits.T1IF = 0;                                 //Se pone a cero el flag de la interrupción
}


void osc_40MIPS(void)
{
   PLLFBD = 38; // M = 40
   CLKDIVbits.PLLPOST = 0; // N1 = 2
   CLKDIVbits.PLLPRE = 0; // N2 = 2
   OSCTUN = 0;
   RCONbits.SWDTEN = 0;
// Clock switch to incorporate PLL
   __builtin_write_OSCCONH(0x01); // Initiate Clock Switch to FRC with PLL (NOSC=0b001)
   __builtin_write_OSCCONL(0x01); // Start clock switching while (oscconbits.cOSC != 0b001); Wait for Clock switch to occur
   while(OSCCONbits.LOCK != 1) {};

/*
   CLKDIVbits.PLLPOST=0;                              //2ª parte de la configuración del oscilador para obtener 40 MIPS
   CLKDIVbits.PLLPRE=0;
   PLLFBDbits.PLLDIV=38;
*/
}

void Init_Timer1(void)
{
   IPC0bits.T1IP = 4;                                   // Se le da el nivel de prioridad
   IFS0bits.T1IF = 0;                                   // Reset Timer1 interrupt flag
   IEC0bits.T1IE = 1;                                   // Enable Timer1 interrupt
   T1CONbits.TCS=0;                                    // Fuente = Internos (Fcy)
   T1CONbits.TCKPS=0;                                  // Prescaler=1:1
   T1CONbits.TGATE=0;                                  // TGate inactivo
   T1CONbits.TSIDL=0;                                  //Continúa activo en modo Idle / Sleep
   PR1=199;                                       //Cuando el timer alcanza el valor del PR1 se resetea y se activa la interrupción si está habilitada
   TMR1=1;
   T1CONbits.TON=1;   //Timer en marcha
}


int main(void)
{

   osc_40MIPS();
   Init_Timer1();
   TRISA=0;                     //Ponemos puerto A como salida
   LATA=0x00;                    //Se pone LATA porque con PORTA parece que hay problemas

   while(1)
   {
   }
}
Título: Re: dsPIC33FJ256GP710 No obedece bien al tiempo de interrupción
Publicado por: fram_22 en 04 de Octubre de 2012, 13:41:00
de cuanto es el cristal contenido en la placa explorer 16?

Título: Re: dsPIC33FJ256GP710 No obedece bien al tiempo de interrupción
Publicado por: venturi en 05 de Octubre de 2012, 05:40:18
de cuanto es el cristal contenido en la placa explorer 16?



Hola fram_22. Gracias por tu interés. El cristal es de 8 MHz.

Un saludo.
Título: Re: dsPIC33FJ256GP710 No obedece bien al tiempo de interrupción
Publicado por: fram_22 en 08 de Octubre de 2012, 12:11:04
Disculpa la tardanza venturi, estuvo un poco ocupado estos dias:

Yo tengo un dspic33fj512mu810, tambien cuenta con un cristal de 8 Mhz y opera a 60 mips.
Te anexo mi cogico, con cambios menos deberias poder probarlo en tu placa:

Código: [Seleccionar]
#include <p33EP512MU810.h> 
#include "dsp.h"
#include "libq.h"

void Init_Timer1( void );
////////////////////////////////////////////////////////Fusibles de operacion/////////////////////////////////////////////////////////////
        _FOSCSEL(FNOSC_FRC);
        _FOSC(FCKSM_CSECMD & OSCIOFNC_OFF & POSCMD_XT);
        _FWDT(FWDTEN_OFF);
//
///////////////////////////////////////////////////////////MAIN///////////////////////////////////////////////////////////////////////
int main(void){
TRISD=0;
PORTD=0;
ANSELD = 0x0000;
//Cambio de oscilador RC a xtal con PLL para operacion a 60 MIPS
// Configure PLL prescaler, PLL postscaler, PLL divisor
PLLFBD = 58; /* M  = 60 */
CLKDIVbits.PLLPOST = 0; /* N1 = 2 */
CLKDIVbits.PLLPRE = 0; /* N2 = 2 */
// Disable Watch Dog Timer
RCONbits.SWDTEN=0;
// Initiate Clock Switch to Primary Oscillator with PLL (NOSC = 0b011)
    __builtin_write_OSCCONH(0x03);
__builtin_write_OSCCONL(0x01);
// Wait for Clock switch to occur
while (OSCCONbits.COSC!= 0b011);
// Wait for PLL to lock
//while(OSCCONbits.LOCK!=1) {};
///////////////////////////////////////////////  Aqui termina la conficuracion del dsPIC a 60 MIPS//////////////////////////////////////////
Init_Timer1();
while(1){

}
}
/* ISR ROUTINE FOR THE TIMER1 INTERRUPT */

void __attribute__((interrupt,no_auto_psv)) _T1Interrupt( void )
{
LATDbits.LATD0 = !LATDbits.LATD0;    
IFS0bits.T1IF = 0;
/* reset Timer 1 interrupt flag */
 
}
/*-----------------------*/
void Init_Timer1( void )
{

    T1CON = 0;              // Timer reset
  IFS0bits.T1IF = 0;      // Reset Timer1 interrupt flag
IPC0bits.T1IP = 6;      // Timer1 Interrupt priority level=4
  IEC0bits.T1IE = 1;      // Enable Timer1 interrupt
  TMR1=  0x0000; 
PR1 = 6000;           // Timer1 period register = 0.1 ms a 60 MIPS
T1CONbits.TON = 1;      // Enable Timer1 and start the counter

}

este código genera una señal cuadrada de 10 khz en el pin RD0, pruebalo y dime como te va con el
Título: Re: dsPIC33FJ256GP710 No obedece bien al tiempo de interrupción (SOLUCIONADO)
Publicado por: venturi en 11 de Octubre de 2012, 10:03:48
Pues ya está solucionado fram_22, gracias a tu inestimable ayuda  ((:-)).

El problema estaba en que en la segunda parte del oscilador la instrucción la tenía como:
   __builtin_write_OSCCONH(0x01); // Initiate Clock Switch to FRC with PLL (NOSC=0b001)
y la que funcina bien es:
   __builtin_write_OSCCONH(0x03); // Initiate Clock Switch to FRC with PLL (NOSC=0b001)

También hay que cambiar:
_FOSC(FCKSM_CSECMD & OSCIOFNC_OFF & POSCMD_NONE);
por:
_FOSC(FCKSM_CSECMD & OSCIOFNC_OFF & POSCMD_XT);

Es curioso porque esa configuración la copié de internet, y hay un monton de ejemplos con ello mal. Aclarar que el error que se comete es del 10% en vez del 20% que había comentado.

Dejo mi programilla midificado por si a alguien le interesa. A proposito ¿como se mete dentro de un recuadro para que no ocupe tanto como ha hecho fram_22,?


#include <p33FJ256GP710.h>
//Primera parte de la configuración del oscilador a 40 Mips. Esta copiada pero no está entendida del todo. Para entenderla mirar el fichero de cabecera del pic
_FOSCSEL(FNOSC_FRC); // Internal FRC oscillator
_FOSC(FCKSM_CSECMD & OSCIOFNC_OFF & POSCMD_XT); // Clock Switching is enabled and Fail Safe Clock Monitor is disabled
// OSC2 Pin Function: OSC2 is Clock Output
// Primary Oscillator Mode: XT Crystanl


 //INTERRUPCIÓN DEL TIMER1
void __attribute__((interrupt,no_auto_psv)) _T1Interrupt( void )
{
   LATAbits.LATA0=~LATAbits.LATA0;
   IFS0bits.T1IF = 0;                                 //Se pone a cero el flag de la interrupción
}


void osc_40MIPS(void)
{
   PLLFBD = 38; // M = 40
   CLKDIVbits.PLLPOST = 0; // N1 = 2
   CLKDIVbits.PLLPRE = 0; // N2 = 2
   OSCTUN = 0;
   RCONbits.SWDTEN = 0;
// Clock switch to incorporate PLL
   __builtin_write_OSCCONH(0x03); // Initiate Clock Switch to FRC with PLL (NOSC=0b001)
   __builtin_write_OSCCONL(0x01); // Start clock switching while (oscconbits.cOSC != 0b001); Wait for Clock switch to occur
   while(OSCCONbits.COSC != 0b011) {};      //Se espera a que entre el oscilador primario con el PLL habilitado.
   while(OSCCONbits.LOCK != 1) {};         //Se espera a que el PLL esté en funcionamiento

}

void Init_Timer1(void)
{
   IPC0bits.T1IP = 4;                                   // Se le da el nivel de prioridad
   IFS0bits.T1IF = 0;                                   // Reset Timer1 interrupt flag
   IEC0bits.T1IE = 1;                                   // Enable Timer1 interrupt
   T1CONbits.TCS=0;                                    // Fuente = Internos (Fcy)
   T1CONbits.TCKPS=0;                                  // Prescaler=1:1
   T1CONbits.TGATE=0;                                  // TGate inactivo
   T1CONbits.TSIDL=0;                                  //Continúa activo en modo Idle / Sleep
   PR1=199;                                       //Cuando el timer alcanza el valor del PR1 se resetea y se activa la interrupción si está habilitada
   TMR1=1;
   T1CONbits.TON=1;   //Timer en marcha
}


int main(void)
{

   osc_40MIPS();
   Init_Timer1();
   TRISA=0;                     //Ponemos puerto A como salida
   LATA=0x00;                    //Se pone LATA porque con PORTA parece que hay problemas

   while(1)
   {
   }
}



Voy a probar el reloj en tiempo real por sofware y os comento el resultado.
Un saludo a todos.

Título: Re: dsPIC33FJ256GP710 No obedece bien al tiempo de interrupción
Publicado por: fram_22 en 12 de Octubre de 2012, 11:12:15
entre las opciones que aparecenc cuando escribes un mensaje hay un cuadro con el simbolo #, este cuado es para incluir codigo, cuano lo escribas aparecera el texto:

{code}este es un ejempli{/code} (he cambiado los corchetes por braquets para que se vea el codigo)


todo lo que escribas entre las palabras code se vera asi:

Código: [Seleccionar]
este es un ejemplo
Título: Re: dsPIC33FJ256GP710 No obedece bien al tiempo de interrupción
Publicado por: venturi en 13 de Octubre de 2012, 10:55:56
Pues ya tengo el error aproximado del reloj en tiempo real por software. Es de unos dos segundos por día, lo cual creo que está bastante bien.

Muchas gracias por la información del recuadro fram_22. Un saludo.