ESP32 (26) – UART

luca 06/11/2017 0

UART (Universal Asynchronous Receiver-Transmitter) è una periferica hardware che consente una comunicazione seriale asincrona, con formato dati e velocità configurabili. La periferica UART normalmente funziona a livello logico: i segnali elettrici sono poi generati da un diverso circuito, secondo gli standard propri del bus di comunicazione scelto.

Ad esempio la classica “porta seriale” dei personal computer si basa sullo standard EIA RS-232, standard che definisce a livello fisico come i segnali sono generati sul mezzo di comunicazione. Esistono appositi chip (il più famoso è sicuramente il MAX232 di Maxim Integrated) per convertire i livelli logici di una periferica UART in segnali secondo lo standard EIA RS232:

uart-001

Il chip esp32 offre 3 controller UART. Questi controller sono collegati alla matrice GPIO; in tal modo è possibile assegnare loro uno i diversi pin digitali del chip:

uart-002

Il framework esp-idf contiene un driver (uart.c) per semplificare l’utilizzo dei controller; per utilizzarlo includiamo il relativo file header nel nostro programma:

#include "driver/uart.h"

I nomi dei 3 controller per il driver sono:

uart-003

In questo primo articolo vediamo l’utilizzo base di un controller; eventi ed interrupts saranno argomento di un prossimo articolo.

Iniziamo con il configurare il controller tramite la struct uart_config_t:

uart_config_t uart_config = {
  .baud_rate = 115200,
  .data_bits = UART_DATA_8_BITS,
  .parity = UART_PARITY_DISABLE,
  .stop_bits = UART_STOP_BITS_1,
  .flow_ctrl = UART_HW_FLOWCTRL_DISABLE
};
  • baud_rate indica la velocità di trasmissione
  • data_bits, e stop_bits indicano il numero di bit per ogni “parola” e il numero di bit di stop
  • parity indica se trasmettere o meno il bit di parità
  • flow_ctrl indica la tipologia di controllo di flusso (hardwaresoftwaredisabilitata)

Vi sono due ulteriori parametri (rx_flow_ctrl_threshuse_ref_tick) utilizzabili per indicare la soglia per il segnale RTS in caso di controllo di flusso hardware e per utilizzare il segnale REF_TICK come clock per il controller UART.

Le costanti da utilizzare per data_bitsstop_bits… sono definite nel file uart.h.

Spesso i parametri da utilizzare per comunicare con un dispositivo in modalità seriale sono espressi in forma “condensata”, ad esempio se trovate indicato 9600,8N1 significa

  • velocità 9600 baud
  • “parola” di 8 bit
  • Nessuna parità
  • 1 stop bit

Configuriamo il controller con il metodo:

uart_param_config(uart_port_t uart_num, const uart_config_t *uart_config);

indicando il numero del controller scelto (uart_num) e la struct che contiene la configurazione preparata in precedenza (uart_config).

Terminiamo la configurazione indicando al controller quali pin utilizzare per i diversi segnali:

uart_set_pin(uart_port_t uart_num, int tx_io_num, int rx_io_num, 
  int rts_io_num, int cts_io_num);

Possiamo utilizzare la costante UART_PIN_NO_CHANGE se quel particolare segnale non è utilizzato o se vogliamo mantenere il pin di default.

Ad esempio per mappare il controller 0 sui pin 4 e 5 senza utilizzare i segnali RTS e CTS:

uart_set_pin(UART_NUM_0, 4, 5, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE);

Possiamo ora installare il driver con:

uart_driver_install(uart_port_t uart_num, int rx_buffer_size, int tx_buffer_size, 
  int queue_size, QueueHandle_t* uart_queue, int intr_alloc_flags);

Oltre al numero del controller, dobbiamo indicare la dimensione dei due buffer di ricezione e trasmissione. I parametri relativi alla queue li vedremo nel prossimo articolo.

I due buffer devono avere dimensione maggiore rispetto ai buffer hardware (128). Solo per il buffer di trasmissione è possibile indicare dimensione = 0; in tal caso il driver si comporterà in maniera bloccante, ovvero l’esecuzione del task sarà bloccata fino al termine della trasmissione.

Vediamo ora come inviare dati. Per meglio comprendere le differenze tra i comandi disponibili, è necessario comprendere come esistano due buffer: uno hardware, integrato nel controller UART e uno software, implementato nel driver:

uart-004

Il primo comando di invio – da usare quando viene disabilitato il buffer di trasmissione software – è uart_tx_chars():

int uart_tx_chars(uart_port_t uart_num, const char* buffer, uint32_t len);

Tale comando invia len bytes prendendoli da buffer. Non utilizzando un buffer software, è possibile che il comando non riesca a inviare tutti i bytes specificati per riempimento del buffer hardware; il metodo uart_tx_chars restituisce quindi il numero di bytes effettivamente inviati.

Per utilizzare il buffer software invece esiste il comando uart_write_bytes():

int uart_write_bytes(uart_port_t uart_num, const char* src, size_t size);

Questo comando copia size bytes dall’array src nel buffer del driver: sarà poi il driver in maniera autonoma a gestire la comunicazione con il controller e l’effettivo invio dei dati. Anche il comando uart_write_bytes() restituisce il numero di bytes effettivamente scritti nel tx buffer.

In ricezione, possiamo utilizzare il comando uart_read_bytes():

int uart_read_bytes(uart_port_t uart_num, uint8_t* buf, uint32_t length, 
  TickType_t ticks_to_wait);

Tale comando legge un massimo di length bytes dal buffer di ricezione e li memorizza nell’array buf. Il comando rimane in attesa di dati il numero di ticks specificati, quindi ritorna il numero di bytes effettivamente letti.

E’ possibile sapere il numero di bytes attualmente presenti nel buffer di ricezione con:

uart_get_buffered_data_len(uart_port_t uart_num, size_t* size);

UART e stdio

Il framework esp consente di utilizzare uno dei controller UART come periferica per le funzionalità di I/O standard. Gli stream standard Unix (stdin, stdout e stderr) sono infatti associati a operazioni di RX e TX da tale controller; è quindi possibile utilizzare i metodi standard C quali printf()scanf()… per scrivere e leggere da tale controller.

Tramite menuconfig è possibile indicare quale controller utilizzare, i parametri di tale controller o se disabilitare del tutto questa funzionalità:

uart-005

Demo

Nel seguente filmato (sottotitoli in italiano disponibili) mostro il funzionamento del controller UART del chip esp32 collegandolo ad un convertitore USB->seriale. Sia il convertitore che la scheda di sviluppo esp32 sono connessi al mio laptop: in questo modo posso inviare dei dati dal laptop alla porta UART1 del chip, leggerli e inviarli nuovamente al laptop tramite la porta UART0.

Leave A Response »

Questo sito usa i cookie per poterti offrire una migliore esperienza di navigazione maggiori informazioni

Questo sito utilizza i cookie per fonire la migliore esperienza di navigazione possibile. Continuando a utilizzare questo sito senza modificare le impostazioni dei cookie o clicchi su "Accetta" permetti al loro utilizzo.

Chiudi