Nerdegutta's logo

nerdegutta.no

PIC16F690 - Day 3: Output Multiplexing Basics

31.07.25

Embedded

Goal: Learn basic multiplexing by lighting multiple LEDs one at a time in quick succession to give the illusion of being all on.
Hardware: 4 LEDs connected to RB4–RB7 (with resistors to GND)
Common multiplexing setup (like scanning digits or rows)
Concepts: Multiplexing = activating outputs one at a time very fast
Human eye can’t perceive the flicker if it's fast enough (~60+ Hz)

Two methods:
Manual scan using __delay_ms()
Abstraction using array/loop + __delay_us() for smoother cycling
Code 1: Simple manual LED scan with delay

#define _XTAL_FREQ 4000000
#include < xc.h >  // remove extra spaces

// CONFIG
#pragma config FOSC = INTRCIO
#pragma config WDTE = OFF
#pragma config PWRTE = OFF
#pragma config MCLRE = OFF
#pragma config BOREN = OFF
#pragma config CP = OFF
#pragma config CPD = OFF

void main(void) {
    // Set RB4–RB7 as outputs
    TRISB &= 0x0F;   // 0b00001111: upper 4 bits as output
    ANSEL = 0;
    ANSELH = 0;
    PORTB = 0;

    while(1) {
        // Light each LED one at a time
        PORTB = 0b00010000;   // RB4 on
        __delay_ms(100);
        PORTB = 0b00100000;   // RB5 on
        __delay_ms(100);
        PORTB = 0b01000000;   // RB6 on
        __delay_ms(100);
        PORTB = 0b10000000;   // RB7 on
        __delay_ms(100);
    }
}
Code 2: Multiplex using loop and array (more scalable)
#define _XTAL_FREQ 4000000
#include < xc.h >  / remove extra spaces

// CONFIG
#pragma config FOSC = INTRCIO
#pragma config WDTE = OFF
#pragma config PWRTE = OFF
#pragma config MCLRE = OFF
#pragma config BOREN = OFF
#pragma config CP = OFF
#pragma config CPD = OFF

const unsigned char led_mask[] = {
    0b00010000,  // RB4
    0b00100000,  // RB5
    0b01000000,  // RB6
    0b10000000   // RB7
};

void main(void) {
    TRISB &= 0x0F;   // RB4–RB7 outputs
    ANSEL = 0;
    ANSELH = 0;
    PORTB = 0;

    while(1) {
        for (char i = 0; i < 4; i++) {
            PORTB = led_mask[i];  // Activate one LED
            __delay_us(500);      // Fast refresh for persistence of vision
        }
    }
}