The datasheet says 3.5 KB of program memory. The programmer reports 2,048 addresses. Both numbers are correct, and the gap between them is where small-flash dumps quietly go wrong.
The PIC16F1782 is a 28-pin part from Microchip’s advanced-analog line, documented in DS41410. It carries 256 bytes of RAM, 256 bytes of data EEPROM, a 12-bit ADC with eleven channels, an 8-bit DAC, three fast comparators, two rail-to-rail op amps and two programmable switch-mode controllers, all driven by an enhanced mid-range core with 49 instructions, a 16-level stack and a 32 MHz internal oscillator. Designs that use it are usually power supplies, LED drivers or three-phase motor stages, where the firmware is mostly timing tables rather than branching logic.
Where 3.5 KB Comes From
Program memory on this core is organised as 14-bit words, not bytes. Two thousand and forty-eight of them add up to 28,672 bits, which is 3,584 bytes, which is the “3.5 KB” on the front page. A programmer does not report bytes. It reports word addresses, and the last one on a 1782 is 0x07FF.
Intel HEX splits each 14-bit word into two bytes, low byte first, and doubles the address to get a byte offset, so the configuration word at 0x8007 appears in the file at 0x1000E. A hex file for this part that ends at 0x0FFF holds 2,048 words and is a complete array. One that ends at 0x0BFF is missing the top half, where XC8 puts lookup tables that no branch points at directly.
What Lives Above the Array
| Word address | Contents | Readable with CP set |
|---|---|---|
0x0000–0x07FF |
program memory, 2,048 words | no |
0x8000–0x8003 |
user ID, 14 bits each | yes |
0x8006 |
device ID, DEV<8:0> + REV<4:0> |
yes |
0x8007 |
CONFIG1, holds the CP bit |
yes |
0x8008 |
CONFIG2 |
yes |
0x8009–0x8011 |
factory calibration words | yes |
The device ID field reads 0x150 on a 1782 and 0x151 on the PIC16F1783. One bit separates a 3.5 KB part from a 7 KB part, and it is the only reliable way to know which die you are holding once the marking has been sanded off.
A file that stops at 0x07FF contains the code and nothing else. Oscillator mode, watchdog, brown-out threshold and code-protect state all sit at 0x8007 and 0x8008. Load such a file into a blank part and it comes up on the default clock, which on a crystal-based board is the wrong one. The code runs, badly, and the copy gets blamed.
One Bit, Whole Array
The 178x family does not offer per-block code protection. A single CP bit in CONFIG1 covers 0x0000–0x07FF. When it is programmed, ICSP reads return zeros across the entire array, so there is no partially readable image and no boundary to reason about.
0x0000 is a legal instruction on this core, NOP, and an erased word reads 0x3FFF. A protected 1782 therefore disassembles into a ribbon of no-ops that looks like padding, so anyone who validates a dump by confirming that it disassembles will pass a file containing no firmware at all.
The Checksum Hidden in the User IDs
MPLAB X can compute the checksum of an unprotected build and store it in the four user ID locations, one nibble each, most significant first. User IDs are not covered by CP, so those four words stay readable on a protected part. That gives a verifier something rare: a fingerprint of the original image that survives the lock.
Rebuild the image, run the same checksum, compare nibble by nibble. A match says the reconstruction is bit-exact; a mismatch tells you a word is wrong without saying which one, but it still separates “close” from “correct”. If the build never enabled the option, the user IDs usually hold a date code or a serial, which is useful for other reasons.
256 Bytes That Are Not Optional
The data EEPROM on a 1782 is small enough to look like an afterthought. In analog designs it usually holds the trim values: op-amp gain selection, fixed-voltage-reference settings, and the ADC offset measured on that specific board at test. The flash image contains the code that reads those values. It does not contain the values.
A replacement with a correct flash image and a blank EEPROM boots, runs, and reports temperatures and currents off by several percent, because a 12-bit converter is being corrected with default constants. That failure gets reported as “the read did not work” when the read was complete and the EEPROM was never requested.
Ask for the array, the configuration block, the calibration words, the user IDs and the EEPROM in one file, plus a note on the CP bit. The reading the program memory page describes how each region is captured, and the services page lists what a delivered image includes.