The board enumerates. The firmware answers. Every analog channel reports a value that is four times coarser than it should be, and the control loop hunts. Nothing in the hex file looks wrong, because nothing in the hex file is wrong.
The PIC18F4553 is the 12-bit-ADC member of the PIC18F2458/2553/4458/4553 family, documented in DS39887. It carries 32 KB of flash, 2,048 bytes of RAM split as 1 KB of USB dual-port memory plus 1 KB of general purpose, 256 bytes of data EEPROM, a full-speed USB 2.0 device interface with sixteen endpoints, a streaming parallel port, thirteen 12-bit ADC channels, one CCP and one ECCP, and 75 instructions at 12 MIPS from a 48 MHz clock.
The Sibling That Fits the Socket
The PIC18F4550 sits next to it in the catalogue with the same 32 KB of flash, the same 2,048 bytes of RAM, the same 40-pin PDIP and 44-pin TQFP, the same USB block and the same support for a crystal-less clock. Distributors stock it deeper and it costs less. When a board is being rebuilt, it is the obvious candidate, and it is the wrong one.
The difference is the converter. The 4550 has a 10-bit ADC module. The 4553 has a 12-bit module, and the two modules do not share a register map: acquisition timing, the negative reference selection, and the way results are justified all differ. Firmware compiled for the 4553 writes 12-bit configuration values into registers that the 4550 interprets under a different definition, so the converter either produces results at the wrong scale or never starts a conversion at all. What an engineer sees is a device that talks USB perfectly and reports a temperature that is wrong.
If a PIC18F4550 is the only donor on the shelf, the honest answer is that the replacement needs its ADC path reworked, not that the copy failed.
The Array in Four Pieces
| Block | Byte range | Words | Bit |
|---|---|---|---|
| 0 | 0x000000–0x001FFF |
4,096 | CP0 |
| 1 | 0x002000–0x003FFF |
4,096 | CP1 |
| 2 | 0x004000–0x005FFF |
4,096 | CP2 |
| 3 | 0x006000–0x007FFF |
4,096 | CP3 |
The four bits live in CONFIG5L at 0x300008. CONFIG5H at 0x300009 adds two more: CPB covers the boot block, CPD covers the 256 bytes of data EEPROM. CPD is the one people forget. A device with CP0–CP3 clear and CPD set gives you a full, readable 32 KB flash image and an EEPROM that returns zeros for every byte — which reads like a wiped part rather than a protected one.
What a USB Image Does and Does Not Contain
Descriptors are code. The device descriptor, configuration descriptor, string descriptors and the endpoint table are constants compiled into flash, and they are the first thing to check in a recovered image: the vendor and product IDs in the dump should match what the host reports when the original board is plugged in.
Runtime state is not in flash. Endpoint buffers live in the USB dual-port RAM and are gone the moment power drops. A recovered image therefore cannot tell you what the device was doing when it failed, only what it was built to do. That distinction matters when a customer asks whether a read will explain why a unit stopped enumerating: it will not, but it will show whether the firmware ever had a USB suspend handler.
Configuration Is Part of the Firmware
The configuration block runs from 0x300000 to 0x30000D. Among other things it holds the oscillator selection, the PLL setting that produces 48 MHz from a 20 MHz crystal, and the enable for the on-chip USB voltage regulator. A file that contains the 32 KB array and omits 0x300000–0x30000D produces a part that programs, runs and never enumerates, because the transceiver has no supply and the PLL is not multiplying. That failure is regularly reported as a bad read.
The device ID at 0x3FFFFE is the other half of the check. It identifies the die, and it will tell you whether the file in your hand came from a 4553, a 4550 or a 4458 — three parts that share a socket and a flash size.
Reading It Properly
Ask for the array, CONFIG1L through CONFIG7H, the 256 bytes of EEPROM and the device ID in one file, with the protection state noted. Then verify without a reference: disassemble across 0x1FFF, 0x3FFF and 0x5FFF, where a seam shows up as a branch landing mid-instruction, and check whether any 8 KB-aligned region reads as uniform zeros. Uniform zeros at a block boundary mean code protection, not empty flash — an erased PIC18 word reads 0xFFFF, and the two are trivially distinguishable once you look for the pattern rather than at individual words.
The reading the program memory page describes the capture, and the services page lists what a delivered file includes for USB parts.