Multiplex a 7-Segment Display with PIC16F877A in PICSimLab

Four-digit 7-segment displays are wired with shared segment lines, so the firmware lights one digit at a time and cycles fast enough for the eye to see a steady number. PICSimLab’s 7 Segments Display spare part exists in exactly this form — four multiplexed displays (or a single one) — which makes it ideal for learning multiplexing on a PIC16F877A.

What you need

  • PICSimLab 0.9.3 — see the download page.
  • MPLAB X IDE and the XC8 compiler.
  • Board: McLab2 or PICGenios, microcontroller PIC16F877A.
  • One 7 Segments Display spare part (Outputs category). A second variant, 7 Segments Display (w/dec), includes a decoder — this tutorial uses the plain multiplexed part so you learn the segment table yourself.

Wiring used in this tutorial (example)

  • Segments a–g and decimal point → RD0–RD7 (segment patterns on PORTD)
  • Digit enables for digits 1–4 → RB0–RB3

Connect the part in its Properties window to match. If your part configuration enables a digit with the opposite polarity, invert the digit-select values in the code and rebuild — the segment table stays the same.

Steps

1. Generate the project and add the display

Create the MPLAB X project for the PIC16F877A with the Code Project Wizard, then open Modules → Spare parts and add Outputs → 7 Segments Display. Open its Properties and wire the segments and digit enables as above.

2. Learn the segment table

For a common-cathode digit, a 1 lights a segment. The patterns for 0–9 on PORTD (bit 0 = a, bit 1 = b, … bit 6 = g) are: 0=0x3F, 1=0x06, 2=0x5B, 3=0x4F, 4=0x66, 5=0x6D, 6=0x7D, 7=0x07, 8=0x7F, 9=0x6F. The example stores them in a lookup table.

3. Multiplex in the main loop

The display routine shows one digit for about 2 ms, then moves to the next. After roughly 125 full refresh cycles (about one second), the counter increments. Keeping the refresh in the main loop is the simplest correct structure; the timers tutorial shows how to move it into an interrupt later.

4. Build, load and run

Build in MPLAB X, load the .hex and run. You should see a counter running from 0000 to 9999, all four digits lit at what looks like the same time.

Example code (XC8)

// Example: 4-digit multiplexed 7-segment counter - PIC16F877A, XC8
// Segments on PORTD, digit enables on RB0-RB3 (example: 1 = enabled)
#pragma config FOSC = HS
#pragma config WDTE = OFF
#pragma config PWRTE = ON
#pragma config BOREN = ON
#pragma config LVP = OFF
#pragma config CPD = OFF
#pragma config WRT = OFF
#pragma config CP = OFF

#include <xc.h>
#define _XTAL_FREQ 20000000     // Example: match the board clock

// Common-cathode segment patterns for digits 0-9 (a=bit0 ... g=bit6)
static const unsigned char seg_table[10] =
    {0x3F, 0x06, 0x5B, 0x4F, 0x66, 0x6D, 0x7D, 0x07, 0x7F, 0x6F};

void show_digit(unsigned char pos, unsigned char value) {
    PORTB = 0x00;                                  // all digits off
    PORTD = seg_table[value];                      // set segments
    PORTB = (unsigned char)(1u << pos);           // enable one digit
    __delay_ms(2);                                 // digit on-time
}

void main(void) {
    TRISB = 0x00;               // digit enables
    TRISD = 0x00;               // segments
    PORTB = 0x00;
    PORTD = 0x00;
    unsigned int count = 0;
    while (1) {
        for (unsigned int tick = 0; tick < 125; tick++) {
            show_digit(0, (unsigned char)(count / 1000));
            show_digit(1, (unsigned char)((count / 100) % 10));
            show_digit(2, (unsigned char)((count / 10) % 10));
            show_digit(3, (unsigned char)(count % 10));
        }
        if (++count > 9999) count = 0;
    }
}

Try next

Troubleshooting

Only one digit ever lights. The digit-enable pins in the part’s Properties do not match RB0–RB3, or the enables have the opposite polarity. Flip the enable logic (write 0 to enable) and rebuild as a quick test.

Digits are readable but flicker heavily. The per-digit delay is too long, or something in the main loop blocks the refresh. Keep the full four-digit cycle under about 10 ms total.

Similar Posts