I have used a lot of different developer boards over the years and home made programmers, but since I am using Linux and Mac’s I grew tired of the bad support and bought a PICKit 3 programmer and moved to Microchip’s own Assembler and C compiler. This is my first project to test the new toolchain.

The project

I wanted to program one of my favorite PICs, the 12F683, with the free version of XC8 (8 bit C-compiller) using my new PICKit 3 from my Macbook Pro Retina (OSX 10.9.4) and Linux (Ubuntu 14.03). Since I was confident in using Assembler and C I wanted to do little more than just blinking a led, so I decided to try to use timer interrupts to have the LED to pulsate.

Project setup

PIC12F683 with MPLAB X w. XC8 Free and a programmer – PicKit 3 LED Connected to GPIO 2 (pin 5 on the PIC12F683)

PICKIT 3 Setup

12F683 / PICKIT 3 PIN 1 <-> (1) MCLR PIN 4 <-> (2) VDD PIN 6 <-> (5) ICSPCLK PIN 7 <-> (4) ICSPDAT PIN 8 <-> (3) VSS (3)

Schema

blink-a-led

Code

#include <xc.h>

/**
 * Blink a led with varying power.
 *
 * PIC: 12F683
 * LED Connected to GPIO 2 (pin 5)
 */

// CONFIG
#pragma config FOSC = INTOSCIO
#pragma config WDTE = OFF
#pragma config PWRTE = OFF
#pragma config MCLRE = OFF
#pragma config CP = OFF
#pragma config CPD = OFF
#pragma config BOREN = OFF
#pragma config IESO = OFF
#pragma config FCMEN = OFF

#define LED GPIObits.GP2

volatile char counter1 = 0;
char dim = 0;
int on = 1;

void main(void)
{
    OSCCON=0b00010111;

    // Prescaler setup
    OPTION_REGbits.PSA=0;   // Assign to TIMER0
    OPTION_REGbits.PS2=0;   // 1:16 (011)
    OPTION_REGbits.PS1=1;
    OPTION_REGbits.PS0=1;
    OPTION_REGbits.T0CS=0;  // Internal Clock
    OPTION_REGbits.T0SE=0;  // Incr low -> high

    CCP1CONbits.CCP1M3=1;
    CCP1CONbits.CCP1M2=1;
    CCP1CONbits.CCP1M1=0;
    CCP1CONbits.CCP1M0=0;
    PR2=0x0F;
    T2CON=0b00000100;
    CCPR1L=0x00;
    CCPR1H=0x00;
    TMR2IF=0;               // Timer2 to PR2 match has not occurred (must be cleared)

    INTCONbits.T0IE=1;      // Enables the Timer0 interrupt
    INTCONbits.T0IF=0;      // Timer0 Overflow Interrupt Flag bit (must be cleared)
    INTCONbits.GIE=1;       // Enable interrupts (global)
    
    TRISIO=0x00;

    LED=1;

    while(1){
        CCPR1L=dim;
        if (dim== 0x01) { on = 1; }
        if (dim==0x10){on = 0;}
        if (counter1==1){LED=0;}
        if (counter1==2){LED=1;}
    }
}

void interrupt timeroverflow () {
    if (INTCONbits.T0IF==1){
        INTCONbits.T0IF=0;
        counter1++;
        if ( on == 1 ) dim++;
        else dim--;

        if (counter1==3){counter1=1;}
    }
}