categorieën: Microcontroller-circuits
Aantal keer bekeken: 41940
Reacties op het artikel: 5

Methoden voor het lezen en beheren van Arduino I / O-poorten

 

Voor interactie met de buitenwereld moet u de uitgangen van de microcontroller configureren om een ​​signaal te ontvangen of te verzenden. Als gevolg hiervan werkt elke pin in de invoer- en uitvoermodus. Er zijn twee manieren om dit te doen op elk Arduino-bord waar je van houdt, precies hoe je leert van dit artikel.

Methoden voor het lezen en beheren van Arduino I / O-poorten

Methode één - De standaardtaal voor de Arduino IDE

Iedereen weet dat Arduino Het is geprogrammeerd in C ++ met enkele aanpassingen en vereenvoudigingen voor beginners. Het heet bedrading. Aanvankelijk worden alle Arduino-poorten als invoer gedefinieerd en hoeft dit niet in de code te worden gespecificeerd.

Poorten worden meestal geschreven in de variabele initialisatiefunctie:

void setup ()
{
// code
}

Gebruik hiervoor de opdracht pinMode, deze heeft een vrij eenvoudige syntax, geef eerst het poortnummer aan en vervolgens de rol, gescheiden door komma's.

pinMode (nomer_porta, naznachenie)

Met dit commando wordt het interne circuit van de microcontroller op een specifieke manier geconfigureerd.

Er zijn drie modi waarin de poort kan werken: INPUT - invoer, in deze modus vindt plaats gegevens lezen van sensoren, knopstatus, analoog en digitaal signaal. De poort bevindt zich in de zogenaamde hoge impedantietoestand, in eenvoudige woorden - de ingang heeft een hoge weerstand. Deze waarde wordt bijvoorbeeld 13 pins van het bord ingesteld als volgt:

pinMode (13, INPUT);

UITGANG - uitvoer, afhankelijk van het in de code voorgeschreven commando, heeft de poort een waarde van één of nul. De uitgang wordt een soort gecontroleerde voedingsbron en produceert een maximale stroom (in ons geval 20 mA en 40 mA bij de piek) naar de aangesloten belasting. Om een ​​poort als output aan Arduino toe te wijzen, moet u het volgende invoeren:

pinMode (13, UITGANG);

INPUT_PULLUP - de poort werkt als een ingang, maar de zogenaamde maakt er verbinding mee. 20 kΩ pull-up weerstand.

De voorwaardelijke interne circuits van de poort in deze toestand worden hieronder weergegeven. Een kenmerk van deze ingang is dat het ingangssignaal als geïnverteerd wordt waargenomen (de "eenheid" aan de ingang wordt door de microcontroller als "nul" waargenomen). In deze modus kunt u geen externe pull-up weerstanden gebruiken bij het werken met knoppen.

pinMode (13, INPUT_PULLUP);

Ingang pull-up weerstand

Gegevens worden ontvangen van de poorten en naar hen verzonden door de opdrachten:

  • digitalWrite (pin, waarde) - converteert de output pin naar een logische 1 of 0, respectievelijk 5V spanning verschijnt of verdwijnt bij de output, bijvoorbeeld digitalWrite (13, HIGH) - levert 5 volt (logische eenheid) naar 13 pins, en digitalWrite (13, low ) - vertaalt 13 pinnen in een staat van logische nul (0 volt);

  • digitalRead (pin) - leest de waarde van de ingang, bijvoorbeeld digitalRead (10), leest het signaal van 10 pins;

  • analogRead (pin) - leest een analoog signaal van een analoge poort, u krijgt een waarde in het bereik van 0 tot 1023 (binnen een 10-bit ADC), een voorbeeld is analogRead (3).


Methode twee - beheer poorten via Atmega-registers en versnel code

Een dergelijke besturing is natuurlijk eenvoudig, maar in dit geval zijn er twee nadelen - groter geheugenverbruik en slechte prestaties bij het werken met poorten. Maar onthoud wat Arduino is, ongeacht de optiekaart (uno, micro, nano)? Allereerst dit microcontroller AVR-familie ATMEGA, recent gebruikte MK atmega328.

In de Arduino IDE kunt u de C AVR-taal van deze familie programmeren, alsof u met een afzonderlijke microcontroller werkt. Maar eerst dingen eerst. Om Arduino-poorten op deze manier te beheren, moet u eerst de volgende illustratie zorgvuldig overwegen.

Atmega168 Microcontroller-poorten

Misschien zal iemand de poorten in deze vorm (hetzelfde in de figuur, maar in een ander ontwerp) duidelijker onderzoeken:

Atmega328 Microcontroller-poorten

Hier ziet u de correspondentie van de conclusies van Arduino en de namen van de havens van Atmega. We hebben dus 3 poorten:

  • PORTB;

  • PORTC;

  • PORTD.

Op basis van de getoonde afbeeldingen heb ik een correspondentietabel samengesteld tussen de poorten van Arduino en Atmega, dit zal in de toekomst nuttig voor u zijn.

Concordantietabel van poorten Arduino en Atmega

Atmega heeft drie 8-bit registers die de status van de poorten regelen, bijvoorbeeld, poort B zal hun doel bepalen door analogieën te tekenen met de standaard bedradingshulpmiddelen die aan het begin van dit artikel worden beschreven:

  • PORTB - Beheer output status. Als de pin in de modus "Uitgang" staat, bepalen 1 en 0 de aanwezigheid van dezelfde signalen aan de uitgang. Als de pin in de modus "Input" staat, dan verbindt 1 een pull-up weerstand (hetzelfde als de INPUT_PULLUP hierboven besproken), als 0 een hoge impedantietoestand is (analoog aan INPUT);

  • PINB is een leesregister. Dienovereenkomstig bevat het informatie over de huidige status van de poortpennen (logische eenheid of nul).

  • DDRB - register van poortrichting. Hiermee geeft u aan de microcontroller aan of de poort een ingang of een uitgang is, met "1" een uitgang en "0" een ingang.

In plaats van de letter "B", kan er een andere zijn volgens de namen van de poorten, bijvoorbeeld PORTD of PORTC andere opdrachten werken op dezelfde manier.

We knipperen de LED, vervangen de standaard digitalWrite () functie. Laten we ons eerst herinneren hoe het oorspronkelijke exemplaar uit de Arduino IDE-bibliotheek eruit ziet.

Arduino LED knippercode

Dit is de code van de bekende "knipper", die het knipperen van de LED laat zien die in het bord is ingebouwd.

Pinbeheer

Het commentaar verklaart de code. De logica van dit werk is als volgt.

Het PORTB B00100000-commando plaatst PB5 in de staat van een logische eenheid, ziet eruit, en die afbeeldingen en de onderstaande tabel en zien dat PB5 overeenkomt met 13-pins van Arduina.

De letter "B" voor de cijfers geeft aan dat we de waarden in binaire vorm schrijven. Nummering in binair getal gaat van rechts naar links, d.w.z. hier bevindt de eenheid zich in het zesde bit vanaf de rechterrand van het bit, dat de microcontroller vertelt over de interactie met de status van het zesde bit van het poort B register (PB5). De onderstaande tabel toont de structuur van poort D, deze is vergelijkbaar en wordt als voorbeeld gegeven.

Port D structuur

U kunt de waarde niet in binair instellen, maar in hexadecimale vorm, hiervoor openen we bijvoorbeeld de Windows-rekenmachine en in de modus "BEKIJKEN" selecteert u de optie "Programmer".

Windows rekenmachine

Voer het gewenste nummer in:

Calculator programmeermodus

En klik op HEX:

Vertaling van getallen op een rekenmachine

In dit geval dragen we dit alles over naar de Arduino IDE, maar in plaats van het voorvoegsel "B" wordt het "0x".

Nummeroverdracht in Arduino IDE

Maar met deze input is er een probleem. Als u iets hebt aangesloten op andere pinnen, voert u een opdracht zoals B00010000 in - u reset alle pinnen behalve 13 (PB5). U kunt gegevens voor elke pin afzonderlijk invoeren. Het ziet er zo uit:

Gegevens invoeren in elke pin

Zo'n record lijkt misschien onbegrijpelijk, laten we het uitzoeken.

Een record parseren

Dit is een logische toevoeging, | = betekent iets toevoegen aan de inhoud van de poort.

Logische toevoeging operatie

Dit betekent dat u een woord van 8 bits in het register moet toevoegen met een eenheid die met 5 bits is verschoven - als een resultaat 11000010 110,110,010 blijkt te zijn. In dit voorbeeld is te zien dat alleen PB5 is gewijzigd, de resterende bits van dit register ongewijzigd zijn gebleven, evenals De status van de microcontroller-pinnen is ongewijzigd gebleven.

Maar met logische toevoeging doet zich een probleem voor - u kunt het apparaat niet in nul veranderen, omdat:

0+0=1

1+0=1

0+1=1

Logische vermenigvuldiging en inversie zullen ons helpen:

Logische vermenigvuldiging en omkering

& = betekent om de inhoud van de poort met een specifiek nummer te vermenigvuldigen.

 

Portinhoud vermenigvuldigen met een nummer

En dit is het getal waarmee we vermenigvuldigen. Het "~" -teken geeft inversie aan. In ons geval is de omgekeerde eenheid nul. Dat wil zeggen, we vermenigvuldigen de inhoud van de poort met nul, verschoven met 5 bits. Het was bijvoorbeeld 10110001, het werd 10100001. De resterende bits bleven ongewijzigd.

Vermenigvuldig de inhoud van de poort met nul verschoven met 5 bits

Hetzelfde kan worden gedaan met de omkering (^):

Het lezen van poorten, het analoog van digitalRead () wordt uitgevoerd met behulp van het PIN-register, in de praktijk ziet het er zo uit:

Lezen van poorten

Hier controleren we of de uitdrukking tussen haakjes gelijk is aan de werkelijke toestand van de poorten, d.w.z. op dezelfde manier als we zouden schrijven als (digitalRead (12) == 1).


conclusie

Waarom zijn er zulke problemen met poortbeheer als u standaard handige functies kunt gebruiken? Het draait allemaal om snelheid en codegrootte. Bij gebruik van de tweede methode, die in het artikel wordt besproken, wordt de codegrootte aanzienlijk verkleind en neemt de snelheid toe met verschillende orden van grootte. De standaard digitalWrite () werd uitgevoerd in 1800 μs en nam rechtstreeks op op de poort in 0,2 μs en digitalRead () in 1900 μs, en werd ook in 0,2 μs. Deze besturingsmethode werd gevonden in de open ruimtes van het netwerk en wordt vaak in code gevonden. voltooide projecten.

Zie ook op bgv.electricianexp.com:

  • Arduino verbinden en programmeren voor beginners
  • Hoe incrementele encoder aan Arduino te verbinden
  • PIC-microcontrollers voor beginners
  • Microcontroller-afstandsbediening: IR-afstandsbediening, Arduino, ESP8266, 433 ...
  • Temperatuur en vochtigheid meten op Arduino - een selectie van methoden

  •  
     
    reacties:

    # 1 schreef: Kipovets | [Cite]

     
     

    "Maar met logische toevoeging doet zich een probleem voor - u kunt de eenheid niet in nul veranderen, omdat:

    0 + 0 = 1 "(c)

    Klein overzicht: 0 + 0 = 0.

     
    reacties:

    # 2 schreef: chugou | [Cite]

     
     

    Kipovets, hij wilde waarschijnlijk zeggen:

    1 + 1 = 1

     
    reacties:

    # 3 schreef: | [Cite]

     
     

    Kipovets,
    Banale typefout! U ziet hoe goed het is dat specialisten op onze portal zitten! U hoeft alleen geschikte inhoud te maken!

     
    reacties:

    # 4 schreef: Serg | [Cite]

     
     

    In het laatste deel staat PORTB | = 1 << 5 ... if (digitalRead (12) == 1). Maar 5 pin van poort B, het is 13 pin van arduino. Of vergis ik me ?!

     
    reacties:

    # 5 schreef: p-a-H-a | [Cite]

     
     

    Als (PINB == B00010000) {} niet isvergelijkbaar met als we schreven if (digitalRead (12) == 1)
    redelijk analoog
    (digitalRead (12) == 1) &&(digitalRead (13) == 1) &&(digitalRead (14) == 1) &&(digitalRead (15) == 1) &&(digitalRead (11) == 1) ... en dus 8 poortpinnen

    Hier heb je dit nodig:
    als (
    ! (~ PORTB & (1 << PB4))) {} //opbrengst0 of 1
    zoals dit:
    als (PORTB & (1 << PB4)) {} // retourneert de verschoven eenheid = 16, DEC
    zoals dit:
    als (
    bit_is_set (PORTB, 4)) {}// geeft de verschoven eenheid terug = 16, DEC