Skip to content

alaamjadi/ARM7-LPC214X

Repository files navigation

ARM7 LPC2148 — Beginner GPIO Labs

A complete, self-contained learning guide + code + wiring

This repository is a beginner-level learning lab course for the NXP LPC2148 (ARM7TDMI-S). Each lab builds one concept at a time: bitwise operations → GPIO registers → switches → LEDs → seven‑segment.

Designed for a bare‑minimum build (no dev board required).
You can wire the circuit on a breadboard or simulate in Proteus or NI Multisim.

What you need

Hardware (for physical device)

  • LPC2148 microcontroller (LQFP64 package)
  • 3.3V regulated supply (do not power GPIO with 5V)
  • 12 MHz crystal + 2 × 22 pF capacitors
  • Reset circuit: 10k pull‑up + pushbutton to GND
  • Decoupling capacitors: at least 100 nF near each VDD pin (+ one 10 µF bulk cap)
  • LEDs + resistors (330Ω–1kΩ)
  • Push buttons + resistors (10k pull‑ups recommended)
  • Seven‑segment display (common cathode) + resistors (330Ω–1kΩ)

Software (for simulation + build)

  • IAR Embedded Workbench (which I used) a comprehensive, integrated development environment (IDE) and toolchain for embedded systems. Another option would be Keil uVision an ARM toolchain that can build LPC214x projects.
  • NI Multisim (which I used) or Proteus optional but recommended for beginners.
  • Text editor (VSCode or an IDE)

Microcontroller crash course

A microcontroller is basically:

  • A CPU core (ARM7TDMI‑S),
  • Flash + RAM,
  • Peripherals (GPIO, UART, Timers, ADC, etc.),
  • Lots of memory‑mapped registers.

Registers

A register is a special hardware-controlled memory location.
Writing/reading a register changes hardware behavior.

Examples:

  • GPIO direction register controls input vs output.
  • GPIO set/clear registers drive pins HIGH/LOW.
  • PINSEL registers choose alternate pin functions (UART, PWM, etc.)

A typical workflow for any peripheral is:

  1. Enable / select the function (often via a clock gate or a PINSEL register)
  2. Configure (direction, mode, speed, pull-up/pull-down, etc.)
  3. Use (read status, write output, handle events)

This course focuses on GPIO, so the “enable” step is mostly:

  • “make sure the pin is configured as GPIO” (PINSEL bits set to 0 for that pin).

Operator cheatsheet

Embedded programming is full of bit manipulation, because registers are bitfields.

  • | (OR) → set bit(s)
  • & (AND) → clear or test bit(s)
  • ^ (XOR) → toggle bit(s)
  • ~ (NOT) → invert bits
  • << / >> shifts
Set a bit
reg |= (1U << n);
Clear a bit
reg &= ~(1U << n);
Test a bit
if (reg & (1U << n)) { /* bit is 1 */ }
Write a multi-bit field (mask + shift)
reg = (reg & ~FIELD_MASK) | ((value << FIELD_SHIFT) & FIELD_MASK);

You will use these patterns constantly in GPIO, timers, UART, ADC, etc.

LPC2148 GPIO Registers

Ports and Usable Pins

LPC2148 has Port 0 and Port 1 GPIO registers.

  • Port 0 has many usable pins, but some are reserved (e.g., P0.24/P0.26/P0.27).
  • Port 1 is a 32-bit port, but P1.0–P1.15 are not available on LPC2148 packages. Only P1.16–P1.31 are usable GPIO pins.

This repo uses valid pins only.

PINSEL registers (choose GPIO vs alternate function)

Pins can be GPIO or another function. The PINSEL registers select the function:

  • PINSEL0 → P0.0..P0.15
  • PINSEL1 → P0.16..P0.31
  • PINSEL2 → P1.16..P1.31

For a pin to act as GPIO, its PINSEL function bits must be 00.

The 4 GPIO registers

1) IOxDIR — direction
  • 0 = input
  • 1 = output

Examples:

IO0DIR |=  (1U << 4);  // P0.4 output
IO0DIR &= ~(1U << 0);  // P0.0 input
2) IOxPIN — read pin state (and optionally write whole port)
  • Read current logic level of pins.
  • Be careful when writing (you can overwrite other pins).
3) IOxSET — set output pin(s) HIGH
  • Writing 1 to a bit sets that pin HIGH.
  • Writing 0 has no effect.

Correct usage:

IO0SET = (1U << 4);
4) IOxCLR — clear output pin(s) LOW
  • Writing 1 clears that pin LOW.
  • Writing 0 has no effect.

Correct usage:

IO0CLR = (1U << 4);
Why IOxSET = mask is safe?

IOxSET/IOxCLR are “command” registers:

  • bits written as 1 take effect,
  • bits written as 0 do nothing.

So IO0SET = (1<<4) does not disturb other pins.

For direction/config registers like IOxDIR, you should use |= and &=~ to preserve other bits.

Pull-ups (important for switches)

Port 0 pins typically do not have built-in pull-up/pull-down resistors, so in real circuits you must add external pull-up resistors for active-low buttons.


Labs

Roadmap

You’ll learn these in order:

  1. Basic input & output
  2. Independent control (multiple signals)
  3. Seven-segment basics + mapping
  4. Macros (safer register manipulation)
  5. Small “libraries” (modular code)

How to run

  1. Wire the circuit.
  2. Create a new project in your IDE for LPC214x.
  3. Add the source files in this folder.
  4. Build & flash.
  5. Interact with the switches and observe the output.

What to learn

  • How to configure GPIO direction (input vs output)
  • How to read a pin (IOxPIN)
  • How to drive a pin (IOxSET / IOxCLR)
  • How to structure embedded code clearly (comments + naming)

Exercises

  • Add a small software debounce (delay + stable reads).
  • Change the pin mapping to match your specific board.
  • Extend the logic:
    • E01/E04: add a third LED behaviour state
    • E03/E08: display a scrolling count when no switch is pressed

If your dev board uses different pins, change the *_PIN macros (or the definitions in Config.h / headers).

E01 — Basic Switch & LED (GPIO Fundamentals)

One push-button controls two LEDs.

Connections used in code:

  • LED1: P1.20
  • LED2: P1.24
  • SW1: P1.29 (active-low, pull-up to 3.3V)

E02 — Dual Switch & LED (Independent Control)

Two push-buttons independently control two LEDs.

Connections used in code:

  • LED1: P0.4
  • LED2: P0.7
  • SW1: P0.0 (active-low, pull-up)
  • SW2: P0.2 (active-low, pull-up)

E03 — Seven-Segment Display (Basic, Single-File)

Select digits 0–9 using ten switches and show them on a 7-seg display.

Connections used in code:

  • 7-seg segments a..g: P1.17..P1.23 (via resistors)
  • Common cathode: GND
  • SW0..SW9: P0.0..P0.9 (active-low, 10k pull-ups to 3.3V)

E04 — Same as E01, but with Macros

Uses safe macros (do { ... } while(0)) to wrap GPIO operations.

Connections used in code:

  • LED1: P1.20
  • LED2: P1.24
  • SW1: P1.29 (active-low, pull-up)

E05 — Same as E02, but with Macros

Two switches control two LEDs using macro wrappers for init and IO.

Connections used in code:

  • LED1: P0.4
  • LED2: P0.7
  • SW1: P0.0 (active-low, pull-up)
  • SW2: P0.2 (active-low, pull-up)

E06 — First ‘Library’: LED + Switch Helper Module

Introduces a small reusable module LedSw.c/.h and Config.h.

Connections used in code:

  • LED bank: P0.16..P0.23 (via resistors)
  • SW1: P0.10 (active-low, pull-up)

E07 — Library Version with Two Switches

Builds on E06: now two switches control two LEDs using the helper module.

Connections used in code:

  • LED bank: P0.16..P0.23 (via resistors)
  • SW1: P0.10 (active-low, pull-up)
  • SW2: P0.11 (active-low, pull-up)

E08 — Seven-Segment with Libraries

Cleaner main() by separating 7-seg logic (7Seg.*) and switch logic (switch.*).

Connections used in code:

  • 7-seg segments a..g: P1.17..P1.23 (via resistors)
  • Common cathode: GND
  • SW0..SW9: P0.0..P0.9 (active-low, pull-ups)

Troubleshooting

My button reads random values
  • Add a 10k pull-up to 3.3V and connect button to GND (active-low).
  • Add debounce (delay + re-sample) if needed.
My LED is inverted
  • You might have wired LED as active-low (GPIO sinks current).
  • Either rewire (GPIO -> R -> LED -> GND), or invert logic in code.
Seven-seg looks wrong
  • Confirm whether your display is common cathode or common anode.
  • Common anode requires inverted segment logic.
Proteus does nothing
  • Ensure your HEX file is attached to the MCU model.
  • Make sure clock/reset circuit exists.
  • Check that you used the correct pin names.

Next steps: more projects

Once you finish these GPIO labs, the next “small projects” to build are:

Core peripherals (recommended order)

  • PLL / clock setup
  • Timer/Counter (delays, time measurement)
  • UART (serial console)
  • ADC (read analog sensor)
  • VIC (interrupts)

Interfacing projects

  • LCD (4-bit and 8-bit)
  • Keypad interfacing
  • Relay and DC motor control (with driver IC)
  • GSM, GPS, Bluetooth modules
  • Ultrasonic, PIR, IR sensors
  • LDR / sound / gas / flame sensors

Suggestions

Programming / debugging hardware

J-Link, LPC-Link, or any ARM-compatible SWD/JTAG debugger (depending on your setup).

Dev boards

If you prefer not to build the minimal hardware, use an LPC2148 development board (Olimex-style boards are common). This repo still applies — only the wiring changes.

References

ARM LPC2148 (ARM7TDMI-S) Datasheet

NXP LPC2148 Datasheet

NXP LPC2148 Usermanual

License

See LICENSE.

About

A collection of basic programs for an introductory course on ARM7 programming to utilizde NXP LPC214X family processesors using IAR Embedded Workbench, NI multisim circuit design suite and, Proteus Pro.

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages