Fork me on GitHub

Project Notes

#331 Getting Blinky with PIC Assembler

Getting starter with PIC assembler on macOS with a PIC12F675 development board and programming with the PICkit 3. Updated in 2026 with the latest MPLAB X IDE. While PICkit 3 is still working on Windows and Linux, it now fails on macOS. As an interim measure, I demonstrate compiling on macOS and using a script to remotely program on Ubuntu.

Here’s a quick demo of it working…

GettingBlinky_build

Notes

PIC is not necessarily everyone’s first choice for embedded development these days, and perhaps it is now more like a right-of-passage. I guess it was Julian Ilett who finally gave me the nudge - I really need to try this for myself. One thing that’s held me back is the perception that you have to “downgrade” to Windows in order to get anything going.

So challenge accepted: I finally decided to see what it is like to develop with PIC assembler with a PIC12F675 development board and PICkit 3 programmer, and ideally do it all on my development platform of choice - macOS - without resorting to containers or VMs.

I originally made these notes in 2017, using MPLAB X IDE v3.51 (later updated to v5.30) on Intel-based macOS with a PICkit 3 programmer, and all was peachy. But….

Feb-2026 Update

It is now Feb-2026, and I am revisiting these notes to get a PIC programming environment back up and running, now on ARM-based macOS 15.7.

Unfortunately, the news is mixed, and the main issue is with PICkit 3 support:

  • updated to MPLAB X IDE v6.20 from the MPLAB downloads archive
    • Now uses PIC-as assembler instead of the old MPASMWIN - source files updated to the new syntax
    • Compiles perfectly on all platforms I’ve tested: macOS 15.7/ARM, Windows 11/Intel, Ubuntu 24.04/Intel
    • This is the last version to support the PICkit 3 programmer, however:
      • I’ve been unable to get the PICkit 3 programmer to work for me correctly on macOS.
      • But it works fine on Windows and Ubuntu.
      • See notes below for more details.
  • I have installed MPLAB X IDE v6.30, the latest release of the IDE product.
    • Compilation works fine.
    • No integrated PICKit 3 support of course - but can use MPLAB IPE v6.20 for programming.
  • Microchip are now promoting MPLAB Tools for VS Code for current and future projects.
    • Also does not support PICKit 3

So where does this leave me?

I don’t really want to fork out for a new (and quite expensive) PICkit 5 that should work on macOS, so my choice right now is to hobble along:

  • Develop on macOS MPLAB X IDE v6.20 or v6.30 (and try MPLAB Tools for VS Code).
  • Send my hex file to Windows or Ubuntu to program the device with MPLAB IPE v6.20 and the PICKit 3.
    • Even automate this with an Ubuntu machine: see “Remote Control Programming: macOS to Ubuntu to PICkit 3” below, where I demonstrate compiling on macOS and using a script to program remotely on Ubuntu
  • In the meantime, I will continue to look for solutions to get my PICkit 3 working on macOS again.

PIC12F675 Specs

The microchip site has plenty of info and datasheets for the processor. The core specs:

  • 1024 words flash memory
  • 64 bytes SRAM
  • 128 bytes EEPROM
  • 6 I/O ports
  • 4 channels ADC (10-bit)
  • 1 comparator
  • 1 timer (8-bit)
  • 1 timer (16-bit)
  • internal 4 MHz oscillator, up to 20 MHz oscillator / clock input

PIC12F675_pinout

PIC12F675 Development Board

I got myself a development board like this: “1PCS NEW 5V PIC12F675 Development Board Learning Board Breadboard L87” (aliexpress seller listing) purchased for US $6.99 (Feb-2017).

It appears to be a very common board - the same as used by Julian - and features the PIC12F675, one of the “Mid-Range 8-bit MCUs” in the PIC family.

GettingBlinky_dev_board

Male-to-female Dupont connectors are fine for connecting the programmer. I also followed the suggestion and made up a cable using a 6-wire “5S1P balanced charger cable” with a 6-pin JST XH female connector on one end and a 6-pin header on the other.

Development Board Circuit and Mods

The development board includes a number peripherals to play with:

  • 2 LEDs (configured active low)
  • 2 push-buttons with pull-up resistors
  • 1 potentiometer (between VDD and ground)
  • reset button with pull-up and RC de-bounce

Power can be provided by the programmer or via the DC jack (with power switch and filter caps).

I’ve sketched the circuit in Fritzing, see GettingBlinky.fzz:

Schematic

One curious thing about the board is how VPP is connected via the RESET switch and debounce circuit. Although this works just fine, there’s a mod recommended by Julian to rewire VPP to connect on the other side of the RESET jumper so that it is possible to remove the RESET jumper and still have VPP connected correctly.

In practice, I’ve not seen a need to use this yet, although I did modify my board to make it possible.

See GettingBlinky-patched.fzz for the modified circuit:

GettingBlinky-patched_schematic

Toolchain

I’m using the MPLAB X IDE which is built on NetBeans and offers great cross-platform support. I’m running it on macOS 15.7/ARM as my preferred platform, but have also tested on Windows 11/Intel, and Ubuntu 24.04/Intel.

I am primarily using MPLAB X IDE v6.20 as it is the last to include PICkit 3 support, but I can also compile with the latest MPLAB X IDE v6.30.

I am using the latest MPLAB XC8 v3.10, which includes C compiler and PCI-as assembler. PIC-as replaces the MPASMWIN assembler used back in 2017.

MPLAB X IDE is actually a great environment, although a little hard to find things at first. A real boon is the built-in simulator, allowing code execution, breakpoints and step-by-step debugging all without a target device or programmer attached.

mplab_ide

The Code

Just a single source file - see blinky.asm. It is just about the simplest thing you could do - blink an LED of course.

The code was originally written for Microchip’s MPASMWIN assembler, but I have now updated the code for the PIC-as assembler that has since replaced it.

I’ve avoided any include files, preferring to need to figure it all out (with some serious cribbing from Julian Ilett). Relevant definitions may be found in the files that xc.inc includes, such as:

  • /Applications/microchip/mplabx/v6.20/packs/Microchip/PIC10-12Fxxx_DFP/1.7.178/xc8/pic/include/pic.inc
  • /Applications/microchip/mplabx/v6.20/packs/Microchip/PIC10-12Fxxx_DFP/1.7.178/xc8/pic/include/proc/pic12f675.inc
  • /Applications/microchip/mplabx/v6.20/packs/Microchip/PIC10-12Fxxx_DFP/1.7.178/xc8/pic/include/proc/12f675.cgen.inc

Configuration Bits

The configuration word (address: 2007h) - documented in section 9.1 of the datasheet - is used to configure chip features. The IDE includes a configuration bits editor that can help derive suitable values.

I’m running with 0x31F5 (0b11000111110101), which breaks down as follows.

Bits Selected Definition
13-12 11 Bandgap Calibration bits for BOD and POR voltage. 11 = Highest bandgap voltage
11-9 000 Unimplemented, read as 0
8 1 Data Code Protection bit. 1 = disabled
7 1 Code Protection bit. 1 = disabled
6 1 Brown-out Detect Enable bit. 1 = enabled
5 1 MCLRE Select bit. 1 = GP3/MCLR pin function is MCLR
4 1 PWRTE: Power-up Timer Enable bit. 1 = PWRT disabled
3 0 WDTE: Watchdog Timer Enable bit. 0 = WDT disabled
2-0 101 FOSC2:FOSC0: Oscillator Selection bits. 101 = INTOSC oscillator: CLKOUT function on GP4/OSC2/CLKOUT pin, I/O function on GP5/OSC1/CLKIN

With PIC-as, the configuration can be set literally:

config "CONFIG" = 0x31F5

or using specific configuration word definitions e.g.:

config FOSC = INTRCCLK
config WDTE = OFF
config PWRTE = OFF
config MCLRE = ON
config BOREN = ON
config CP = OFF
config CPD = OFF

Where to find these word definitions? The docs have endless redirection, but eventually one will find themselves inside the board support packs. Specifically for the 12F675 on my mac, these are the critical files:

  • file:///Applications/microchip/mplabx/v6.20/packs/Microchip/PIC10-12Fxxx_DFP/1.7.178/xc8/docs/pic_chipinfo.html - menu of chips
  • file:///Applications/microchip/mplabx/v6.20/packs/Microchip/PIC10-12Fxxx_DFP/1.7.178/xc8/docs/chips/12f675.html - for the 12f675
  • /Applications/microchip/mplabx/v6.20/packs/Microchip/PIC10-12Fxxx_DFP/1.7.178/xc8/pic/dat/cfgdata/12f675.cfgdata - configuration word definitions

With that oscillator setting, can conveniently measure the clock (FOSC/4) on pin 3 (GP4/OSC2/CLKOUT), around 1.063MHz according to my scope i.e. FOSC=4MHz:

scope_clock

Turning an LED on and off

GPIO ports default to input, so clearing the corresponding bit in the TRISIO register sets the port state to output:

bcf TRISIO, 0

Then clearing and setting the corresponding bit in the GPIO register sets the output state high or low:

bsf GPIO, 0
bcf GPIO, 0

But… TRISIO and GPIO registers are in different “banks”, so it is necessary to set the correct bank in the STATUS register first by setting or clearing the RP0 bit.

Adding Delay

It’s been a long time since I did any assembler, and I’d forgotten that with great power comes … the need to do everything for yourself. None of this sleep(500) business!

I obviously want to slow my LED blinking down to something visible. Julian demonstrated how you can do this by just slowing down the clock. But keeping the clock at full speed requires delay code, and there are many approaches ( just google it ).

I chose to use a trick based on an idea I found here.

It essentially does a 2’s complement of the 1’s complement to increment by one, with a few NOPs thrown in to produce a loop of 8 clock cycles.

Surrounded by a few make-work loops, the result is an LED blinking at around 4Hz:

scope_led_pulse

The Programmer: PICkit 3

I got myself a clone PICkit 3 programmer, purchased for US$18.85 (Feb-2017): “pickit 3 Programming / emulator + PIC microcontroller / minimum system board / development board / universal programmer seat” (aliexpress seller listing).

Only 5 of the pins are relevant for programming the PIC12F675:

PIC12F675 Pin Programmer Pin Function Description
MCLR (4) VPP (1) VTEST MODE Program Mode Select
VDD (1) VDD (2) VDD Power Supply
VSS (8) GND (3) VSS Ground
ICSPDAT (7) PGD (4) DATA Data Input/Output
ICSPCLK (6) PGC (5) CLOCK Clock Input

Notes:

  • MCLR is the Master Clear (Reset) input/programming voltage input. This pin is an active low RESET to the device
  • In the PIC12F675, the programming high voltage is internally generated. To activate the Programming mode, high voltage needs to be applied to MCLR input. Since the MCLR is used for a level source, this means that MCLR does not draw any significant current.

One important configuration item is to enable the programmer to provide power to the target device, if it is not powered separately. I generally have this set to 4.75V, as I’ve seen reports of , and experienced myself, intermittent communication issues if the full 5V is selected (the programmer complains that it has detected a VDD lower than specified).

mplab_programmer_power

Of course, the board also works just fine with external 5V power connected after the chip has been programmed:

GettingBlinky_external_power

PICkit 3 Programming on macOS

I had no issues with PICkit 3 on Intel-based macOS running MPLAB X IDE v3.51 and later v5.30.

Now on ARM-based macOS and MPLAB X IDE v6.20, I have so far been unable to get the PICkit 3 to work:

  • It usually shows up in the USB device tree, and is recognised by the IDE/IPE
    • with some cables, especially long ones, it doesn’t even show up in the USB device tree (as viewed with System Information)
  • But any attempt to get programmer status or perform a programmer operation fails

mac-pk3-fail

Since the new Macs lack a type-A connector, I have to use a USB-C to USB 2/3 port extender. This may be contributing to the problem, especially as I suspect the root issue is USB power management. Microchip/Atmel programmers are notorious for poor USB power design. The Pickit 3 draws 100mA+ and tries to source 200mA+ to targets, which is right at the USB 2.0 limit. Combined with voltage drop across extenders, I may be running headlong into the Mac’s protection thresholds.

What next? I will try to find another USB extender to see if it works any better, but for now I am giving up on trying to get the PICkit 3 working on the Mac.

PICkit 3 Programming on Windows

I only did this to get a benchmark of what should be expected to “work”! I installed MPLAB X IDE v6.20 on Windows 11/Intel, and have had no issue compiling and programming with the PICkit 3 programmer.

win-mplab-4

PICkit 3 Programming on Ubuntu

What about Ubuntu? That would be more interesting, as it is the workhorse OS I mostly use in conjunction with macOS.

I installed MPLAB X IDE v6.20 on Ubuntu 24.04/Intel, and have had no issue compiling and programming with the PICkit 3 programmer.

ubuntu-mplab-2

Remote Control Programming: macOS to Ubuntu to PICkit 3

So given that I can compile on macOS, and much prefer to work there, and can program on Ubuntu, what about combining the two?

The IPE program supports a command-line mode, and there’s a script for it installed as part of the MPLAB X IDE. I found it here: /opt/microchip/mplabx/v6.20/mplab_platform/mplab_ipe/ipecmd.sh

I’ve written a little script ipe-remote.sh that I can now run from macOS to send a hex file I’ve compiled locally to my Ubuntu machine with PICkit 3 attached

$ ./ipe-remote.sh
Remote IPE programming script
Usage: ./ipe-remote.sh <hostname> <chip_type> <hex_file>
Example: ./ipe-remote.sh user@remotehost 12F675 mycode.hex

$ ./ipe-remote.sh ronda-u1 12F675 Blinky.X/dist/default/production/Blinky.X.production.hex
Blinky.X.production.hex                                                                                                                                                                                                          100%  216    17.7KB/s   00:00
DFP Version Used : PIC10-12Fxxx_DFP,1.7.178,Microchip
*****************************************************
Connecting to MPLAB PICkit 3...
Currently loaded firmware on PICkit 3
Firmware Suite Version.....01.56.09
Firmware type..............Midrange
Programmer to target power is enabled - VDD = 4.750000 volts.
Target device PIC12F675 found.
Device Revision ID = b
Erasing...
Erase successful
Device Erased...
Programming...
The following memory area(s) will be programmed:
program memory: start address = 0x0, end address = 0x3ff
configuration memory
Programming/Verify complete
PICKIT3 Program Report
2026-02-06, 17:12:54
Device Type:PIC12F675
Program Succeeded.
PK3 Verify Report
2026-02-06, 17:12:54
Device Type:PIC12F675
The following memory areas(s) will be verified:
program memory: start address = 0x0, end address = 0x3ff
configuration memory
EEData memory
User Id Memory
Verification successful.
Verify Succeeded.
Operation Succeeded

Credits and References

Video Tutorials

PIC Assembly Language Tutorials: #0 - Shopping List & Mods

YouTube by Julian Ilett

clip

PIC Assembly Language Tutorial: #1 - Config and Clock

YouTube by Julian Ilett

clip

PIC Assembly Language Update: #1.1 - PCB schematic

YouTube by Julian Ilett

clip

About LEAP#331 PICLEDPIC12F675

This page is a web-friendly rendering of my project notes shared in the LEAP GitHub repository.

Project Source on GitHub Return to the LEAP Catalog
About LEAP

LEAP is my personal collection of electronics projects - usually involving an Arduino or other microprocessor in one way or another. Some are full-blown projects, while many are trivial breadboard experiments, intended to learn and explore something interesting.

Projects are often inspired by things found wild on the net, or ideas from the many great electronics podcasts and YouTube channels. Feel free to borrow liberally, and if you spot any issues do let me know or send a pull-request.

NOTE: For a while I included various scale modelling projects here too, but I've now split them off into a new repository: check out LittleModelArt if you are looking for these projects.

Project Gallery view the projects as an image gallery Notebook reference materials and other notes Follow the Blog follow projects and notes as they are published in your favourite feed reader