DIO

Introduction

This tutorial will present how to control digital input/output pins (generally called GPIO or General-Purpose Input/Output) using the 'dio' library.

The DIO library allows controlling the GPIO pins on the ioNode. This library can also be used with most AVR microcontrollers - check DIO pin matching when not using an ioNode.

What can you do with this?

GPIO pins can be used in two ways:

  • output - this allows 'controlling' the value of a GPIO from your code, setting it to logical 0 (0V) or 1 (3.3V).
  • input - this allows 'reading' the value that is being applied to a GPIO pin.

We will explore both uses in detail below.

How to use

First, we need to add the 'dio' library to our dependencies in dfe.conf:

name: example_app
type: app
mmcu: atmega1284p
freq: 10000000
deps:
  - dio

Direction (in / out)

Let's have a quick look at how to configure the direction (input or output) of these pins.

Pins are configured as inputs or outputs with the 'dio_input' and 'dio_output' functions:

#include <dio/dio.h>

void main()
{
    // Set pin 3 as input
    dio_input(3);

    // Set pin 5 as output
    dio_output(5);

    // ...
}

Internal pull-ups

When a pin is configured as input, we can choose to enable something called an 'internal pull-up resistor'.

A pull-up is a resistor that is placed between a digital signal and 'VCC' (the '+' of the power supply). Doing this will ensure that the signal "defaults" to a stable logical '1' when the signal is not asserted by anything (signal is in high-Z state).

This has many uses, for example when connecting a push button (tactile switch) to an input pin. The button, when pressed, will assert '0' on the input by connecting it to the ground (the '-' of the power supply). When the button is not pressed, nothing is "setting" the input - reading the pin's value will give random results. To solve this we can enable the internal pull-up resistor on this input pin to make sure it's always either '0' (when button is pressed) or '1' (when not pressed).

To enable the internal pull-up on a pin that has been configured as input, we actually write to it as if it were an output pin:

#include <dio/dio.h>

void main()
{
    // Set pin 3 as input
    dio_input(3);

    // Enable internal pull-up on pin 3
    dio_hi(3);

    // ...

    // Disable internal pull-up on pin 3
    dio_lo(3);

    // ...
}

Output

Once a pin is configured as output, we can set its value:

#include <dio/dio.h>

void main()
{
    // Set pin 5 as output
    dio_output(5);

    // Set pin 5 to '1'
    dio_hi(5);

    // ...

    // Set pin 5 to '0'
    dio_lo(5);

    // ...
}

Input

When a pin is configured as input, we can read its value as follows:

#include <dio/dio.h>

void main()
{
    // Set pin 3 as input
    dio_input(3);

    // Enable internal pull-up on pin 3
    dio_hi(3);

    // Read pin value
    if(dio_rd(3))    { /* pin is HIGH (1) */ }
    else             { /* pin is LOW (0) */ }

    // ...
}