Barebones PIC Programming on Mac + pickit2

If you’ve never done any microcontroller programming, start with an It’s the best way of getting started with embedded hardware programming.

If for whatever reason you’re determined to use PICs (cost, availability of free samples, you already had a bunch of them, etc.), you should get a pickit3 and use the netbeans-derived MPLAB X to develop, program and debug your devices.

But if like me you’re in the weird position of having a bunch of PICs, a Chinese knockoff pickit2 and a strong dislike of Java, here’s how to set up a *minimal* C development environment on a Mac.

Ingredients and Goal

Presumably you already have a pickit2, some board you can use to program PICs (I have a handy 28 pin demo board) and a computer. You need three additional things: a text editor for writing C, a compiler for turning it into a hex executable and a utility to copy the compiled program onto the device, via the pickit2.

Once you’re finished you’ll be able to write, compile, burn and run C programs on PICs via your pickit2 like this:

$ edit main.c
(write C program in external editor)
$ xc8 main.c --outdir=build --chip=16F886
$ pk2cmd -Fbuild/main.hex -PPIC16F886 -T

Text Editor

Any plain text or code editor will suffice for writing basic embedded C applications. I like TextWrangler, so much so I am writing this article in it, but any code editor will do. If it has syntax highlighting for C, all the better.


After a long period of PIC compiler fragmentation, Microchip has released the XC8 compiler as the canonical C compiler for PIC, and there’s a free version.

Download: direct more info

After the download is complete, open the installer and follow through the installation process. If you’re using a non-bash shell you’ll have to add Applications/microchip/xc8/v1.30/bin to your PATH.

Now you not only have the xc8 compiler available, you also have a whole bunch of documentation and device-specific header files in /Applications/microchip/xc8.

docs/ contains PDF documentation of the compiler and C used (MPLAB_XC8_C_Compiler_User_Guide.pdf), as well as a bunch of HTML documents detailing the config options available to each different chip.

include/ contains header files for each chip, as well as various libraries.

xc.h is the top-level file you include in your application. It automatically figures out which PIC you’re targeting and includes other relevant headers. plib/ contains a bunch of PIC18 peripheral libraries. There are various other header files which reward study scattered around in here too.

Barebones C program

This is the smallest meaningful PIC C program:

#include <xc.h>
#include <stdbool.h>

#pragma config CPD = OFF
#pragma config BOREN = OFF
#pragma config IESO = OFF
#pragma config DEBUG = OFF
#pragma config FOSC = INTRC_NOCLKOUT
#pragma config FCMEN = OFF
#pragma config MCLRE = OFF
#pragma config WDTE = OFF
#pragma config CP = OFF
#pragma config LVP = OFF
#pragma config PWRTE = OFF

void init(void) {
  // 4MHz clock
    OSCCON = 0b01100000;
    TRISA = 0;
    TRISB = 0;
    TRISC = 0;

void main(void) {
    PORTA = 0b111111;
    PORTB = 0b11111111;
    PORTC = 0b11111111;
    while (true)

The #include directives include xc.h, which automatically includes the header file for the chip as mentioned above, and stdbool.h, which defines true and false as 1 and 0, respectively.

The #pragma config directives set chip-specific config options as defined in the chip’s datasheet and in the HTML file for the device. In this case we are turning all the interesting features off and telling the device to use the internal oscillator without exposing the signal on a pin.

void init(void) is a function which sets up the PIC by setting the internal clock to run at 4MHz, and setting all of the available digital IO pins to outputs. 0bXXXXXXXX is a binary literal, e.g. 0b0 is zero, 0b1 is one, 0b10 is two, etc.

void main(void) is the function which is called when the PIC is turned on. It calls init() to set up the device, then raises all of the available outputs. If you have a different device you may have to change the PORT references or lengths of the numbers here. The PIC16F886 just happens to have three ports, one of which has only six pins. Refer to your datasheet or CHIP.h file.

Finally we enter an endless loop of NOP()s (no-operation), which prevents the PIC from shutting down. If we didn’t do this the LEDs would be lit for a small fraction of a second and we would be left wondering why our program didn’t work.

Write this out as main.c somewhere and compile it as so, replacing 16F886 with the part number you’re using:

$ xc8 main.c --outdir=build --chip=16F886

You should now have a build/ folder containing a bunch of files, including main.hex.

Burning a program to the device

For this you will need the free pk2cmd utility offered by microchip for command-line control of the pickit2 device over USB.

I defer to Curuxa’s installation instructions. If compiling from source (you will probably have to) replace make linux with make mac105.

I use the following homebrew formula to install pk2cmd. Use with brew edit pk2cmd, paste this code in, save, then brew install pk2cmd.

require "formula"

class Pk2cmd < Formula
  homepage ""
  url ""
  sha1 "19e90a665caef6d993820ce6c7ace5416b656f47"
  version "1.20"

  depends_on "libusb"

  def install
    system "make mac105"
    bin.install "pk2cmd", "PK2DeviceFile.dat", "PK2V023200.hex", "usbhotplug.txt"
    doc.install "ReadmeForPK2CMDLinux2-6.txt"

  test do
    system "pk2cmd"

At some point I might try getting this merged into homebrew core.

pk2cmd is rather a weird command-line application. Every command you run demands the -P option, which specifies the device you’re using, e.g. -PPIC16F886. Basic commands:

  • pk2cmd -Fbuild/main.hex -M -PPIC16F886 burns your program to the device by writing the contents of the main.hex File to the PICs Memory
  • pk2cmd -A5.0 -T -PPIC16F886 powers the Target board At 5V
  • pk2cmd -PPIC16F886 turns off power to the target board

Next Steps

Now you should have some pretty LEDs lit up as well as a minimal edit/compile/deploy workflow. The next steps depend on your personal interest, project and skill level.

I uploaded the source code for this project to github: barnabywalters/barebones-xc8. It has a few little command line tools you might find interesting or useful.

If like me you don’t know C, work through Not all of it will be relevant to embedded C (case in point: lack of filesystem) but it’s solid stuff nonetheless.

You’ll probably need to read through the datasheet for your device to get a feel for what it’s capable of and how to use it. If you’re using a PIC18 device, check out the plib for ready-built peripheral libraries. Otherwise, look through your datasheet, chip header file and chip HTML file.

Again, using PICs seems a little masochistic in a world where Arduino is so widely available. Perhaps you should consider whether or not it’s really a good idea to use them for your project. Either way, the option is now available to you.