LPC2103 tutorials: GPIO & leds

[Mail:Me:]

WORK IN PROGRESS, CHECK LATER FOR MORE

0. Introduction

LPC2103 chip support 32 GPIO ports. Every GPIO port can be configured as on output or as an input. This tutorial will explain how to use GPIO ports as outputs.

LPC2103 educational board has an RGB-led, connected to P0.19, P0.20 and P0.21 pins (the same applies to LPC2103-based “Christmas Tree” board). The low level on the corresponding pin turns the light on, and the high level turns it off. We will use this led to illustrate GPIO manipulation. (“Christmas Tree” board works other way round, high level turns the led on and low switches it off.)

There are two ways to access GPIO ports: one set of registers provides enhanced features and one is preserved for backward compatibility with older devices. We will try both.

1. Pin connect block

Every pin of LPC2103 has more than one function. So called pin connect block allows to configure pins to the desired functions. For this purpose there are two registers: PINSEL0 at address 0xE002C000 and PINSEL1 at address 0xE002C004.

The bits 1 and 0 of PINSEL0 choose the function for P0.0 pin, the bits 3 and 2 — for P0.1 pin, ..., the bits 31 and 30 — for P0.15 pin. Pins P0.16–P0.31 are controlled in the same manner by PINSEL1 register. The value of 00 for any pin always configures the pin as corresponding GPIO port. After the reset, the value in PINSEL0 and PINSEL1 is 0; so P0.0 pin is GPIO port 0.0, P0.1 pin — GPIO port 0.1, etc. It means that we should not do anything to configure P0.19, P0.20 and P0.21 as GPIO ports.

2. RGB-led the old way

Configuring GPIO ports as outputs

If we want to control RGB-led, we need to be able to switch P0.19, P0.20 and P0.21 to low or high level. It means that GPIO ports 0.19, 0.20 and 0.21 should be configured as outputs.

The legacy way of configuring GPIO ports as inputs or outputs is the IO0DIR register at address 0xE0028008. If bit n is set in IO0DIR then GPIO port 0.n is configured as output; otherwise the port is configured as input. The reset value of IO0DIR is 0, so every GPIO port is configured as input. We need to control RGB-led, not to read its status, so GPIO ports 0.19, 0.20 and 0.21 should be configured as outputs. To achieve this purpose we may use the following C code (there is no mistake, green light is connected to pin 21 and blue to pin 20):

#define IO0DIR (*((volatile unsigned long *) 0xE0028008))
/* Legacy register to switch GPIO ports between input and output */
#define LED_R (1<<19)
#define LED_G (1<<21)
#define LED_B (1<<20)

void rgb_init() {

        IO0DIR |= LED_R|LED_G|LED_B;

}

Using GPIO ports as outputs

The legacy way to set GPIO port configured as output to low or high level is the usage of IO0SET register at address 0xE0028004 and IO0CLR register at address 0xE002800C. Writing 1 to the bit n of IO0SET register puts GPIO port 0.n to high level; writing 1 to the bit n of IO0CLR register puts GPIO port 0.n to low level; writing 0 to any bit of either register has no effect.

With this knowledge, we can write the code to control RGB-led:

#define IO0SET (*((volatile unsigned long *) 0xE0028004))
/* Legacy register to put high level on GPIO port */
#define IO0CLR (*((volatile unsigned long *) 0xE002800C))
/* Legacy register to put low level on GPIO port */

#define LED_R (1<<19)
#define LED_G (1<<21)
#define LED_B (1<<20)

void rgb_on(unsigned long color) {
/* color must be one of LED_R, LED_G or LED_B */
        IO0CLR |= color;
}

void rgb_off(unsigned long color) {
/* color must be one of LED_R, LED_G or LED_B */
        IO0SET |= color;
}

Illumination

Now we can combine everything into one program (download leds-1.c; also Makefile, ramstartup.S, lpc2103_ram.ld):

#define U0THR (*((volatile unsigned char *) 0xE000C000)) /* UART0 transmitter holding register */
#define U0LSR (*((volatile unsigned char *) 0xE000C014)) /* UART0 line status register */
#define U0THRE ((U0LSR & (1<<5))) /* UART0 transmitter holding register is empty */

#define IO0DIR (*((volatile unsigned long *) 0xE0028008))
/* Legacy register to switch GPIO ports between input and output */

#define IO0SET (*((volatile unsigned long *) 0xE0028004))
/* Legacy register to put high level on GPIO port */
#define IO0CLR (*((volatile unsigned long *) 0xE002800C))
/* Legacy register to put low level on GPIO port */

#define LED_R (1<<19)
#define LED_G (1<<21)
#define LED_B (1<<20)

void rgb_on(unsigned long color) {
	IO0CLR |= color;
}

void rgb_off(unsigned long color) {
	IO0SET |= color;
}

void rgb_init() {
	IO0DIR |= LED_R|LED_G|LED_B;
}

void putch(char c) {
	while (!U0THRE);
	U0THR = c;
}

void putstr(char *s) {
	while (*s) putch(*s++);
}

void pause() {
	int i = 0;
	volatile int k = 0;
	while (i++ < 1500000) k=1;
}

int main(int  argc, char *argv[]) {

	putstr("Initializing RGB led...\n");
	rgb_init();
	rgb_off(LED_R|LED_G|LED_B);
	
	putstr("Starting the loop...\n");
	while (1) {
		rgb_on(LED_R);
		pause();
		rgb_on(LED_G);
		pause();
		rgb_off(LED_R);
		pause();
		rgb_on(LED_B);
		pause();
		rgb_off(LED_G);
		pause();
		rgb_on(LED_R);
		pause();
		rgb_on(LED_B|LED_G);
		pause();
		rgb_off(LED_R|LED_G|LED_B);
		pause();
	}

	return 0;
}

This program will put RGB-led through the following colorful cycle: red, yellow, green, light blue, blue, purple, white, off. The function pause is an empty loop for the delay; int k being volatile prevents GNU C from optimizing the function away.

If you use “Christmas Tree” board, remember that led is switched on by high level, not by low; so you need to modify rgb_on() and rgb_off() functions, putting IO0SET into the former and IO0CLR into the latter.

Compile the program, load it to the board and enjoy the show!

Search this site

...
...
...

Creative Commons License
This work by Alexey Vyskubov is licensed under a Creative Commons Attribution-Noncommercial-No Derivative Works 3.0 Unported License.