categorie: Circuiti a microcontrollore
Numero di visite: 41940
Commenti sull'articolo: 5

Metodi per la lettura e la gestione delle porte I / O di Arduino

 

Per interagire con il mondo esterno, è necessario configurare le uscite del microcontrollore per ricevere o trasmettere un segnale. Di conseguenza, ciascun pin funzionerà in modalità input e output. Ci sono due modi per farlo su ogni scheda Arduino che ami, esattamente come impari da questo articolo.

Metodi per la lettura e la gestione delle porte I / O di Arduino

Metodo 1: il linguaggio standard per l'IDE di Arduino

Lo sanno tutti Arduino È programmato in C ++ con alcuni adattamenti e semplificazioni per i principianti. Si chiama Cablaggio. Inizialmente, tutte le porte di arduino sono definite come input e non è necessario specificarlo nel codice.

Le porte sono generalmente scritte nella funzione di inizializzazione variabile:

void setup ()
{
// codice
}

Il comando pinMode viene utilizzato per questo, ha una sintassi abbastanza semplice, prima viene indicato il numero di porta, quindi il suo ruolo è separato da virgole.

pinMode (nomer_porta, naznachenie)

Con questo comando, i circuiti interni del microcontrollore sono configurati in un modo specifico.

Esistono tre modalità in cui la porta può funzionare: INPUT - input, in questa modalità si verifica lettura dei dati dai sensori, stato del pulsante, segnale analogico e digitale. La porta si trova nel cosiddetto stato ad alta impedenza, in parole semplici - l'ingresso ha un'alta resistenza. Questo valore è impostato, ad esempio, 13 pin della scheda, se necessario, come segue:

pinMode (13, INPUT);

OUTPUT - output, a seconda del comando prescritto nel codice, la porta assume un valore di uno o zero. L'uscita diventa una sorta di fonte di energia controllata e produce una corrente massima (nel nostro caso, 20 mA e 40 mA al picco) al carico collegato ad essa. Per assegnare una porta come output ad Arduino devi inserire:

pinMode (13, OUTPUT);

INPUT_PULLUP: la porta funziona come input, ma la cosiddetta si connette ad essa. Resistenza pull-up 20 kΩ.

Di seguito è mostrato il circuito interno condizionale della porta in questo stato. Una caratteristica di questo ingresso è che il segnale di ingresso è percepito come invertito (l '"unità" sull'ingresso è percepita dal microcontrollore come "zero"). In questa modalità, non è possibile utilizzare resistori di pull-up esterni quando si lavora con i pulsanti.

pinMode (13, INPUT_PULLUP);

Resistenza pull-up in ingresso

I dati vengono ricevuti dalle porte e trasmessi loro dai comandi:

  • digitalWrite (pin, valore) - converte il pin di uscita in 1 o 0 logico, rispettivamente, la tensione 5V appare o scompare in uscita, ad esempio digitalWrite (13, HIGH) - fornisce 5 volt (unità logica) a 13 pin e digitalWrite (13, basso ) - traduce 13 pin in uno stato di zero logico (0 volt);

  • digitalRead (pin) - legge il valore dall'ingresso, ad esempio digitalRead (10), legge il segnale da 10 pin;

  • analogRead (pin): legge un segnale analogico da una porta analogica, si ottiene un valore compreso tra 0 e 1023 (all'interno di un ADC a 10 bit), un esempio è analogRead (3).


Metodo 2: gestire le porte tramite i registri Atmega e velocizzare il codice

Tale controllo è ovviamente semplice, ma in questo caso ci sono due svantaggi: maggiore consumo di memoria e scarse prestazioni quando si lavora con le porte. Ma ricordi cos'è Arduino, indipendentemente dalla scheda opzionale (uno, micro, nano)? Prima di tutto questo famiglia di microcontrollori AVR ATMEGA, recentemente usato MK atmega328.

Nell'IDE di Arduino, è possibile programmare il linguaggio C AVR nativo di questa famiglia, come se si stesse lavorando con un microcontrollore separato. Ma prima le cose. Per gestire le porte di Arduino in questo modo, devi prima considerare attentamente la seguente illustrazione.

Porte per microcontrollori Atmega168

Forse qualcuno esaminerà più chiaramente le porte in questo modulo (lo stesso nella figura, ma con un design diverso):

Porte per microcontrollori Atmega328

Qui puoi vedere la corrispondenza delle conclusioni di Arduino e i nomi dei porti di Atmega. Quindi, abbiamo 3 porte:

  • PORTB;

  • PORTC;

  • PORTD.

Sulla base delle immagini mostrate, ho compilato una tabella di corrispondenza tra i porti di Arduino e Atmega, che ti sarà utile in futuro.

Tavolo Concordanza dei porti Arduino e Atmega

Atmega ha tre registri a 8 bit che controllano lo stato delle porte, ad esempio la porta B ne capirà lo scopo tracciando analogie con gli strumenti di cablaggio standard descritti all'inizio di questo articolo:

  • PORTB - Gestisce lo stato dell'output. Se il pin è in modalità "Uscita", allora 1 e 0 determinano la presenza degli stessi segnali sull'uscita. Se il pin è in modalità "Input", allora 1 collega un resistore pull-up (lo stesso di INPUT_PULLUP discusso sopra), se 0 è uno stato ad alta impedenza (analogo di INPUT);

  • PINB è un registro di lettura. Di conseguenza, contiene informazioni sullo stato corrente dei pin della porta (unità logica o zero).

  • DDRB - registro direzione porta. Con esso, si indica al microcontrollore quale sia la porta come input o output, con "1" un'uscita e "0" un input.

Invece della lettera "B", potrebbero essercene altri secondo i nomi delle porte, ad esempio PORTD o PORTC altri comandi funzionano in modo simile.

Lampeggiamo il LED, sostituiamo la funzione standard digitalWrite (). Innanzitutto, ricordiamo come appare l'esempio originale della libreria IDE di Arduino.

Codice lampeggiante LED Arduino

Questo è il codice del noto "lampeggio", che mostra il lampeggiamento del LED incorporato nella scheda.

Gestione dei pin

I commenti spiegano il codice. La logica di questo lavoro è la seguente.

Il comando PORTB B00100000 mette PB5 nello stato di un'unità logica, guarda, e quelle immagini e la tabella sotto si trovano e vediamo che PB5 corrisponde a 13 pin di Arduina.

La lettera "B" davanti ai numeri indica che stiamo scrivendo i valori in forma binaria. La numerazione in binario va da destra a sinistra, ad es. qui l'unità si trova nel sesto bit dal bordo destro del bit, il che indica al microcontrollore l'interazione con lo stato del sesto bit del registro della porta B (PB5). La tabella seguente mostra la struttura della porta D, è simile e viene fornita come esempio.

Struttura della porta D.

È possibile impostare il valore non in binario, ma in forma esadecimale, ad esempio, per questo apriamo il calcolatore di Windows e in modalità "VISUALIZZA", selezionare l'opzione "Programmatore".

Calcolatrice di Windows

Inserisci il numero desiderato:

Modalità calcolatrice programmatore

E clicca su HEX:

Traduzione di numeri su una calcolatrice

In questo caso, trasferiamo tutto questo sull'IDE di Arduino, ma invece del prefisso "B" sarà "0x".

Trasferimento del numero in in IDE Arduino

Ma con questo input c'è un problema. Se hai qualcosa collegato ad altri pin, immettendo un comando come B00010000 - ripristinerai tutti i pin tranne 13 (PB5). È possibile inserire i dati per ciascun pin singolarmente. Sarà simile a questo:

Immissione dei dati in ciascun pin

Un record del genere può sembrare incomprensibile, scopriamolo.

Analisi di un record

Questa è un'operazione di aggiunta logica, | = significa aggiungere qualcosa al contenuto della porta.

Operazione di aggiunta logica

Ciò significa che è necessario aggiungere una parola di 8 bit nel registro con un'unità spostata di 5 bit - di conseguenza, se 11000010 risulta essere 110.110.010 In questo esempio, si può vedere che è cambiato solo PB5, i restanti bit di questo registro sono rimasti invariati, così come Lo stato dei pin del microcontrollore è rimasto invariato.

Ma con l'aggiunta logica, sorge un problema: non è possibile trasformare l'unità in zero, perché:

0+0=1

1+0=1

0+1=1

La moltiplicazione logica e l'inversione verranno in nostro aiuto:

Moltiplicazione logica e inversione

& = significa moltiplicare il contenuto della porta per un numero specifico.

 

Moltiplicare il contenuto della porta per un numero

E questo è il numero per cui ci moltiplichiamo. Il segno “~” indica l'inversione. Nel nostro caso, l'unità invertita è zero. Cioè, moltiplichiamo il contenuto della porta per zero, spostato di 5 bit. Ad esempio, era 10110001, è diventato 10100001. I bit rimanenti sono rimasti invariati.

Moltiplicare il contenuto della porta per zero spostato di 5 bit

La stessa cosa può essere fatta usando l'operazione di inversione (^):

Leggendo dalle porte, l'analogo di digitalRead () viene eseguito utilizzando il registro PIN, in pratica è simile al seguente:

Leggi dalle porte

Qui controlliamo se l'espressione tra parentesi è uguale allo stato reale delle porte, ad es. allo stesso modo se abbiamo scritto if (digitalRead (12) == 1).


conclusione

Perché ci sono tali difficoltà con la gestione delle porte se è possibile utilizzare le pratiche funzioni standard? Si tratta di velocità e dimensioni del codice. Quando si utilizza il secondo metodo, discusso nell'articolo, la dimensione del codice viene notevolmente ridotta e la velocità aumenta di diversi ordini di grandezza. DigitalWrite standard () è stato eseguito in 1800 μs e registrato direttamente sulla porta in 0,2 μs, e digitalRead () in 1900 μs, e anche in 0,2 μs. Questo metodo di controllo è stato trovato negli spazi aperti della rete e si trova spesso nel codice. progetti finiti.

Vedi anche su bgv.electricianexp.com:

  • Connessione e programmazione di Arduino per principianti
  • Come collegare l'encoder incrementale ad Arduino
  • Microcontrollori PIC per principianti
  • Telecomando a microcontrollore: telecomando IR, Arduino, ESP8266, 433 ...
  • Misurazione della temperatura e dell'umidità su Arduino: una selezione di metodi

  •  
     
    Commenti:

    # 1 ha scritto: Kipovets | [Cite]

     
     

    "Ma con l'aggiunta logica, sorge un problema: non è possibile trasformare l'unità in zero, perché:

    0 + 0 = 1 "(c)

    Piccola svista: 0 + 0 = 0.

     
    Commenti:

    # 2 ha scritto: chugou | [Cite]

     
     

    Kipovets, probabilmente voleva dire:

    1 + 1 = 1

     
    Commenti:

    # 3 ha scritto: | [Cite]

     
     

    Kipovets,
    Errore banale! Vedi quanto è bello che gli specialisti siano seduti sul nostro portale! Devi creare solo contenuti adatti!

     
    Commenti:

    # 4 ha scritto: Serg | [Cite]

     
     

    Nella parte finale dice PORTB | = 1 << 5 ... if (digitalRead (12) == 1). Ma 5 pin della porta B, è 13 pin di arduino. O mi sbaglio ?!

     
    Commenti:

    # 5 ha scritto: p-a-h-a | [Cite]

     
     

    Se (PINB == B00010000) {} non lo èsimile a se abbiamo scritto if (digitalRead (12) == 1)
    piuttosto analogico
    (digitalRead (12) == 1) &&(digitalRead (13) == 1) &&(digitalRead (14) == 1) &&(digitalRead (15) == 1) &&(digitalRead (11) == 1) ... e quindi pin a 8 porte

    Qui è necessario questo:
    se (
    ! (~ PORTB & (1 << PB4))) {} //ritorna0 o 1
    o così:
    se (PORTB & (1 << PB4)) {} // restituisce l'unità spostata = 16, DEC
    o così:
    se (
    bit_is_set (PORTB, 4)) {}// restituisce l'unità spostata = 16, DEC