May 22, 2024

PIC16F87x support in ZEPPP

Almost 3 years ago I developed and published ZEPPP, my Arduino-based, “Zero-External-Parts” PIC Programmer, and wrote about it here on my blog.

From time to time I hear from people using it, and, sometimes I would also get questions about whether specific PIC devices are supported.

Now, ZEPPP is pretty limited in scope, as it was made to target the 16F628A primarily, but when I wrote it I also added support for other mid-range 8-bit PICs that employed similar programming procedures, and were popular back in the day. Just to echo the list, from day one ZEPPP had support for:

  • 16F87, 16F88
  • 16F627A, 16F628A, 16F648A
  • 16F873A, 16F874A, 16F876A, 16F877A

The Question

One of the PIC families that ZEPPP has supported from the start, is the 16F87XA line of microcontrollers. That means the 16F873A, 16F874A, and so on. They are not particularly modern devices, mind you, but in a couple of occasions, I’ve been asked whether ZEPPP could support the “non-A” variants, which predate the “A” versions although were almost functionally the same.

A Picture of a PIC 16F871
A PIC16F871 I bought from a fellow PIC enthusiast.

This is not something I get all the time, in fact, I had not heard that request in probably a couple of years, until recently a user on my blog echoed the same question, and he was apparently knowledgeable and interested enough in this, that he was already looking into adding the support himself.

It’s worth noting that the 16F628A also has a “non-A” version, and it’s not compatible with ZEPPP because it does not support LVP, which is what ZEPPP uses to program the chips. So it wouldn’t be crazy to assume that the 87X line of microcontrollers were the same, with the “non-A” parts not supporting LVP…

Except they do. The non-A plain “87X” parts, do, in fact, support LVP. So maybe it was just a matter of treating them like the “A” parts? Maybe?


I didn’t have any “non-A” part to try, but Ken (the user who posted the question), had a bunch of 16F876 devices, and he was more than willing to test, so we started tinkering with it. I branched the code from the repository and added settings for the 87X parts that mirrored the 87XA settings, and then asked Ken to test.

He reported very thoroughly the behavior of ZEPPP, and unfortunately the non-A parts would refuse to be programmed the way the “A” parts did, so I spent the next afternoon comparing the programming specifications of both 87XA and 87X parts trying to find the differences.

After looking at them side by side I noticed that most of the timing and the memory reading commands were the same, but the “non-A” parts did not support block writes, and had completely different erase algorithms. Fortunately there was support in ZEPPP already for non-block writes (because the 16F628A also lacks support for them), so I configured ZEPPP to use that style of programming with the 87X parts and asked Ken to try again. This led to a version of ZEPPP that was able to write and read to 87X parts, but was unable to erase them.

The Hunt for non-A Parts

This was good enough for most uses, but I wanted to have full support for all operations, and that meant having a way of testing the code myself, as new low-level routines were needed in the firmware, and that was not as straightforward.

To do this, I ordered a handful of old 16F877 from eBay, but that was not something that would arrive anytime soon.

In the meantime I found a small shop nearby, that according to their online listing had stock of 16F871 PICs, an old part of which no “A” variant exists. This store was run by a guy who’s been developing custom PIC projects for different clients for a long time, and of course had several very ancient PICs ready to sell.

In a matter of days I got a few 16F871 PICs to play with, and after another night of work I finally managed to implement the erase procedures for all memory areas, and was able to confirm that they worked with my 16F871 PICs. I also asked Ken to test on his 16F876 ICs, and he also reported success.

Polish and Fixes

I was quite happy now with ZEPPP successfully programming the 87X devices, but I also took this opportunity to improve the code a bit. There were a few places where changes were needed; From the internal structure of the code, to error messages and the behavior of some commands. There were also some assumptions inside ZEPPP that I wasn’t quite happy with.

All the changes are now in the ZEPPP Git Repository. The project now also includes a Changelog where you can check what was added/changed in more detail.

I would like to thanks Ken again for his very generous help testing the support for 87X parts, and for starting this whole endeavor that resulted in a handful of improvements to ZEPPP, and the support for a new (old?) family of devices.

12 thoughts on “PIC16F87x support in ZEPPP

  1. 16F887
    Trying to program this chip, with INTRC, and including ‘ignore out of bounds flag as I was getting the ERROR: Memory address 0x4010 is not mapped to any memory space in the selected device (16f887) error statement.
    I am now getting
    INFO: Failed to Verify data at offset 0x0000!. Expected 0x2fe4. Got 0x3fe4 instead
    INFO: Verification can fail if CP was enabled, or the Conf. Word tried to disable LVP.
    The program still doesn’t seem to be running in the microcontroller, I’ve tried a simple blink sketch with still no success.
    Any ideas?

    1. Hi!
      Check the config word in your code. I would recommend you to make sure it doesn’t attempt to disable LVP, but also I think you might be setting Code Protect to ON, in which case you will always need to erase the device before programming, and even then I’m not entirely sure if verification would pass on that device with that flag set.

  2. I wanted to test a pic16f877 that was laying around here.
    I dont have a compiler on hand and used this hex.
    Zepp wasn’t able to upload all of it.

    Connecting to ZEPPP interface…
    — Interface detected: ZEPPP 1.0.2 20220824
    Detecting connected device…
    — Device Name: 16f887
    — Device ID: 0x0104
    — Device Revision: 0x0005
    Reading input Hex file: C:\Users\roman\Downloads\blink.hex
    ERROR: Memory address 0x4010 is not mapped to any memory space in the selected device (16f887)

    1. Hi,
      That’s definitely outside the programming memory space of that device (goes up to 0x1FFF). Some compilers tend to generate extra data that goes outside the memory mapping, and that could be the problem in this case. Try adding the -ignore-bounds-error flag.

    2. Hi,
      I half forgot about my comment. I’ve tested it and it works. Thanks.
      Maybe i will build an serial LED matrix out of it

    1. Adding support for High-Voltage Programming can definitely be done by means of a charge pump (like in the example) or by adding an external 12V supply. I’ve been thinking about toying with adding a HVP attachment, but It would stop being “zero external parts” at that point, and Arduino-based programmers who require some circuitry to be build already exist (for example the project you just linked me). It would be an interesting experiment, and I may add it like a sort of “optional” upgrade, but I wouldn’t want to make it a core part of ZEPPP.

    2. It’s probably going to be a small circuit, so I don’t see it as terribly offensive to the concept. I will try to play around with the idea, but as mentioned, there’s already other programmers that require circuitry and do HVP, and they probably already support a whole lot more devices than ZEPPP does. Not sure if it will be of benefit, at all.

    1. Hi Albert,
      Unfortunately that family of devices doesn’t seem to support LVP, so they wouldn’t be compatible.

Leave a Reply

Your email address will not be published. Required fields are marked *