LED's are there to be flashed and buttons are there to be pushed

Light Emitting Diodes, also known as LED's, are the source of those beautiful green and red light emissions (and others, RGB LED's anyone?) that Engineers will NEVER get sick of. Now is the time to flash these good things and join the Embedded Master Race (Yep, I went there).

A flashing LED! source

Are you still with us? It's always hard to refocus after being entranced by the flickering goodness (even if you've flashed an LED hundreds of times, it ages well) :)

Hardware Setup

So how can we control an LED with a processor? Well, let's approach this from a top down perspective and consider the LED to be an output that is driven by a microcontroller, or an FPGA. In an Embedded System this would look like:

Block Diagram of our Embedded System

Let's now take a ubiquitous real world example of a Microcontroller driving an LED with a schematic. A schematic is the electronic diagram which is then implemented on a physical PCB.

MCU driving an LED

Shown above is a schematic consisting of a Microcontroller, MCU, a 500Ω resistor and an LED connected to a 3.3V voltage rail. The blue connections between the components represent wires, which we assume have a resistance of 0Ω (in the real world of course these would be implemented as copper tracks on a PCB which have a small but non-zero resistance). The resistor connects to a pin on the microcontroller which it can drive to 0V or 3.3V.

As alluded to in the passage above, the MCU can set the pin to 0V or 3.3V (Logic Low and Logic High we can say) and this is how we can turn the LED on/off.

To make this concrete, let's redraw the schematic for the two use cases of 0V (logic low) and 3.3V(logic high) present at the pin:

Effective circuit for 0V at the pin:

Effective circuit for 0V at the pin
0V pin current and voltage drops

In the above we see current flowing from the 3.3V supply through the LED, resistor and into this triangle symbol... What is that all about? That is the circuit symbol for ground which for the moment let's just say that it's the current return path back to the voltage source so the current flows through it back to the 3.3V rail.

As current flows through the LED a voltage is dropped across it and this energy is converted to both heat and visible light we see.

If we assume a red LED then the voltage drop is typically around 1.8V meaning (3.3-1.8) 1.5V is dropped across the resistor. The current flowing is then given by Ohm's Law (1.5/500) 3mA which is enough current to light this particular LED. More current would increase the brightness up to its rated current which when exceeded will damage the LED. Let's now redraw this with the voltages and currents shown:

Schematic with annotated voltages and currents

Okay so we have turned the LED on with the above circuit configuration by passing a current through the LED and dropping a voltage across it but then how do we turn it off to make it blink? Thinking about it intuitively, we need a circuit configuration that prevents a current flowing and has no voltage drop across the LED. What would that look like?

The answer lies in first principle thinking, specifically that current flow requires a potential difference between two points in a circuit and so if we could have the negative terminal of the resistor connected to 3.3V we would have 0V across the LED and resistor and as there is no potential difference across the entire circuit we would have no current flow. Let's show this circuit configuration below:

Effective circuit for 3.3V at the pin

In the above circuit the LED would be off as there is no current flowing through the circuit. That's all well and good for the hardware perspective, but how can we control the voltage of the pin in software to make it turn on and off periodically to make it blink?

General Purpose Input Output

As mentioned in part 1 Microcontrollers have pins to communicate with the outside world which from the perspective of a microcontroller are the electronic components connected to the pins.

Furthermore, each pin serves a particular function such as power supply pins that provide power to the microcontroller as well as what we call General Purpose Input Output, or GPIO, pins which can function in input or output modes as the name suggests.

Holistically the task then becomes to firstly ensure that the LED is connected to a GPIO pin and then in software configure the pin to be an output (so we can force a state onto the pin, we will discuss inputs shortly as well) and then periodically drive the pin to 3.3V and 0V to turn the LED on and off respectively.

Let's now break this down and actually learn by doing it by considering a microcontroller connected to an LED as below:

What does PA5 mean in the above? It is how we describe pins in terms of ports. We read it as Port A Bit 5 where a port is simply a collection of pins that we can consider as a group in software and hardware. We could have for example PA0, PA1, PA2, PA3, PA4, PA5, PA6, PA7 as one port and then Port B would begin, i.e. PB0, PB1, etc.

In pseudocode the task then becomes in flowchart form:

Flowchart to flash an LED

Let's break this down.

We first set Port A bit 5 to be an output, this allows us to then set the pin to a logic high (3.3V for example) or logic low (0V) to turn the LED on and off and then we set Port A bit 5 high to turn the LED on, wait half a second, set it low to turn the LED off, wait half a second and repeat indefinitely and there you have it, we have a blinking LED!

How does this then look in code? Well the Port A bit 5 output setting is achieved via a function call (or API) provided by the microcontroller vendor as well as the Set Port A bit 5 high/low and the wait 500ms is typically achieved by a sleep() function call which simply turns the active thread off for the specified period.

Let's toggle an LED with a push button

So far we have discussed the output component of GPIO, it is now time to discuss the input component with a push button.

We now have ourselves a circuit composed of an LED and resistor connected to Port A bit 5 as we had before (our output) as well as a push button connected to Port B bit 1 (our input).

We can now write a program which configures PB1 as an input and then reads the voltage at the pin to determine if the button has been pressed. If we press the button down then a short circuit will be created which means the 3.3V will be read at the pin and if we don't press the button we have an open circuit and will read 0V at the pin (not strictly true if the circuit is not isolated from electromagnetic waves, but we will not consider this situation for now, assume it is isolated away from any other electromagnetic radiation).

We can then toggle the LED state on detection of a button press to turn the LED on and off, however, if you try this using the circuit above you will likely see the LED flicker multiple times. What is that? That is a phenomenon we will discuss in the next part.


  • Microcontroller's can interact with the outside world via GPIO's
  • We can blink an LED by setting a GPIO as an output and then periodically toggling the output
  • We can connect push buttons to the circuit as an input where we configure the GPIO as an input, read the logic level at the pin and then react accordingly.

Coming up next

In the next part of the course we will be taking a look at button debouncing.