PIC12F683 Square wave generation

Thread Starter

ChipCircuit

Joined May 1, 2023
73
Hi Folks,

I am using a PIC 12F683 microcontroller to generate periods of 32µs and 6µs on PINs 6 and 5, respectively. I am using an external 10MHz crystal oscillator for the clock source. I have already written the code and flashed it to the chip. However, when verifying the output with an oscilloscope, I am not getting the expected period signals. Instead, I am seeing 240µs signals with varying duty cycles. I programmed the code to achieve a 50% duty cycle.

Here are some additional details:

  • Microcontroller: PIC 12F683
  • Clock Source: 10MHz external crystal oscillator
  • Expected Output: 32µs and 6µs periods on PINs 6 and 5 with 50% duty cycle
  • Observed Output: 240µs signals with different duty cycles
  • Software MPLAB X IDE v6.20
I couldn’t identify the mistake in my code. If you have time, could you please help me verify it? Thanks in advance!

Code:
#include <xc.h>

#define _XTAL_FREQ 10000000  // 10 MHz crystal

void delay_us(unsigned int us) {
    while(us--) {
        __delay_us(1);
    }
}

void main(void) {
    #pragma config FOSC = XT  // Select external XT oscillator
    #pragma config WDTE = OFF // Disable watchdog timer
    #pragma config PWRTE = OFF // Power-up timer disabled
    #pragma config MCLRE = ON // GP3/MCLR pin function is MCLR
    
    // Set up the oscillator to use the external 10 MHz crystal
    OSCCON = 0x00;  // External oscillator selected (no internal oscillator used)

    // Set all pins as digital I/O
    ANSEL = 0x00;
    ADCON0 = 0x00;

    // Set pin directions
    TRISIO = 0b11111001;  // GP1 and GP2 as output, others as input (GP0, GP3-GP5 are input)

    // Main loop
    while(1) {
        // Generate 32 µs pulse on GP1 (pin 6) with 50% duty cycle
        GPIO |= 0b00000010;  // Set GP1 high
        delay_us(16);
        GPIO &= ~0b00000010;  // Set GP1 low
        delay_us(16);

        // Generate 6 µs pulse on GP2 (pin 5) with 50% duty cycle
        GPIO |= 0b00000100;  // Set GP2 high
        delay_us(3);
        GPIO &= ~0b00000100;  // Set GP2 low
        delay_us(3);
    }
}
 

hexreader

Joined Apr 16, 2011
619
Far too many mistakes to go through them all.

Here is my attempt at something a little closer to requirement, but not perfect.

If I get bored, I may try PWM to see if I can produce better waveforms

Code:
// random code found on forum

// PIC12F683 Configuration Bit Settings
#pragma config FOSC = HS        // Oscillator Selection bits (HS oscillator: High-speed crystal/resonator on RA4/OSC2/CLKOUT and RA5/OSC1/CLKIN)
#pragma config WDTE = OFF       // Watchdog Timer Enable bit (WDT disabled)
#pragma config PWRTE = OFF      // Power-up Timer Enable bit (PWRT disabled)
#pragma config MCLRE = ON       // MCLR Pin Function Select bit (MCLR pin function is MCLR)
#pragma config CP = OFF         // Code Protection bit (Program memory code protection is disabled)
#pragma config CPD = OFF        // Data Code Protection bit (Data memory code protection is disabled)
#pragma config BOREN = ON       // Brown Out Detect (BOR enabled)
#pragma config IESO = OFF       // Internal External Switchover bit (Internal External Switchover mode is disabled)
#pragma config FCMEN = OFF      // Fail-Safe Clock Monitor Enabled bit (Fail-Safe Clock Monitor is disabled)

#include <xc.h>

#define _XTAL_FREQ 10000000     // 10 MHz crystal

// global variables
unsigned char timecount;

void main(void) {

    // Set all pins as digital I/O
    ANSEL = 0x00;
    ADCON0 = 0x00;

    // Set pin directions
    TRISIO = 0b11111001;  // GP1 and GP2 as output, others as input (GP0, GP3-GP5 are input)

    // Main loop
    while(1) {
        // Generate 16 µs high on GP1 (pin 6) with 50% duty cycle
 
        for(timecount = 0; timecount < 2; timecount++){
            // Generate 3 µs high, 3us low on GP2 (pin 5) with 50% duty cycle
            GPIO = 0b00000110;                                                   // Set GP2 high, GP1 high
            GPIO = 0b00000110;                                                   // Set GP2 high - waste time
            GPIO = 0b00000110;                                                   // Set GP2 high - waste time
            GPIO = 0b00000110;                                                   // Set GP2 high - waste time
            GPIO = 0b00000010;                                                   // Set GP2 low
        }

        // Generate 16 µs low on GP1 (pin 6) with 50% duty cycle

        for(timecount = 0; timecount < 2; timecount++){
            // Generate 3 µs high, 3us low on GP2 (pin 5) with 50% duty cycle
            GPIO = 0b00000100;                                                   // Set GP2 high, GP1 low
            GPIO = 0b00000100;                                                   // Set GP2 high - waste time
            GPIO = 0b00000100;                                                   // Set GP2 high - waste time
            GPIO = 0b00000100;                                                   // Set GP2 high - waste time
            GPIO = 0b00000000;                                                   // Set GP2 low
        }
    }
}
 

Thread Starter

ChipCircuit

Joined May 1, 2023
73
Far too many mistakes to go through them all.

Here is my attempt at something a little closer to requirement, but not perfect.

If I get bored, I may try PWM to see if I can produce better waveforms

Code:
// random code found on forum

// PIC12F683 Configuration Bit Settings
#pragma config FOSC = HS        // Oscillator Selection bits (HS oscillator: High-speed crystal/resonator on RA4/OSC2/CLKOUT and RA5/OSC1/CLKIN)
#pragma config WDTE = OFF       // Watchdog Timer Enable bit (WDT disabled)
#pragma config PWRTE = OFF      // Power-up Timer Enable bit (PWRT disabled)
#pragma config MCLRE = ON       // MCLR Pin Function Select bit (MCLR pin function is MCLR)
#pragma config CP = OFF         // Code Protection bit (Program memory code protection is disabled)
#pragma config CPD = OFF        // Data Code Protection bit (Data memory code protection is disabled)
#pragma config BOREN = ON       // Brown Out Detect (BOR enabled)
#pragma config IESO = OFF       // Internal External Switchover bit (Internal External Switchover mode is disabled)
#pragma config FCMEN = OFF      // Fail-Safe Clock Monitor Enabled bit (Fail-Safe Clock Monitor is disabled)

#include <xc.h>

#define _XTAL_FREQ 10000000     // 10 MHz crystal

// global variables
unsigned char timecount;

void main(void) {

    // Set all pins as digital I/O
    ANSEL = 0x00;
    ADCON0 = 0x00;

    // Set pin directions
    TRISIO = 0b11111001;  // GP1 and GP2 as output, others as input (GP0, GP3-GP5 are input)

    // Main loop
    while(1) {
        // Generate 16 µs high on GP1 (pin 6) with 50% duty cycle

        for(timecount = 0; timecount < 2; timecount++){
            // Generate 3 µs high, 3us low on GP2 (pin 5) with 50% duty cycle
            GPIO = 0b00000110;                                                   // Set GP2 high, GP1 high
            GPIO = 0b00000110;                                                   // Set GP2 high - waste time
            GPIO = 0b00000110;                                                   // Set GP2 high - waste time
            GPIO = 0b00000110;                                                   // Set GP2 high - waste time
            GPIO = 0b00000010;                                                   // Set GP2 low
        }

        // Generate 16 µs low on GP1 (pin 6) with 50% duty cycle

        for(timecount = 0; timecount < 2; timecount++){
            // Generate 3 µs high, 3us low on GP2 (pin 5) with 50% duty cycle
            GPIO = 0b00000100;                                                   // Set GP2 high, GP1 low
            GPIO = 0b00000100;                                                   // Set GP2 high - waste time
            GPIO = 0b00000100;                                                   // Set GP2 high - waste time
            GPIO = 0b00000100;                                                   // Set GP2 high - waste time
            GPIO = 0b00000000;                                                   // Set GP2 low
        }
    }
}
Thank you so much for your help! I tried your code and managed to get 32us, but I’m seeing 7.7us instead of 6us. Your effort is much appreciated, and it’s definitely closer to what I need. :)
 

hexreader

Joined Apr 16, 2011
619
Seems I got bored quicker than expected.

Here is the PWM version:

Code:
// random code found on forum
// square wave 6uS period 50% on GP 2
// square wave 32uS period 50% on GP 1
//
// actual frequencies measured to 2 decimal places are:
//   GP2 166.68 kHz   ( 6uS would be 166.67 kHz)
//   GP1  31.65 kHz   (32uS would be  31.60 kHz)

// PIC12F683 Configuration Bit Settings
#pragma config FOSC = HS        // Oscillator Selection bits (HS oscillator: High-speed crystal/resonator on RA4/OSC2/CLKOUT and RA5/OSC1/CLKIN)
#pragma config WDTE = OFF       // Watchdog Timer Enable bit (WDT disabled)
#pragma config PWRTE = OFF      // Power-up Timer Enable bit (PWRT disabled)
#pragma config MCLRE = ON       // MCLR Pin Function Select bit (MCLR pin function is MCLR)
#pragma config CP = OFF         // Code Protection bit (Program memory code protection is disabled)
#pragma config CPD = OFF        // Data Code Protection bit (Data memory code protection is disabled)
#pragma config BOREN = ON       // Brown Out Detect (BOR enabled)
#pragma config IESO = OFF       // Internal External Switchover bit (Internal External Switchover mode is disabled)
#pragma config FCMEN = OFF      // Fail-Safe Clock Monitor Enabled bit (Fail-Safe Clock Monitor is disabled)

#include <xc.h>

#define _XTAL_FREQ 10000000     // 10 MHz 2 pin crystal with two 22pF capacitors

// prototypes
void pwm_start(void);
void pwm_stop(void);

void main() {

    ADCON0 = 0;                         // all pins digital
    ANSEL = 0;                          // all pins digital
    CMCON0 = 7;                         // Comparators off.
    TRISIO = 0;                         // all output
    GPIO = 0;                           // all pins low

    T2CON = 0x04;                       // prescaler + turn on TMR2;
    PR2 = 0x0e;                         // freq 0x0e for 167kHz
    CCPR1L = 0x07;                      // set low time 0x07 for 50% duty
    CCP1CON = 0x3c;                     // duty lowest bits + PWM mode

    while (1){
        GPIObits.GP1 = ~GPIObits.GP1;   // toggle 16uS high, 16uS low
        __delay_us(11);                 // rest of loop takes about 5 uS to execute
    }
}
 
Last edited:

Thread Starter

ChipCircuit

Joined May 1, 2023
73
Seems I got bored quicker than expected.

Here is the PWM version:

Code:
// random code found on forum
// square wave 6uS period 50% on GP 2
// square wave 32uS period 50% on GP 1
//
// actual frequencies measured to 2 decimal places are:
//   GP2 166.68 kHz   ( 6uS would be 166.67 kHz)
//   GP1  31.65 kHz   (32uS would be  31.60 kHz)

// PIC12F683 Configuration Bit Settings
#pragma config FOSC = HS        // Oscillator Selection bits (HS oscillator: High-speed crystal/resonator on RA4/OSC2/CLKOUT and RA5/OSC1/CLKIN)
#pragma config WDTE = OFF       // Watchdog Timer Enable bit (WDT disabled)
#pragma config PWRTE = OFF      // Power-up Timer Enable bit (PWRT disabled)
#pragma config MCLRE = ON       // MCLR Pin Function Select bit (MCLR pin function is MCLR)
#pragma config CP = OFF         // Code Protection bit (Program memory code protection is disabled)
#pragma config CPD = OFF        // Data Code Protection bit (Data memory code protection is disabled)
#pragma config BOREN = ON       // Brown Out Detect (BOR enabled)
#pragma config IESO = OFF       // Internal External Switchover bit (Internal External Switchover mode is disabled)
#pragma config FCMEN = OFF      // Fail-Safe Clock Monitor Enabled bit (Fail-Safe Clock Monitor is disabled)

#include <xc.h>

#define _XTAL_FREQ 10000000     // 10 MHz 2 pin crystal with two 22pF capacitors

// prototypes
void pwm_start(void);
void pwm_stop(void);

void main() {

    ADCON0 = 0;                         // all pins digital
    ANSEL = 0;                          // all pins digital
    CMCON0 = 7;                         // Comparators off.
    TRISIO = 0;                         // all output
    GPIO = 0;                           // all pins low

    T2CON = 0x04;                       // prescaler + turn on TMR2;
    PR2 = 0x0e;                         // freq 0x0e for 167kHz
    CCPR1L = 0x07;                      // set low time 0x07 for 50% duty
    CCP1CON = 0x3c;                     // duty lowest bits + PWM mode

    while (1){
        GPIObits.GP1 = ~GPIObits.GP1;   // toggle 16uS high, 16uS low
        __delay_us(11);                 // rest of loop takes about 5 uS to execute
    }
}
Hey, thank you so much for your help. I tried the PWM code, and it is working fine. However, instead of 6 µs, I was getting 7.75 µs. I corrected the PR2 value to 14, which allowed me to achieve the correct 6 µs. Once again, thank you for your help. It is much appreciated! :)
 
Top