Electronic – NEED HELP: Oscillator Error and PIC24F stopped working

crystalmplabxoscillatorpic

I have a 30MHz Crystal Oscillator to clock a PIC24FJ128GC010 Controller. I am programming in MPLAB X. My idea is to generate a pulse on one of the I/O pin toggling. But unfortunately, I cannot do so. Initially I was using a 8MHz Crystal. I have made the Configuration Word settings as well as Control Register adjustments. I have changed the baud rate too.

Please suggest the possibilities in this case.

*****************************************************************************************
CONFIG WORDS
*****************************************************************************************

POSCMD = HS              // Primary Oscillator Select (HS Oscillator Enabled)
OSCIOFCN = OFF           // OSCO Pin Configuration (OSCO/CLKO/RC15 functions as CLKO (FOSC/2))//
FCKSM = CSDCMD           // Clock Switching and Fail-Safe Clock Monitor Configuration bits (Disabled)
FNOSC = PRI              // Initial Oscillator Select (Primary Oscillator (XT, HS, EC))
IESO = OFF               // Internal External Switchover (Disabled)

*****************************************************************************************
#include "timer.h"

unsigned millisCount = 0;

void __attribute__ ((interrupt, no_auto_psv)) _T2Interrupt(void)
{
  IFS0bits.T2IF = 0;
  millisCount++;
}

/*******************************************************************************
 * Returns the number of milliseconds since the device was started as an
 * unsigned long.
 ******************************************************************************/
unsigned long Millis()
{
  return millisCount;
}

void ResetMillis(void)
{
  millisCount = 0u;
}

void Delay(unsigned long delayTime)
{
  volatile int delayStart = Millis();
  while (Millis() - delayStart < delayTime);
}

****************************************************************************************    
INITIALISATION CODE
****************************************************************************************
void Osc_Config(void)
{
    OSCTUN = 0;
    CLKDIV = 0;
    OSCCON = 0;

    OSCCONbits.COSC = 2;
    OSCCONbits.NOSC = 2;
    OSCCONbits.OSWEN = 1;

    while(OSCCONbits.OSWEN);
}

void Timer2_Config(void)
{
    T2CON = 0;
    TMR2 = 0x0000;                      //Turn off Timer2
    PR2 = 0xFFFF;                       //Period register at maximum

    _T2IF = 0;                          //clear Timer2 interupt flag
    _T2IE = 1;                          //Enable Time2 interupt

    //T2CON
    T2CONbits.T32 = 0;                  //Timer2 and T3 or T4 and T5 act as two 16-bit timers
    T2CONbits.TCKPS = 0;                //Timer Prescale 1:1
    T2CONbits.TGATE = 0;                //Gated time accumulation is disabled
    T2CONbits.TSIDL = 0;                //Continues module operation in Idle mode
    T2CONbits.TCS = 0;                  //Internal clock (FOSC/2)
    T2CONbits.TON = 1;                  //Starts Timer2
}

void Io_Config(void)
{
    ****//Start pulse pin**
    PULSE_PIN = 0;
    TRISBbits.TRISB2 = 0;   //set as output pin**

    //Stop pulse pin
    TRISBbits.TRISB15 = 1;  //set as input pin
    TRISCbits.TRISC1 = 1;   //set as input pin for current
    TRISBbits.TRISB13 = 1;  //set as input pin

    //Trip point pin
    TRISBbits.TRISB5 = 0;   //set as output pin

    // Configure start and stop pulse as digital
    ANSBbits.ANSB2 = 0;      //set as digital
    ANSBbits.ANSB15 = 0;    // set as digital
    ANSCbits.ANSC1 = 1;     // set to analog
    ANSBbits.ANSB13 = 0; // set to digital
    ANSBbits.ANSB12 = 0;   //Set to Digital to check the frequency of the Oscillator

    //reference clock output
    ANSBbits.ANSB15 = 0;    //seta s digital
    TRISBbits.TRISB15 = 0;  //SSet as output
} <-- NOTE: was missing trailing brace here.

void Adc_Config(void)
{
    PMD1bits.ADC1MD = 0;    //Clear PMD bit to allow ADC operation

    //ADCON1
    ADCON1bits.ADSIDL = 0;
    ADCON1bits.ADSLP = 0;
    ADCON1bits.FORM = 0;
    ADCON1bits.PUMPEN = 0;
    ADCON1bits.ADCAL = 0;
    ADCON1bits.PWRLVL = 1;

    //ADCON2
    ADCON2bits.PVCFG = 0;
    ADCON2bits.NVCFG0 = 0;
    ADCON2bits.BUFORG = 1;

    //ADCON3
    ADCON3bits.ADRC = 0;
    ADCON3bits.ADCS = 0;

    ADCON3bits.SLEN0 = 1u; //FKo

    ADCON1bits.ADON = 1;
    while(ADSTATHbits.ADREADY == 0); // Wait for ready flag set.

    //Make sure ADC sample lists and Accumulator feature are in known states
    ACCONH = 0x0000;        //Disable accumulation for the moment
    ACRES = 0x00000000;     //Clear previous accumulation count
    ADL0CONLbits.SLSIZE = 1-1; //Sample list length for 1 channel
//Configure Sample List 0 settings
    ADL0CONHbits.ASEN = 0;
    ADL0CONHbits.SLINT = 1;
    ADL0CONHbits.WM = 0;
    ADL0CONHbits.CM = 0;
    ADL0CONHbits.SAMC = 1;
    ADL0CONLbits.SLTSRC = 0;    
    ADTBL0bits.ADCH = 8;    // channel 0 selected
    ADL0PTR = 0;            // Point to start of sample list 0

#if (__TEST_FREQUENCY_SETUP__)
    ADL0CONLbits.SAMP = 1;
    Nop();Nop();
    ADL0CONLbits.SAMP = 0;
    while(!IFS0bits.AD1IF && !ADSTATLbits.SL0IF) { ; }
    IFS0bits.AD1IF = 0u;
    ADSTATLbits.SL0IF = 0u;
    {
        unsigned long res = ADRES0;
        res = 15u;
    }
#endif <-- NOTE: was missing.
} <-- NOTE: missing.

void Uart_Config(void)
{
    RPOR1bits.RP2R = 3;         //Assign UART1 transmit to RP3 Peripheral
    RPOR1bits.RP3R = 4;
    RPINR18bits.U1RXR = 0;      //Assign UART1 RXD to RP0 Peripheral
    RPINR18bits.U1CTSR = 1;
    U1BRG = 50;//12;
    U1STA = 0;
    U1MODE = 0x8000;
    U1STAbits.UTXEN = 1;
}

**#define UART_BUFFER_SIZE  128

void UARTInit(void)
{
    //U1BRG = 312;   //9600 baudrate @ 24MHz osc
    U1BRG = 24;      //19200 baudrate @ 10 MHz osc

    U1MODE = 0;
    U1MODEbits.BRGH = 1;
    U1STA = 0;
    U1STAbits.URXISEL = 0;
    U1MODEbits.UARTEN = 1;
    U1STAbits.UTXEN = 1;
    IFS0bits.U1RXIF = 0;
}

void UARTPutChar(uint8_t ch)
{
    while(U1STAbits.TRMT == 0);
    Nop(); Nop();Nop(); Nop();
     Nop(); Nop();Nop(); Nop();
    U1TXREG = ch;
}

void UARTPutInt(int32_t data)
{
    int j;
    char string[UART_BUFFER_SIZE];

    sprintf(string, "%ld", data);

    j = 0;
    while(string[j] != 0)
    {
        UARTPutChar(string[j]);
        j++;
        if(j >= UART_BUFFER_SIZE)
        {
            break;
        }
    }
}

void UARTPutString(char* string)
{
    while(*string != 0)
    {
        UARTPutChar(*string);
        string++;
    }
}

void UARTPutDouble(double data)
{
    int j;
    char string[UART_BUFFER_SIZE];

    sprintf(string, "%9.3f", data);

    j = 0;
    while(string[j] != 0)
    {
        UARTPutChar(string[j]);
        j++;
        if(j >= UART_BUFFER_SIZE)
        {
            break;
        }
    }
}

char UARTWaitChar(void)
{
    while(IFS0bits.U1RXIF == 0);
    IFS0bits.U1RXIF = 0;
    return U1RXREG;
}

char UARTGetChar(void)
{
    if(IFS0bits.U1RXIF == 0)
    {
        return 0;
    }
    U1STAbits.OERR = 0;
    IFS0bits.U1RXIF = 0;
    return U1RXREG;
}

*************************************************************************************
MAIN CODE
*************************************************************************************
// PIC24FJ128GC010 Configuration Bit Settings

#define STARTUP_DELAY (5)  //Time spent waiting after device start up
#define ZERO_SET_TIME (5)  //Time spent setting the zero level
#define COUNT 5
#define DELAY for(i=0;i<COUNT;i++)
int dispOffset = 0;

void SetDutyCycle(int nDC);                //Set duty cycle for trip point
int  PulseMeasure(void);                   //Single pulse measurement
int  LevelMeasure(int, int);               //Averaged return of multiple measurements
int  adctemp;
void TestMeas(void);                       //Test routine to scan through PWM values
double StdDev(int, double, double, double);//Get sigma for measurements
int i;


/*******************************************************************************
 * Main
 ******************************************************************************/
int main(void)
{
    //Configure all of the devices

    while (Millis() < STARTUP_DELAY);                        //Wait for settling...
    //Wait for sensor to be plugged in
    **while(LevelMeasure(CTMU_BUFFER_POWER, OVER_SAMPLE) < 0);** 

    #if (__TEST_FREQUENCY_SETUP__)
        while(Millis() < 10) { ; }
        ResetMillis();
        LATBbits.LATB2 = 1;
        while(Millis() < 10) { ; }
        ResetMillis();
        LATBbits.LATB2 = 0;
    #endif
} <-- NOTE: missing brace.

int PulseMeasure(void)
{
    volatile unsigned int Vread;
    double Vtot = 0;
    int j;
    //ADL0CONLbits.SAMP = 1;       //Sample
    PULSE_PIN = 0;
    CTMUCON2 = CTMUCON2 & 0xFCFF;
    CTMUCON1bits.IDISSEN = 1;     //discharge cap
    Delay(20);
    CTMUCON1bits.IDISSEN = 0;     //Release cap from discharge
    ADL0CONLbits.SLEN = 1;
    ADL0CONLbits.SAMP = 1;
    for(j=0;j<10;j++)
    {
        Nop();Nop();Nop();Nop();
        Nop();Nop();Nop();Nop();
        Delay(1);
        CTMUCON2 = CTMUCON2 & 0xFCFF;

        PULSE_PIN = 1;
        PULSE_PIN = 0;
        while(!CTMUCON2bits.EDG1STAT);
        while(ADSTATHbits.ADBUSY);//{;}
        Nop(); Nop();
        IFS0bits.AD1IF = 0;
        ADSTATLbits.SL0IF = 0;
        ADL0CONLbits.SAMP = 0;    //Conversion

        while (!ADSTATLbits.SL0IF);

        Vread = ADRES0;
        IFS0bits.AD1IF = 0;
        ADSTATLbits.SL0IF = 0;
        ADL0CONLbits.SAMP = 1;
        UARTPutString("#gy;1;");
        UARTPutInt(Vread);
        UARTPutString("\r\n");
    }
    return (Vread);
}

PULSE_PIN is the function for the pulse generation. Excuse me for the lengthy code and number of edits. But I really do not understand why the program runs well at 8MHz and not 30MHz! And YES; it really is a 30MHz crystal oscillator.

PLEASE HELP ME!!! I am new to programming but I must work with this code to run it at 30/2=16MHz for further work.

Best Answer

I cut your code down to the bare minimum required to test the system clock and timer operation, and ran it on a PIC24FJ64GA104 (whose basic clock and timer operation is similar to your PIC). Everything worked correctly, even when using an external oscillator module instead of a crystal (POSCMD should be set to EC in that case).

I changed a couple of things that might be stopping your frequency test from working properly:-

  1. Disabled the watchdog timer (it is enabled by default, which will cause the MCU to reset repeatedly if not periodically reset).

  2. Enclosed the frequency test code in a while(1) loop, to make it run continuously rather than exiting main() after one iteration.

Try my code on your PIC. If it doesn't work then you may have a hardware problem (oscillator not starting up, insufficient power supply bypassing, incorrect wiring etc.).

#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <xc.h>               // automatically includes MCU selected in project

#pragma config POSCMOD = HS   // Primary Oscillator Select (HS = crystal, EC = external clock input)
#pragma config OSCIOFNC = OFF // OSCO Pin Configuration (OSCO/CLKO/RC15 functions as CLKO (FOSC/2))
#pragma config FCKSM = CSDCMD // Clock Switching and Fail-Safe Clock Monitor Configuration bits (Disabled)
#pragma config FNOSC = PRI    // Initial Oscillator Select (Primary Oscillator (XT, HS, EC))
#pragma config IESO = OFF     // Internal External Switchover (Disabled)
#pragma config FWDTEN = OFF   // watchdog timer (off)

//******************************************************************************
#include "timer.h"

unsigned millisCount = 0;

void __attribute__ ((interrupt, no_auto_psv)) _T2Interrupt(void)
{
  IFS0bits.T2IF = 0;
  millisCount++;
}

/*******************************************************************************
 * Returns the number of milliseconds since the device was started as an
 * unsigned long.
 ******************************************************************************/
unsigned long Millis()
{
  return millisCount;
}

void ResetMillis(void)
{
  millisCount = 0u;
}

void Delay(unsigned long delayTime)
{
  volatile int delayStart = Millis();
  while (Millis() - delayStart < delayTime);
}

//******************************************************************************
// INITIALISATION CODE
//******************************************************************************

void Timer2_Config(void)
{
    T2CON = 0;
    TMR2 = 0x0000;                      //Turn off Timer2
    PR2 = 0xFFFF;                       //Period register at maximum

    _T2IF = 0;                          //clear Timer2 interupt flag
    _T2IE = 1;                          //Enable Time2 interupt

    //T2CON
    T2CONbits.T32 = 0;                  //Timer2 and T3 or T4 and T5 act as two 16-bit timers
    T2CONbits.TCKPS = 0;                //Timer Prescale 1:1
    T2CONbits.TGATE = 0;                //Gated time accumulation is disabled
    T2CONbits.TSIDL = 0;                //Continues module operation in Idle mode
    T2CONbits.TCS = 0;                  //Internal clock (FOSC/2)
    T2CONbits.TON = 1;                  //Starts Timer2
}

#define PULSE_PIN LATBbits.LATB2

void Io_Config(void)
{
 // pulse pin
    PULSE_PIN = 0;
    TRISBbits.TRISB2 = 0;   //set as output
} 

//******************************************************************************
//MAIN CODE
//******************************************************************************

#define STARTUP_DELAY (5)  //Time spent waiting after device start up

int main(void)
{
    //Configure all of the devices
    Io_Config();
    Timer2_Config();
    while (Millis() < STARTUP_DELAY){};   //Wait for settling...
    while (1)
    {
       while(Millis() < 10) { ; }
       ResetMillis();
       LATBbits.LATB2 = 1;
       while(Millis() < 10) { ; }
       ResetMillis();
       LATBbits.LATB2 = 0;
    }
        return 0;
} 
Related Topic