ESP32 (9) – Basic I/O

by luca
5 comments

Iniziamo, con il tutorial di oggi, ad utilizzare i pin di I/O del chip esp32. Il chip mette a disposizione 40 General Purpose I/O pads (GPIO), ovvero 40 “contatti” che possono essere utilizzati per diverse funzionalità di ingresso (input) e uscita (output).

La gestione di tali pads è abbastanza complessa: il chip esp32 consente infatti di “mappare” le diverse periferiche interne (UART, SPI…) sui vari pad tramite matrici configurabili via software. All’interno del technical reference manual è presente un diagramma che illustra questo meccanismo:

esp32-io01

In questo primo articolo non andrò ad illustrarvi tutti i diversi registri e configurazioni… è importante però tenere presente sin da subito che per utilizzare un pin, anche solo con funzioni di I/O base, è necessaria una configurazione iniziale. Il driver del framework da includere nel proprio codice per avere a disposizione tutte le funzioni descritte di seguito è:

#include "driver/gpio.h"

Funzionalità I/O base

Come detto, prima di poter utilizzare un pin è necessario impostare i vari registri che ne configurano i collegamenti interni. Dopo il reset del chip, molti pin sono automaticamente configurati per funzionalità di I/O base. Possiamo assicurarci che il pin scelto sia configurato per funzionalità di I/O con la funzione:

void gpio_pad_select_gpio(uint8_t gpio_num);

Nel funzionamento come pin di I/O, i pin del chip esp32 possono essere configurati in 3 direzioni:

  • input
  • output
  • open drain
Open Drain
Un pin configurato come open drain può soltanto accettare corrente in ingresso (se configurato a livello logico 0) ma non fornire corrente in uscita; se infatti è configurato a livello logico 1, il pin risulta di fatto disconnesso.

Le relative costanti sono definite nel file gpio.h:

esp32-io02

Vi sono alcune eccezioni, in particolare i pins > 33 possono essere utilizzati solo come input.

E’ possibile configurare la direzione di un pin con la funzione:

esp_err_t gpio_set_direction(gpio_num_t gpio_num, gpio_mode_t mode);

gpio_num indica il pin da configurare, mentre mode è una delle tre modalità descritte sopra. Per configurare ad esempio il pin 13 come output, il comando da utilizzare sarà:

gpio_set_direction(GPIO_NUM_13, GPIO_MODE_DEF_OUTPUT);

Possiamo leggere lo stato del pin, se configurato come input, con la funzione:

int gpio_get_level(gpio_num_t gpio_num);

mentre se il pin è configurato come output o open drain, possiamo cambiarne lo stato con:

esp_err_t gpio_set_level(gpio_num_t gpio_num, uint32_t level);

Pull-up e pull-down

Ogni pin è anche dotato di resistenze di pull-up pull-down, attivabili tramite la funzione:

esp_err_t gpio_set_pull_mode(gpio_num_t gpio_num, gpio_pull_mode_t pull);

le costanti possibili sono:

esp32-io03

In alternativa esistono funzioni per abilitare/disabilitare le resistenze su ogni pin:

esp_err_t gpio_pullup_en(gpio_num_t gpio_num);
esp_err_t gpio_pullup_dis(gpio_num_t gpio_num);
esp_err_t gpio_pulldown_en(gpio_num_t gpio_num);
esp_err_t gpio_pulldown_dis(gpio_num_t gpio_num);

Configurazioni multiple

Finora abbiamo visto come configurare singolarmente i vari pin. Esiste la possibilità di configurare simultaneamente più pin, applicando a tutti la medesima configurazione.

Per prima cosa va definita una struct di tipo gpio_config_t:

gpio_config_t pin_config;

I parametri configurabili sono:

esp32-io04

I pin oggetto della configurazione multipla vengono inseriti nella variabile pin_bit_mask concatenando le costanti GPIO_SEL_x con l’operatore OR (|). Vediamo un paio di esempi (degli interrupt parlerò più diffusamente in un prossimo post, per ora saranno disabilitati):
[checklist]

  • pin 2, 3 e 7 configurati come output, pull-up e down disabilitati:

[/checklist]

pin_config.pin_bit_mask = GPIO_SEL_2 | GPIO_SEL_3 | GPIO_SEL_7;
pin_config.mode = GPIO_MODE_OUTPUT;
pin_config.pull_up_en = GPIO_PULLUP_DISABLE;
pin_config.pull_down_en = GPIO_PULLDOWN_DISABLE;
pin_config.intr_type = GPIO_PIN_INTR_DISABLE;

[checklist]

  • pin 6 e 8 configurati come input con resistenza di pull-up abilitata:

[/checklist]

pin_config.pin_bit_mask = GPIO_SEL_6 | GPIO_SEL_8;
pin_config.mode = GPIO_MODE_INPUT;
pin_config.pull_up_en = GPIO_PULLUP_ENABLE;
pin_config.pull_down_en = GPIO_PULLDOWN_DISABLE;
pin_config.intr_type = GPIO_PIN_INTR_DISABLE;

La configurazione viene infine applicata con la funzione gpio_config(&pin_config).

Codice

Visti i concetti base affrontati in questo tutorial, non ho preparato dei programmi dedicati… insieme al framework sono infatti distribuiti due esempi che illustrano quanto spiegato:

Related Posts

5 comments

Karl Britton 16 aprile 2017 - 15:41

Hi Luca

I have read most of your web-site with interest. I wish I had found it 4 weeks ago while trying to set up Eclipse!
Excellent tutorials!

Would it be possible for you to explain how to send a data packet from a PC to the ESP32 on the same wireless home network (not accessing the external web)?

My goal is to send a simple graphic (much like your LED matrix project) to the ESP32 and use the I/O (SPI) to control some LEDs.

Would it require the ESP32 to have a fixed IP address or could the network be scanned to get the automatically assigned IP address?

Many thanks in advance.

Reply
luca 19 aprile 2017 - 09:19

Hi Karl, thanks for your comment! I’m working on a tutorial for using ESP32 as a server and… something also to solve the problem to “find” the ESP32 on the network 😉

Reply
lucadentella.it – ESP32 (23) – I2C basic 9 ottobre 2017 - 08:57

[…] controller I2C sono collegati internamente alla matrice IO_MUX quindi, come vi ho spiegato in un precedente articolo, è possibile assegnare loro via software i diversi pin del chip (con alcune […]

Reply
arun maisale 5 dicembre 2018 - 05:15

hello
In the Blink example how do I

Can run ‘make menuconfig’ to choose the GPIO to blink,

I cant see Any Settings in MenuConfig where I can set GPIO

Reply
luca 7 dicembre 2018 - 15:51

in the “Example Configuration” menu… see the readme as this is an official example by Espressif

Reply

Leave a Comment