Micro:bit - Basic PWM
Written by Harry Fairhead   
Tuesday, 05 April 2022
Article Index
Micro:bit - Basic PWM
PWM Functions
How Fast?

PWM is a very basic way of controlling the outside world. This is an extract from the newly published second edition of my book on programming the micro:bit in C, now covering both the original version and V2.

Micro:bit IoT In C Second Edition

By Harry Fairhead


Buy from Amazon.


  1. The Micro:bit Family
  2. Getting Started With C/C++ ***NEW!
  3. First Steps With The GPIO
  4. Fast Memory-Mapped GPIO
  5. Pulse Width Modulation, Servos and More
    Extract: Micro:bit - Basic PWM
  6. I2C Bus
  7. I2C Measuring Temperature And Humidity
  8. Creating A Custom Protocol
  9. DS18B20 1-Wire Temperature Sensor
  10. SPI Bus
  11. A‑to‑D With The SPI Bus
  12. Serial Connections
  13. Getting On WiFi
  14. The LED Display
  15. Radio Sounds
    Extract: Morse Transmitter
  16. Appendix I The Mbed Online Compiler
  17. Appendix II Yotta And Offline Development



One way around the problem of getting a fast response from a microcontroller is to move the problem away from the processor. In the case of the micro:bit's processor there are some built-in devices that can use GPIO lines to implement protocols without the CPU being involved. In this chapter we take a close look at Pulse Width Modulation (PWM) including sound generation, driving LEDs and servos.

At their most basic output function, the GPIO lines can be set high or low by the processor. How fast they can be set high or low depends on the speed of the processor. Using the GPIO line in its PWM mode you can generate pulse trains up to 9.6MHz, i.e. pulses as short as or just a little more than 0.1µs.

The reason for the increase in speed is that the GPIO controls a pulse generator and, once set to generate pulses of a specific type, the pulse generator just gets on with it without needing any intervention from the GPIO line or the processor. In fact, the pulse output can continue after your program has ended if you forget to reset it.

Of course, even though the PWM line can generate pulses as short as 0.1µs, it can only change the pulses it produces in the time the processor can modify it. For example, you can't use PWM to produce a single 0.1µs pulse because you can't disable the PWM generator in just 0.1µs.

Some Basic Micro:bit PWM Facts

There are some facts worth getting clear right from the start, although some of their meanings will only become clear as we progress. First what is PWM?
The simple answer is that a Pulse Width Modulated signal has pulses that repeat at a fixed rate, say one pulse every millisecond, but the width of the pulse can be changed.

There are two basic things to specify about the pulse train that is generated, its repetition rate and the width of each pulse. Usually the repetition rate is set as a simple repeat period and the width of each pulse is specified as a percentage of the repeat period the duty cycle. For example, a 1ms repeat and a 50% duty cycle specifies a 1ms period which is high for 50% of the time, i.e. a pulse width of 0.5µs.

The two extremes are 100% duty cycle, i.e. the line is always high; and 0% duty cycle, i.e. the line is always low. What this means is that generally you select a repeat rate and stick to it and what you change as the program runs is the duty cycle.

In many cases PWM is implemented using special PWM generation hardware that is built either into the processor chip or provided by an external chip. The processor simply sets the repeat rate by writing to a register and then changes the duty cycle by writing to another register. This generally provides the best sort of PWM with no load on the processor and generally glitch-free operation. You can even buy add-on boards that will provide additional channels of PWM without adding to the load on the processor.

The alternative to dedicated PWM hardware is to implement it in software. You can quite easily work out how to do this. All you need a timing loop to set the line high at the repetition rate and then set it low again according to the duty cycle. You can implement this using either interrupts or a polling loop.

In the case of the micro:bit, the PWM lines are not implemented using special PWM hardware. Instead two general purpose facilities - the GPIOTE and the PPI – are used to allow the GPIO lines to trigger events and respond to tasks. The software sets things up so that the system timer automatically toggles the specified GPIO line at the selected repetition rate and duty cycle. This saves the processor’s time, but it is sophisticated and, at times, a little difficult to use.

You can use the three "main" GPIO lines, P0, P1 and P2, for PWM. You can also use other GPIO lines, but these generally have other uses as well as PWM. For the moment we will concentrate on using P0, P1 and P2.

As a single timer is used, the repetition rate is shared between all of the GPIO lines being used as PWM outputs. That is, all PWM lines operate at the same frequency - i.e. the last frequency set.

You can, however, set different duty cycles for each of the PWM lines you are using by setting the repetition rate in multiples of 4µs, i.e. the timer tick is 4µs. The fastest pulse repetition rate you can specify is 1µs, but this actually gives a 27-microsecond repeat rate. The slowest is 0.262 seconds which means you can't use a PWM line to flash an LED once every second.

As you can guess, there are no PWM inputs, just six outputs. If for some reason you need to decode or respond to a PWM input then you need to program it using the GPIO input lines and the pulse measuring techniques introduced in the previous chapters. If you are really ambitious you could use the GPIOTE and PPI facilities to automatically analyze the incoming PWM signal. Again, you would use the timer to record the repetition rate and duty cycle.

Last Updated ( Tuesday, 05 April 2022 )