PIC Hex File Format

Microchip have scored a winner over Atmel AVR by including all the information required to program a PIC microcontroller in one Hex file. This includes code, EEPROM data, User bytes (User ID) and most importantly, configuration words.

This makes it much easier to transfer the project from development to production or between engineers, as all the information needed is in one file.  Atmel, now they have been taken over by Microchip, have belatedly added an ELF production file format that can do the same thing. See this post for details – Producing AVR and ATxmega ELF production files So, what is this PIC file format?

Creating Configuration Bytes in your source file
You need to add configuration byte data to your source file in C or assembler. The syntax does vary for different tools and C or assembler. PIC16F examples in Microchip C or assembler use __Config directive, for example,

Another example, in assembler, is
__config _CP_OFF & _HS_OSC & _WDT_OFF & _PWRTE_ON & _LVP_OFF & _BODEN_ON

PIC18F usually use CONFIG directive, for example,
CONFIG WDT=OFF; disable watchdog timer
CONFIG DEBUG = ON; Enable Debug Mode

XC8 and XC16 compilers use pragma directive, for example
#pragma config FOSC = HS // Oscillator Selection
#pragma config WDTE = OFF // Watchdog Timer Enable (WDT disabled)
#pragma config PWRTE = OFF // Power-up Timer Enable (PWRT disabled)
#pragma config MCLRE = ON // MCLR Pin Function Select
#pragma config CP = OFF // Flash Program Memory Code Protection
#pragma config CPD = OFF // Data Memory protection

Check your compiler documentation for more details. Configuration bit names vary from PIC device to PIC device, see “Special Features of CPU section” in PIC device datasheets for details about configuration bytes.

MPLAB X Configuration Tool
The latest MPLAB X deals with Configuration Bytes differently in C files. With MPLAB X assembler files, __CONFIG and CONFIG directives still work but the C compiler requires a different format. It requires the use of #pragma config WDTE = ON syntax.

The easiest way to generate the required #pragma directives is with a built-in Configuration Bytes Tool.

Go to Window menu -> PIC Memory View -> Configuration bits.
A window opens with a list of the possible configuration bytes available on the device that is set in the project. The available Configuration bytes are different for PIC18F chips but the method is the same. Set them how you want and click “Generate Source Code to Output” button. This creates the code you need to cut and paste into your main source file, or put in a separate C file and use #include directive in your main file.

Example PIC18F Configuration Bytes in MPLAB X
#include <xc.h>

// #pragma config statements should precede project file includes.
// Use project enums instead of #define for ON and OFF.

#pragma config OSC = RCIO // Oscillator (External RC oscillator, port function on RA6)
#pragma config FCMEN = OFF // Fail-Safe Clock Monitor Enable bit (Fail-Safe Clock Monitor disabled)
#pragma config IESO = OFF // Internal/External Oscillator Switchover bit (Oscillator Switchover mode disabled)

Example PIC16F Configuration Bytes in MPLAB X
// #pragma config statements should precede project file includes.
// Use project enums instead of #define for ON and OFF.

#pragma config FOSC = HS // Oscillator Selection bits (HS oscillator: High-speed crystal/resonator on RA6/OSC2/CLKOUT and RA7/OSC1/CLKIN)
#pragma config WDTE = ON // Watchdog Timer Enable bit (WDT enabled)
#pragma config PWRTE = OFF // Power-up Timer Enable bit (PWRT disabled)
#pragma config MCLRE = ON // RE3/MCLR pin function select bit (RE3/MCLR pin function is MCLR)
#pragma config CP = OFF // Code Protection bit (Program memory code protection is disabled)
#pragma config CPD = OFF // Data Code Protection bit (Data memory code protection is disabled)
#pragma config BOREN = OFF // Brown Out Reset Selection bits (BOR disabled)
#pragma config IESO = ON // Internal External Switchover bit (Internal/External Switchover mode is enabled)
#pragma config FCMEN = ON // Fail-Safe Clock Monitor Enabled bit (Fail-Safe Clock Monitor is enabled)
#pragma config LVP = OFF

These directives will add the Configuration bytes to the output Hex file, which is described next.


A Microchip format Hex file is an extended Intel Hex file with code, data, configuration bytes and user ID included. You need to select output file type as INHX32. This is 32-bit addressing as Configuration bytes are stored above 64KB, which is the limit for 8-bit Intel Hex format, INHX8. All PIC programmers should be able to cope with this format, and PIC compilers should produce it.

Each line in the file has this format:


: is start of line marker
BB is number of data bytes on line
AAAA is address in bytes
TT is type. 00 means data, 01 means EOF, 02 means linear address and 04 means extended address
DD is data bytes, number depends on BB value
CC is checksum (2s-complement of number of bytes+address+type+data)

Extended and Linear Addressing
Standard Intel Hex files can only address 64KB of data (0..FFFFh), and extended addressing gets over this limitation by adding extended address lines for every 64KB, for example

:020000040000FA – 0 marker – not really necessary but often added
:020000040001F9 – 64KB marker
:020000040002F8 – 128KB marker

The Extended Address – 04 – marker means shift the value given after 04 16 places left.
The line :020000040001F9 means shift 1 16 places left, which gives 10000h, which in decimal is 65536 or 64KB. Shifting 2 16 places left gives 20000h or 128KB and so on.
The address of all data after the marker has the marker value added to it automatically.

The next complication is that some compilers use Linear Address instead of Extended Address. This works in a similar way but the marker is 02 not 04 and the value is only shifted left 4 places. The equivalent 64KB marker in linear addressing format is

:020000020000FC – 0 marker, often omitted
:020000021000EC – 64KB marker
:020000022000DC – 128KB marker

Shifting the value after the 02 marker, for example 1000, four places left also gives 10000 or 64KB. Note that the checksum will change. You may see either format used in PIC Hex files.

Some compilers include empty code lines (all FF) but others omit these lines to save space.

Code: This is at the top of the file and may be proceeded by an extended address line – :020000040000FA, where 04 is the type for extended address or by a linear address, 02. In both cases, the resulting address value is still 0x0000 so it actually has no effect.

EEPROM Data: It is proceeded by the extended address line – :0200000400F00A. The EEPROM section is optional

Newer microcontrollers like PIC18FxxK40 or PIC18FxxQ10 have EEPROM data at a different address – :020000040031C9 and PIC18FxxQ4x use :020000040038C2 but the principle is the same.

Configuration bytes: These are stored at 300000h and are preceded by the extended address line – :020000040030CA. The correct format is 8 Fuse bytes and 6 Lock bytes all on the same line but different compilers and assemblers have different methods of displaying these bytes. Sometimes lock bytes are omitted if they are not set, sometimes the data is spread over multiple lines.
The standard format displays unused bits as 1 (e.g. FF for an unused byte) but on older PIC device they read as 0.  A programmer should mask unused bits to 0 so that the Configuration Byte will verify correctly.

User ID: These are bytes for the user to store data, such as code version numbers. They are stored at 200000h. Again they are preceded by the extended address line :020000040020DA. The standard format requires 8 bytes but again some compilers omit unused bytes.

Device ID: This is sometimes included but most programmers ignore it. They are located at 3FFFFEh in device memory. The extended address marker is :02000004003FBB, which converts to address 3F000h. The next line has the  2 byte Device ID with address set to FFFEh, for example, :02FFFE003D00C4, where Device ID is 3D00h .

End of File: The End Of File marker for all Intel Hex files is :00000001FF




This shows 4 lines of code, 1 line of EEPROM data at :0200000400F00A, 8 user User bytes at :020000040020DA and 16 Configuration bytes at :020000040030CA, the last 2 are dummies as it only has 14 configuration bytes.



The PIC16F file has a similar format to the PIC18F file but does not use extended addressing as the PIC16F devices are smaller. This section is not correct for the latest PIC16F1xxx chips – see separate section below.

Code: Code is always at the top of the .hex file. The layout varies with different compilers and assemblers e.g. amount of data per line, whether blank lines are included etc. Note that the PIC16F devices use 14-bit instructions, so code is stored as Words with low byte first. Therefore, an unused location appears as FF3F. Addressing is in bytes though.

EEPROM Data: If the device has EEPROM, the data is stored at address 0x4200 upwards in the HEX file. It is stored in word format but only the lower byte contains data – the high byte is always 0 and is discarded.

Configuration Word: There is only one 14-bit configuration word on most PIC16F, stored at address 0x400E. It is stored high byte first. Some devices have up to 3 words.

User Data: Up to 8 bytes stored at 0x4000.

End of File: The End Of File marker for all Intel Hex files is :00000001FF




Earlier PIC16F microcontrollers had less than 16KB of code memory. The EEPROM data, User ID and configuration bytes were also stored below 64KB, so standard Intel Hex files were fine.

The newer PIC16F1xxx devices are bigger, with the latest having 64KB of program space. To accommodate this larger flash memory, the other data in the hex file was moved above 64KB and Extended or Linear addressing is required to access this – see PIC18F section for a full description of these addressing modes.

This is still stored from address 0x0000 but may have an extended or linear address line at the start eg :020000040000FA. This still means start the code at 0x0000. As the maximum code size is 64KB, the file doesn’t actually need extended addressing to accommodate the code.

EEPROM data is stored starting at address 0x1E000. This means it must have an extended address marker before it, :020000040001FA or :020000021000EC. This gives a base address of 0x10000 and the EEPROM data address, starting at E000 is added to this, giving 0x1E000 as EEPROM address in the file.
Note that the 8-bit EEPROM data is padded with 00, which is discarded when the PIC device is programmed.

User ID
There are 4 14-bit words of User ID, stored at address 0x10000 to 0x10003. They are usually stored on one line but can appear spread over different lines.

Configuration Bytes
The number of configuration bytes varies from 2 to 5 and they are actually 14-bit words. They start at address 0x1000E and may appear on one line or each may have its own line.


:020000040000FA Extended Address 0x0000
:020000000428D2 Code
:0C0030001728A10B1728A20B17280800A6 End of Code
:020000040001F9 Extended Address 0x10000
:10E0000061006200630064006500660067006800EC EEPROM
:10E01000FF00FF00FF00FF00FF00FF00FF00FF0008 EEPROM
:080000000100020003000400EE User ID 0x10000
:02000E00DA1FF7 Configuration starting at 0x1000E
:02001600FF3FAA Last configuration
:00000001FF End of File

Although EEPROM is stored at a higher address (0x1E000) it usually appears in the hex file before User ID, stored at 0x10000, and Configuration, stored at 0x1000E. Program code can also be stored out of normal address order by some tools.

PIC24FJ Devices
The configuration data is created in exactly the same way using #pragma and the same generation tool as PIC18F. The number of configuration bytes and names varies for different PIC24FJ devices.

The latest PIC24FJxxGB4xx and PIC24FJxxGB7 microcontrollers have a separate OTP (One Time Programmable) memory for user data storage. This is permanent and is one programming page in size, either 64 or 128 instructions (192 or 384 bytes). This section can be created in MPLAB using Window -> PIC Memory Views -> User OTP Memory menu.

The configuration bytes are stored in the last page of flash and loaded to configuration registers on reset, so the last page of flash may be separated by an extended address marker in the hex file.

On GA4/GB4 devices, the OTP memory is usually listed in the file before the last page of code, even though it is at a much higher address, beyond the actual size of the device.
This section has the extended address marker :020000040100F9 and is either 192 or 384 bytes in size.

The last page of flash will have an extended address but this will vary with the size of the device. For a PIC24FJ64 device it would be :020000021000EC – they are actually bigger than 64KB.

Related Information

Choosing the Right PIC Microcontroller

PIC ICSP Methods

PIC ICSP Circuit Schematic

MPLAB X Explored

9 thoughts on “PIC Hex File Format”

  1. The configuration bytes for PIC18F in the example are these


    From the hex file description, if we omit the hex file formatting we get 16 data bytes like this

    These are the configuration bytes from Config1L to Config7H (14 bytes). The last 2 bytes are dummies. The bottom 8 are configuration, and next 6 are lock bytes. If you look in a PIC datasheet under “Special Features of the CPU” section, you will see all the configuration bits laid out and described.

  2. Admiring the time and effort you put into your blog and in depth information you provide. It’s awesome to come across a blog every once in a while that isn’t the same unwanted rehashed material. Great read! I’ve saved your site and I’m including your RSS feeds to my Google account.

  3. Hello there, I believe your site could possibly be having web
    browser compatibility problems. Whenever I take a look at your website in Safari, it looks fine but when opening in
    Internet Explorer, it has some overlapping issues.

    I just wanted to provide you with a quick heads
    up! Besides that, excellent site!

    1. As long as you add the configuration bits to your MPLAB project, they will be in the hex file. All PIC programmers (I think all, certainly all the ones we sell) will program the configuration bits from the hex file and will moan if they aren’t there.

      To add congiguration bytes to your MPLAB project, use __CONFIG or CONFIG directives in MPLAB 8, or #pragma config in MPLAB X – there is a tool to do this in MPLAB X under Windows menu -> PIC Memory Views -> Configuration Bits.

      Please see another blog post on MPLAB X for more information MPLAB 8 versus MPLAB X

  4. What’s Going down i am new to this, I stumbled upon this I have found It absolutely helpful and it has aided me out loads.
    I am hoping to contribute & assist different users like its helped me.
    Great job.

Leave a Reply