PIC Ecosystem

Leslie Foster
20 min readMay 27, 2024

--

How to start coding for the PIC16LF18324

If you have already done a few projects with a Raspberry PICO, or one of the various Arduinos, and you would like to try working on a different microcontroller, you may be interested in the PICs from Microchip corporation. These include some 8-bit microcontrollers, which are sometimes an interesting challenge. Although there can be some money involved to do the setup, the chips themselves are inexpensive and can be fun to build with and explore.

This article tells what tools are required to get started. Please note that this article covers PIC microcontrollers themselves, rather than development boards. There are development boards for PIC microcontrollers that, although more expensive than an individual PIC microcontroller of the type covered here, can help you to avoid purchasing the PicKit item covered below.

If you are still interested, and want to get beyond the development boards or other pre-soldered approaches, read on.

Why PIC?

One interesting aspect of the PICs is that there are special low-power chips in the family. Low-power use is a challenge akin to designing a fast algorithm, but it can be aided greatly by the right choice of MCU. The Arduino “platform” is a great starting point for many of us. It lends itself easily to exploring related AVR chips like the ATTiny85. But if you want to get a broader understanding of microcontrollers and move beyond the world of Arduino, the PIC family can be an avenue to do that with very low power offerings. One such offering is the PIC16LF18324 (also: 18324, “chip” or “pic” from this point). This is an 8-bit chip, not 16 despite the name. It has 14 pins, 12 of which are I/O pins. Other members of the PIC family have various pin counts. The “L” in the name is for “low power”. There is also a non-low-power model (no ‘L’ in its name) but that model will not be covered here. The price for just the PIC16LF18324 chip is comparable to the ATTiny85. Like the ATTiny85, it can be bought in through-hole or surface-mount packages, and it has an internal oscillator.

The 18324 runs at 32MHz out of the box (no external crystal required to attain this speed). The internal oscillator is factory calibrated. It has 7KB of flash and 1/2K (512 bytes) of static RAM onboard. There is a wide range of peripherals (like so many MCUs):

  • USART (called an enhanced USART or EUSART)
  • I2C
  • SPI
  • PWM (often used in motor control or TV and other remotes)
  • Timers (including capture/compare); also a “watchdog” timer.
  • Analog/Digital Converters and Digital to Analog Converters
  • Of course: the ability to read pins or write digital values to pins (1 for LED on; 0 for LED off)

One thing that is especially nice about the 18324 is its PPS. This “peripheral pin select” feature allows you to use most of the pins for any peripheral. You may have seen pinout diagrams for various microcontrollers? While the 18324 may have some default settings for pins, you are free to route things with considerable flexibility. Although there may be some limits to this (based on things like clock speed; specific pins that are not PPS mappable), you can for example route the EUSART TX pin to RC4.

Speaking of pins, the 18324, being limited to 14 pins, has its I/O pins designated as being in either RAn or RCn. Larger members of the PIC16 family will also have an RBn set. Two pins are “busied” with power service (VDD and VSS). Unlike many other chips out there which have their power pins at opposite diagonals, VDD (power) and VSS (ground) are on opposite sides of the notch at one end. The power pins are on one end of the 18324 chip. The full pinout is shown below.

Pinout of PIC16LF18324

Now that this brief rundown has been provided, it is time to look at the setup, or “gear” needed to get going on a PIC16lf18324.

Prerequisites

If you wish to merely read about this for the sake of interest, please do. But if you wish to code along with this article, you will need to either have the following, or be willing to get it.

  • Breadboard
  • The PIC16LF18324
  • Programming device
  • Wires (or Dupont cables)
  • An LED
  • Two resistors
  • 220Ω to 330Ω should be fine. Higher values may be OK but the LED will be dimmer. We will assume 220.
  • 5.1 kΩ pull up resistor (or approximate)
  • A 0.1 µF capacitor. Ceramic, non polarized is recommended
  • Some kind of power supply. Batteries should be fine. You will need approximately 3.3V.
  • It would be beneficial to have some knowledge of ‘C’ code. The code is provided, however.

Buying the Chip

These can be ordered from DigiKey or Mouser. Both offerings are under $2 (seen in May 2024 for $1.29 to $1.56 each). Discounts for bulk may bring the price down still further. Be careful to get the packaging you need. In order to snap one of these into a breadboard you will need a through hole package like “PDIP”. This may be referred to as “14 PDIP” or “PDIP-14”. Also, please be aware of shipping costs which can be more than the price of multiple such chips. You may find that purchasing these in groups of three or more can defray the cost of shipping. Amazon may have PIC boards (not compatible with these instructions but usually easy to work with) available for less than $20.

The Biggest Expense: the Programmer

It may be possible to get exposure to PIC16 family chips using a development board for in-system-programming. And if the reader is interested in leveraging an investment, it might be worth a good google. However, you may wish to “remove the training wheels” so to speak and get deeply into the ecosystem. Going with the raw microcontroller requires the use of a programming device. This is frequently an expenditure for working with microcontrollers and this one is no exception. If you are clever enough to make this happen without purchasing this device, feel free.

In the past the PICkit 4® was available at around $100, and is described below. More recently, PicKit 5 was introduced and PicKit 4 was obsoleted by the manufacturer. However the price is roughly the same. Similar functionality is assumed. Both are compatible with the MPLAB X IDE v6 software (more below). There may also be less expensive devices (< $40) available by now. Your mileage may vary.

The MPLAB PICKit4 has a set of connector holes on one end (or “the bottom” if you use the written labeling on it as a reference). It has a very specific pinout. You will need to connect the holes to your breadboard. Dupont cables or simple wire work fine. If you do lots of projects on these chips, you may find you want to build something for more convenience.

The other end of the PICKit4 has a small USB 2 connector. That can be plugged into your PC (folks use MAC and Linux as well according to forum posts). Once plugged, you can program from the IDE.

The Software

Loading the code into the microcontroller can be done here with a C compiler and a downloadable piece of software called MPLAB X IDE. At time of writing this is at version 6.

Above is a screen shot of the software.

There is a full set of instructions below, but the page Install MPLAB® X IDE Version 6.00 Walkthrough — Developer Help from Microchip is also available as an alternative. MPLAB X installs similarly to other IDEs (actually, based on files in the installation, this one may be based on the NetBeans IDE from Apache, with a lot of customization for use with Microcontrollers).

Setting up a wholly new PIC16LF18324 project in this IDE is described below, but first some breakdown of useful tools and necessary dialogs.

Some Tools and Dialogs

After you create a project, it is highly useful to have a look at the properties page. To do so, as illustrated to the left, “mouse click” (left click on Windows or otherwise bring up a menu as you normally would with your OS) and then click the “Properties” menu item at the very bottom. Later / earlier versions of the IDE may place this differently, but “Properties” is a very likely name.

Properties menu item

Clicking will bring up a new popup dialog as shown below, which includes setting the device name to work with. That setting is necessary to get things like debugging and burning code to the builtin flash drive correct.

Screen shot of the properties dialog

Please note the tree structure on the left. This changes the mode of the right-hand pane. Clicking its “PICKit4” node will change to the mode below.

PICkit 4 Options

This one is very important for the use of the “Options categories” dropdown, which still further modifies the visible controls.

PICkit 4 Options with Power Option categories

“Power target circuit from the PICkit 4” should be selected. This setting is used when you have connected the PICkit 4 and your PIC chip through the computer’s USB drive. It is needed for debugging and burning code to the flash drive. This value causes the USB power to flow into the board. Not using this allows the power of the board itself to be used. With a simple breadboard-bound chip as illustrated, powering from the PICkit is the correct choice. This is not selected by default. Probably because the software tries to protect all the hardware. If there were a backing power supply in use on the target board, this setting would not be a good idea. In fact, one might go as far as to say not to change this setting to “Power target circuit from PICkit 4” until and unless you receive a popup telling you to do so. The PICkit / IDE combination will complain with a popup error dialog if this is needed and not set. Be sure to click the “OK” button to save the setting.

The Configuration Bits

Window / Target Memory View / Configuration Bits item

This menu item opens the “Configuration Bits”. In the PIC realm this is how special flash-burned settings for configuring the hardware at a low level, are selected. Other microcontrollers may refer to these settings as “fuses”, if you are familiar.

The Bit Settings

These are the settings that may be configured here. They can give you a few ideas of some of the interesting things this modest chip can actually do (brown out detection, the PPS (peripheral pin select) mentioned above, and the watchdog timer are all hinted at here). The most relevant to this discussion is probably the “FEXTOSC” / “RSTOSC” pair of settings at the top. This PIC chip is flexible with respect to clock drive. External oscillators may be used, but should not be bit-set here unless they are being used. For purposes of this discussion, set FEXTOSC (external oscillator) off, and set RSTOSC (reset-defaulted oscillator) to the NFINT32 (read “internal 32,000,000 Hz”) setting. That can be set to 1 MHz as well. But the external settings will require wiring up an oscillator to drive the chip, and is beyond the scope of this discussion. It also occupies pins, costs more money and requires playing with more hardware.

Also, set the Watchdog Timer setting “WDTE” to “OFF”. This is a very useful power saving and error correction device. But it is not used for this simple demo, and it will reset the chip, which is not desirable.

Regarding the code presented elsewhere in this document: additional code to the actual operational part was generated by clicking the “Generate Source Code to Output” button above. That produces the code you see at the beginning of the source, starting with:

// PIC16LF18324 Configuration Bit Settings

The Compiler

We will install the XC8 compiler. It is available for download at https://www.microchip.com/en-us/tools-resources/develop/mplab-xc-compilers .

We have an 8-bit PIC

The choice of compiler will affect the code you write and how well optimized it is. This is the one that comes from the same company as the IDE and the chips. It is a safe bet for working well. The download page claims it is “award winning”. The reader is welcome to check up on reviews and alternatives, of course. Also note: if you are a bigger fan of AVRs like the ATTiny series, using a setup similar to that shown in this article could allow you to move away from the world of Arduino. But be aware you may need to purchase the other hardware as well.

Clicking that button leads to a larger page displaying licenses — an important consideration if you plan to distribute projects based on this software. But it also has the download control:

Our download

This one has a date of only a few months earlier at time of writing. That is a good sign that the code is being maintained regularly. The IDE prompts regularly with updates.

The download here will be for an installer. Running that installer will popup the series of dialogs below.

Free is OK for this project
This is the default installation location
Clicking “Next” will install at the location chosen above

Tool Chains

The MPLAB X IDE uses “tool chains” (tools including a compiler and other associated code) to do its builds. They may be managed using “Tools/Options” and clicking the Embedded Icon on the ensuing dialog.

Clicking “Add” on the left, will allow you to include the XC8 compiler just downloaded.

Creating a Project

This may well be your first ever PIC16LF18324 project. Or perhaps an even bigger first. If so, welcome! We will build a simple LED project here.

We start with “File / New Project”.

This will bring up a wizard dialog for making one.

We will be making a Microchip Embedded Standalone Project. There is a rather tempting “Samples” subtree, but that is not relevant to our chip of choice. The standalone project is actually quite simple to deal with.

Having chosen a project, select a device
Best bet: start typing the device name into the Device Combination Box
If you have your PICKit 4 plugged in, you can select it as the tool of choice

Next screen lets you select a compiler. This IDE offers flexibility in this regard.

Selecting the XC8 compiler

Just use the one installed earlier.

At last, we get to name the project

Leaving the “Set as main project” checked will cause this one to be the default choice in many controls. Code will be included to simply blink an LED on and off in a regular pattern, below.

Here is a top-left-corner shot showing our project on the IDE (showing the Files Pane on the left)

The Code

Having gotten this far, we have a starting point for adding the code. For that, you would want to use the projects tab in the IDE to show the Projects pane. You can see from the image below that the Source Files tree node is empty (even expanded, without the ‘+’ sign, there are no files there).

We will remedy that.

Using this control, we can add a “main.c” file. ‘C’ is the language we will use for this program.

Click through this or provide a different name. Let us use ‘blinker’

The raw code produced is simply this.

/*

* File: blinker.c

* Author: you

*

* Created on May 23, 2024, 12:21 AM

*/

#include <xc.h>

void main(void) {

return;

}

This doesn’t do much. But it is a complete program. The challenge now is to fill in the details. Fully fleshed out, this is more like it.

// PIC16LF18324 Configuration Bit Settings

// ‘C’ source line config statements

// CONFIG1

#pragma config FEXTOSC = LP // FEXTOSC External Oscillator mode Selection bits (LP (crystal oscillator) optimized for 32.768 kHz)

#pragma config RSTOSC = HFINT32 // Power-up default value for COSC bits (HFINTOSC with 2x PLL (32MHz))

#pragma config CLKOUTEN = ON // Clock Out Enable bit (CLKOUT function is enabled; FOSC/4 clock appears at OSC2)

#pragma config CSWEN = OFF // Clock Switch Enable bit (The NOSC and NDIV bits cannot be changed by user software)

#pragma config FCMEN = OFF // Fail-Safe Clock Monitor Enable (Fail-Safe Clock Monitor is disabled)

// CONFIG2

#pragma config MCLRE = OFF // Master Clear Enable bit (MCLR/VPP pin function is digital input; MCLR internally disabled; Weak pull-up under control of port pin’s WPU control bit.)

#pragma config PWRTE = ON // Power-up Timer Enable bit (PWRT enabled)

#pragma config WDTE = OFF // Watchdog Timer Enable bits (WDT disabled; SWDTEN is ignored)

#pragma config LPBOREN = ON // Low-power BOR enable bit (ULPBOR enabled)

#pragma config BOREN = OFF // Brown-out Reset Enable bits (Brown-out Reset disabled)

#pragma config BORV = HIGH // Brown-out Reset Voltage selection bit (Brown-out voltage (Vbor) set to 2.7V)

#pragma config PPS1WAY = OFF // PPSLOCK bit One-Way Set Enable bit (The PPSLOCK bit can be set and cleared repeatedly (subject to the unlock sequence))

#pragma config STVREN = OFF // Stack Overflow/Underflow Reset Enable bit (Stack Overflow or Underflow will not cause a Reset)

#pragma config DEBUG = ON // Debugger enable bit (Background debugger enabled)

// CONFIG3

#pragma config WRT = ALL // User NVM self-write protection bits (0000h to 0FFFh write protected, no addresses may be modified)

#pragma config LVP = OFF // Low Voltage Programming Enable bit (High Voltage on MCLR/VPP must be used for programming.)

// CONFIG4

#pragma config CP = ON // User NVM Program Memory Code Protection bit (User NVM code protection enabled)

#pragma config CPD = ON // Data NVM Memory Code Protection bit (Data NVM code protection enabled)

// #pragma config statements should precede project file includes.

// Use project enums instead of #define for ON and OFF.

#include <xc.h>

#define _XTAL_FREQ 32000000 //define crystal frequency to 20MHz

void main(void) {

TRISC0 = 0; //set RC0 pin as a digital output pin

while (1) {

RC0 = 1; // set RC0 pin to logic High & turn on

__delay_ms(250); //add delay of 1/4 second

RC0 = 0; // set RC0 pin to logic low & turn off

__delay_ms(1000); //add delay of 1 second

}

return;

}

When the pins of the MCU (the chip) are wired correctly, and this has been burned onto the chip, it will cause the LED we will wire below to flash on and off.

At the beginning of the code (and including most of it) are the ‘bit’ settings mentioned earlier. Removing those may actually cause different behavior, even though they mostly consist of ‘C’ pragma settings. You do not need to understand how these work per se, as they are generated for you.

One thing you may notice about this code is all of the references to variables that were not declared. Those are actually ‘register’ locations. The pins of an MCU are usually backed by special hardware and have very flexible functions. The PIC here is exceptional in its flexibility. But with flexibility comes the price of having to make selections. This is a more complicated world from something like Arduino sketches where you just call the right procedure. In this case, the RC0 pin had to be setup first. Fortunately, this is a pretty simple and “likely” operation — writing to the pin. Other functions require more steps.

The “while(1) {}” is an implementation of a “forever loop”. It just keeps running. This loop writes a 1 and a 0 with delays in between, to get a higher or low voltage running out of pin RC0. We’ll see how this needs to be wired below.

Flashing the Code

Given the excellent tool set we have at our disposal, we can ‘burn’ or ‘flash’ the code onto our MCU. Programming is necessary by way of special hardware which we mentioned above, because an MCU is very self-contained unlike a general purpose computer. The connectivity of this simple MCU is only what you hook to its pins. It doesn’t have an internet connector or wireless. It does have its own memory (multiple types) and to get the program into its flash (which will stay the same after a reset or power-down) it must be pushed onto the chip using a device like the PICkit 4. These devices often use special voltage levels. This can allow the chip to run normally without fear of it being accidentally reprogrammed (and becoming “bricked” or worthless).

The Wiring

During the code-flashing operation, the C code is also compiled into the right format. This is when the breadboard makes its first appearance. In order to burn the program we need to know two things. First, we need to know the pinout of the PIC16LF18324 itself.

Available in the PIC16(L)F183XX product brief

And next we need to know how these pins should be wired to the PICKit4.

MPLAB PICkit 4 In-Circuit Debugger User’s Guide has this detail

There is a certain very special pin involved here. Pin 1 is the MCLR pin. It is “active low”. Because this is part of the chip, it is necessary to keep this one “pulled high” under normal operation. We will do that by using a fairly large (5.1kΩ) resistor going from that pin on our PIC chip to the power rail on the breadboard. The wire running from that one, which is at the mid-point of the pins on the left side if the chip is lined up as above, can also be routed to the programmer’s pin 1. Otherwise, we need to connect the first five pins as indicated.

The Wiring

Given what we now know, the hookup is as illustrated here.

PICkit 4 wired to breadboard and USB
Close up view of PIC16LF18324. Note the small circular indentation. There is also a notch, which you can feel
Close up view of the PICkit wiring. Note the arrow over pin 1

Please note the position of the little indentation at the top edge of the chip. That tells where the “top” is. On either side of that are power to the left and ground to the right. Just to be as clear as possible, the pin pointed to by the arrow (pin 1 of the PICkit) is connected to the middle pin of the chip on the left, which also has the resistor in place. That’s the yellow wire. The red VDD wire is running to the red power rail on the left side of the board. The ground wire is going to the ground power rail on the right side of the board. To power the PIC chip, a smaller red wire is running to the topmost/left side pin and a small gray wire is running to the topmost/right side pin. The blue wire is connected at one pin below the ground wire. The white wire is one position below the blue wire.

On the PICkit side, the yellow wire is at pin 1, red at pin 2, black at pin 3, blue at pin 4, white at pin 5. As a check, you should see three empty holes on the PICkit farthest away from the arrow marking. Again, that’s yellow-red-black-blue-white.

Flash Demo

Precaution: Just in case: always Disconnect from Debug Tool before flashing

Doing this disconnect before attempting the flash may assure a more smooth experience.

This is the control to write to the pic

You may have to select your PICkit as the tool for flashing

The screen below will appear unless you check the “do not show this message again” box. After this, the flash will take place. This is an important warning, as some devices are 3.3 and others may be 5 volts. The PIC16LF18324 works at 3.3V. There is one further issue that requires a setting to be made in the IDE. Here the warning was left in, because it is easy to overlook.

The PIC16LF18324 is a 3.3 volt device. Please beware of this warning for other devices

Gotcha

There is a step that must be done with this setup prior to programming / flashing the MCU. The error message below:

…tells us that the default setting is “device is powered”. This is an important feature of the PICkit 4. It can power the device or it can be used to program a device that has its own power. But the settings err on the side of safety.

The setting to change can be found with this sequence:

Menu-click over the project name in the projects pane and select “Properties”
Click PICkit 4 in the outline view, and select “Power” from the Options Categories dropdown
Check the “Power target circuit from PICkit 4” and click the “OK” button

To be on the safe side, after this step you can go back in and see that the setting is still there. It may be advisable to click Debug / Disconnect debug tool after this failed attempt. Now, just try the burn step again.

If all goes well, you should see something like this

If all is not well, please recheck the wiring. If the wires are wrong, you may see this instead.

Wrong wiring!

The Fun Part

Most programmers are aware of the “Hello, world” moment. This is when you have a crude working program that, well, works. If you are learning a new programming language, framework, or system, getting that to work can tell you that things are at least connected and you do not have syntax errors. In the world of Microcontrollers, this same milestone is most often achieved by making a blinking LED. Microcontrollers do not require a video display. Blinking the LED is important because you could accidentally hook an LED up to power (don’t do that without a resistor) or a pin that is just misconfigured and still have it light up continuously. If it blinks, that proves you are running an actual program and making things happen in the world.

To make that happen here, we will need different wiring. We need to wire some 3.3V power supply to the left side’s power rail and the supply’s ground to the ground rail as shown. Then, RC0 is the 3rd pin from the bottom right of the 18324. That needs to be connected to the 220 ohm resistor. The other end of the resistor should go to the forward bias (or power receiving pin) of the LED, which gets its other pin connected back to ground. Press the two leads of the 0.1µF capacitor into the “power rails” of the breadboard. You should also ensure that a wire connects both of the ground rails. This is just one possible way to wire this up. The important thing is that there is a ground and power for the chip and a ground for the LED, and the pin is connected to the LED.

An aside on wiring

The setup shown here is very minimal. The data sheet recommends that you use a volt splitter with a capacitor at the reset pin. We are using only a single resistor.

Not glowing
Glowing

If the code is correct and the wiring is correct and the chip has been correctly programmed, you should see the LED blink on once per second, and each lit period should be ¼ second.

Important disclaimer: although low power operation was mentioned in this article, the introductory code used here is far from achieving that. Please do not think this is the best we can do with this chip.

Conclusion

This concludes a run down of the tool set, culminating in a demo of what can be accomplished. Of course this is only the beginning. MCUs like this one include a host of other features and capabilities. Even with hardware as simple as being able to read a 1/0 input or produce a 1/0 output can be exploited in myriad ways, and there is so much more that can be done with an MCU. Knowing how to get code running on a microcontroller, you can begin to explore everything else it can do.

I would like to thank Drew Foster for editorial input.

--

--

Leslie Foster
0 Followers

Programmer / Developer / Software Engineer since late 1980s