Implementing SPI Communication on LPC2138 with 74HC595 LED Driver

LPC2138 integrates a hardware SPI peripheral supporting synchronous, full-duplex serial communication. During each transfer cycle, the master transmits one byte while simultaneously receiving one byte from the slave — even when the slave response is irrelevant, as in driving a 74HC595 shift register.

The following implementation configures the LPC2138 as an SPI master to drive a 74HC595-based LED display. Pin P0.8 serves as the chip-select (CS) signal for the shift register. The SPI clock polarity (CPOL) is set high, sampling occurs on the first edge (CPHA = 0), and data is transmitted most-significant-bit first (LSBF = 0).

#include "config.h"

#define SHIFT_REG_CS    (1U << 8)  // P0.8 as active-low chip select

static volatile uint8_t received_byte;

void busy_wait_ms(uint32_t ms) {
    for (uint32_t i = 0; i < ms; ++i) {
        for (volatile uint32_t j = 0; j < 6000; ++j);
    }
}

void spi_master_init(void) {
    S0PCCR = 0x52;  // SPI clock divisor: PCLK / 52 ≈ 1.15 MHz (assuming 60 MHz PCLK)
    S0PCR  = 0x30;  // MSTR=1, CPOL=1, CPHA=0, LSBF=0, SPEN=1
}

uint8_t spi_transfer(uint8_t tx_byte) {
    IO0CLR = SHIFT_REG_CS;     // Assert chip select
    S0PDR  = tx_byte;          // Load byte into SPI data register
    while (!(S0PSR & 0x80));   // Wait until SPIF flag is set (transfer complete)
    IO0SET = SHIFT_REG_CS;     // Deassert chip select
    return S0PDR;              // Return received byte (often ignored for 74HC595)
}

// Segment patterns for digits '2','0','2','1','0','0','0','1'
static const uint8_t digit_patterns[] = {
    0xA4,  // '2'
    0xC0,  // '0'
    0xA4,  // '2'
    0xF9,  // '1'
    0xC0,  // '0'
    0xC0,  // '0'
    0xC0,  // '0'
    0xF9   // '1'
};

int main(void) {
    // Configure P0.0–P0.3 for SPI (MOSI, MISO, SCK), P0.8 for CS
    PINSEL0 = 0x00005500;
    PINSEL1 = 0x00000000;

    IO0DIR |= SHIFT_REG_CS;  // Set P0.8 as output

    spi_master_init();

    while (1) {
        for (uint8_t idx = 0; idx < sizeof(digit_patterns); ++idx) {
            received_byte = spi_transfer(digit_patterns[idx]);
            busy_wait_ms(150);
        }
    }
}

This code initializes the SPI interface with appropriate clock and mode settings, then cycles through a custom sequence of segment codes corresponding to a student ID (e.g., 20210001). Each digit is sent over SPI to the 74HC595, which latches and displays it on a common-anode seven-segment LED. The chip-select line is toggled per byte to ensure proper timing and latch behavior.

Tags: embedded SPI lpc2138 74HC595 Keil

Posted on Wed, 26 Aug 2026 16:24:13 +0000 by brokenme