1
\$\begingroup\$

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.

\$\endgroup\$
  • \$\begingroup\$ What are your configuration word settings for POSCMD, FNOSC, SOSCSEL etc.? \$\endgroup\$ – Bruce Abbott Jul 3 '15 at 9:44
  • \$\begingroup\$ SOSCSEL = OFF POSCMD = HS FNOSC = PRI \$\endgroup\$ – Bob Jul 3 '15 at 11:45
  • \$\begingroup\$ Edit your question with the details, don't put them in comments. People often won't search lengthy comment threads looking for context that belongs in the body of the question. Also, where's main()? \$\endgroup\$ – Adam Lawrence Jul 3 '15 at 12:15
  • \$\begingroup\$ I wanted to edit your code with 4 spaces in front of every line, but unfortunately this means that the question is larger than the allowed character count. Maybe you can identify yourself the important part and dump the full code somewhere else for reference... \$\endgroup\$ – 0x6d64 Jul 3 '15 at 13:15
  • \$\begingroup\$ You have posted a confusing mess of code, but still haven't shown some which may be relevant (eg. Millis(), resetMillis()). Strip out everything that is not necessary for clock setup and testing, and see if you can reproduce the problem with just the bare essentials (Osc_Config(), frequency test code etc.). Is your "30MHz Crystal Oscillator" an oscillator module, or is it a quartz crystal? \$\endgroup\$ – Bruce Abbott Jul 3 '15 at 18:19
3
\$\begingroup\$

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;
} 
| improve this answer | |
\$\endgroup\$
  • \$\begingroup\$ Thanks Bruce. I could run this and see the pulse. But for my Task, I Need to have a single pulse. Which I tried to generate without while(1). The result was: I could see the pulse Flash for less than second and disappear. I can't figureout where is the delay or Count calculation is going wrong. :( \$\endgroup\$ – Bob Jul 7 '15 at 13:01
  • \$\begingroup\$ Use the while(1) loop to make continuous pulses for testing, then tune the timer code to get the pulse width you want. For 1ms timer interrupts at FOSC/2 = 8MHz (16MHz crystal) PR2 needs to be 0.001s/(1/8000000Hz)=8000. \$\endgroup\$ – Bruce Abbott Jul 7 '15 at 20:14
1
\$\begingroup\$

http://ww1.microchip.com/downloads/en/DeviceDoc/39726a.pdf (fairly sizable doc) shows in section 35.8 that the maximum frequency for a crystal oscillator is 25 MHz. If you need a higher frequency, you need a lower frequency crystal and the internal PLL to generate it.

It can also take an external clock source of up to 32 MHz, but that isn't the same as a crystal.

| improve this answer | |
\$\endgroup\$
  • \$\begingroup\$ Thanks Scott for the Response. I am using now 16MHz Crystal. \$\endgroup\$ – Bob Jul 7 '15 at 13:08
  • \$\begingroup\$ @Bob -- did it work? \$\endgroup\$ – Scott Seidman Jul 7 '15 at 13:56

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.