kategorier: Mikrokontrollkretsar
Antal visningar: 41940
Kommentarer till artikeln: 5

Metoder för att läsa och hantera Arduino I / O-portar

 

För att interagera med omvärlden måste du konfigurera utgångarna från mikrokontrollern för att ta emot eller sända en signal. Som ett resultat kommer varje stift att fungera i ingångs- och utgångsläget. Det finns två sätt att göra detta på varje Arduino-bräde som du älskar, exakt hur du lär dig av den här artikeln.

Metoder för att läsa och hantera Arduino I / O-portar

Metod ett - standardspråket för Arduino IDE

Alla vet det Arduino Det är programmerat i C ++ med viss anpassning och förenklingar för nybörjare. Det kallas ledningar. Till att börja med definieras alla arduino-portar som ingångar, och det finns inget behov av att ange detta i koden.

Portar skrivs vanligtvis i variabelinitieringsfunktionen:

ogiltig installation ()
{
// kod
}

För att göra detta använder du kommandot pinMode, det har en ganska enkel syntax, ange först portnumret och sedan dess roll, åtskilda med kommatecken.

pinMode (nomer_porta, naznachenie)

Med detta kommando konfigureras mikrokontrollerns interna kretsar på ett specifikt sätt.

Det finns tre lägen där porten kan fungera: INPUT - ingång, i detta läge inträffar läsa data från sensorer, knappstatus, analog och digital signal. Hamnen ligger i den så kallade med hög impedans, i enkla ord - ingången har hög motstånd. Detta värde ställs in, till exempel, 13 stift på kortet, om nödvändigt, enligt följande:

pinMode (13, INPUT);

UTGÅNG - utgång, beroende på kommandot som föreskrivs i koden, tar porten ett värde på ett eller noll. Utgången blir en slags kontrollerad kraftkälla och producerar en maximal ström (i vårt fall 20 mA och 40 mA vid toppen) till den last som är ansluten till den. För att tilldela en port som utgång till Arduino måste du ange:

pinMode (13, OUTPUT);

INPUT_PULLUP - porten fungerar som en ingång, men den så kallade ansluter till den. 20 kΩ uppdragningsmotstånd.

Portens villkorade interna kretsar i detta tillstånd visas nedan. En funktion hos denna ingång är att insignalen uppfattas som inverterad ("enheten" vid ingången uppfattas av mikrokontrollern som "noll"). I det här läget kan du inte använda externa uppdragningsmotstånd när du arbetar med knappar.

pinMode (13, INPUT_PULLUP);

Ingångsmotstånd

Data tas emot från portarna och överförs till dem av kommandona:

  • digitalWrite (stift, värde) - konverterar utgångstappen till logisk 1 respektive 0, 5V-spänning visas eller försvinner vid utgången, till exempel digitalWrite (13, HÖG) - levererar 5 volt (logisk enhet) till 13 stift och digitalWrite (13, låg) ) - översätter 13 stift till ett tillstånd av logisk noll (0 volt);

  • digitalRead (pin) - läser värdet från ingången, exempelvis digitalRead (10), läser signalen från 10 stift;

  • analogRead (pin) - läser en analog signal från en analog port, du får ett värde i området från 0 till 1023 (inom en 10-bitars ADC), ett exempel är analogRead (3).


Metod två - hantera portar genom Atmega-register och snabba upp koden

En sådan kontroll är naturligtvis enkel, men i det här fallet finns det två nackdelar - större minneskonsumtion och dålig prestanda när du arbetar med portar. Men kom ihåg vad är en Arduino, oavsett alternativkort (uno, mikro, nano)? Först och främst detta mikrokontroller AVR-familj ATMEGA, använde nyligen MK atmega328.

I Arduino IDE kan du programmera C AVR-språket som är infödda till den här familjen, som om du arbetade med en separat mikrokontroller. Men först saker först. För att hantera Arduino-portarna på detta sätt måste du först ta hänsyn till följande illustration.

Atmega168 mikrokontrollportar

Kanske kommer någon tydligare att undersöka hamnarna i denna form (samma på figuren, men i en annan design):

Atmega328 mikrokontrollportar

Här ser du korrespondensen mellan slutsatserna från Arduino och namnen på hamnarna atmega. Så vi har tre portar:

  • PORTB;

  • PORTC;

  • PORTD.

Baserat på de visade bilderna sammanställde jag en korrespondensstabell mellan hamnarna i Arduino och Atmega, det kommer att vara användbart för dig i framtiden.

Concordance tabell över hamnarna Arduino och Atmega

Atmega har tre 8-bitarsregister som kontrollerar tillståndet för portarna, till exempel kommer port B att räkna ut deras syfte genom att rita analogier med standardledningsverktygen som beskrivs i början av denna artikel:

  • PORTB - Hantera utgångsstatus. Om stiftet är i "Output" -läge, bestämmer 1 och 0 närvaron av samma signaler vid utgången. Om stiftet är i "Input" -läget, ansluter 1 ett pull-up-motstånd (samma som INPUT_PULLUP som diskuterats ovan), om 0 är ett högimpedans-tillstånd (analog INPUT);

  • PINB är ett läsregister. Följaktligen innehåller den information om det aktuella tillståndet för portstiften (logisk enhet eller noll).

  • DDRB - portriktningsregister. Med den indikerar du till mikrokontrollern om porten är en ingång eller en utgång, med "1" en utgång och "0" en ingång.

I stället för bokstaven “B” kan det finnas någon annan beroende på namnen på portarna, till exempel PORTD eller PORTC andra kommandon fungerar på liknande sätt.

Vi blinkar lysdioden, byt ut funktionen för digitalWrite (). Låt oss först komma ihåg hur det ursprungliga exemplet från Arduino IDE-biblioteket ser ut.

Arduino LED blinkande kod

Det här är koden för den välkända "blinkningen", som visar blinkningen på den inbyggda lysdioden i kortet.

Pin management

Kommentarerna förklarar koden. Logiken i detta arbete är som följer.

Kommandot PORTB B00100000 sätter PB5 i tillståndet för en logisk enhet, titta, och dessa bilder och tabellen nedan finns och vi ser att PB5 motsvarar 13 stift Arduina.

Bokstaven "B" framför siffrorna indikerar att vi skriver värdena i binär form. Nummerering i binär går från höger till vänster, d.v.s. här är enheten i den sjätte biten från bitens högra kant, som berättar mikrokontrollern om interaktionen med tillståndet för den sjätte biten i port B-registret (PB5). Tabellen nedan visar strukturen för port D, den är likadan och ges som ett exempel.

Port D-struktur

Du kan ställa in värdet inte i binär, men i hexadecimal form, till exempel för detta öppnar vi Windows-kalkylatorn och i "VIEW" -läget, välj alternativet "Programmer".

Windows-kalkylator

Ange önskat nummer:

Programmeringsräknare

Och klicka på HEX:

Översättning av siffror på en räknemaskin

I det här fallet överför vi allt detta till Arduino IDE, men istället för prefixet "B" kommer det att vara "0x".

Nummeröverföring i Arduino IDE

Men med denna inmatning finns det ett problem. Om du har något anslutet till andra stift och ange ett kommando som B00010000 - återställer du alla stift utom 13 (PB5). Du kan ange data för varje stift separat. Det kommer att se ut så här:

Mata in data i varje stift

En sådan post kan verka obegriplig, låt oss räkna ut det.

Analysera en post

Detta är en logisk tilläggsoperation, | = innebär att lägga till något i portens innehåll.

Logisk tilläggsoperation

Detta innebär att du måste lägga till ett ord med 8 bitar i registret med en enhet förskjuten med 5 bitar - som ett resultat, om 11000010 visar sig vara 110.110.010. I detta exempel kan man se att endast PB5 har ändrats, de återstående bitarna i detta register har förblivit oförändrade, liksom Tillståndet för mikrokontrollstiften förblev oförändrat.

Men med logiskt tillägg uppstår ett problem - du kan inte förvandla enheten till noll, eftersom:

0+0=1

1+0=1

0+1=1

Logisk multiplikation och inversion kommer att hjälpa oss:

Logisk multiplikation och invertering

& = betyder att multiplicera portens innehåll med ett specifikt nummer.

 

Multiplicera portens innehåll med ett nummer

Och detta är det antal som vi multiplicerar med. "~" -Tecknet indikerar inversion. I vårt fall är den inverterade enheten noll. Det vill säga vi multiplicerar portens innehåll med noll, skiftat med 5 bitar. Till exempel var det 10110001, det blev 10100001. De återstående bitarna förblev oförändrade.

Multiplicera portens innehåll med noll skiftat med 5 bitar

Detsamma kan göras med inverteringsoperationen (^):

Avläsning från portar, analogen till digitalRead () utförs med hjälp av PIN-registret, i praktiken ser det ut så här:

Läs från portarna

Här kontrollerar vi om uttrycket inom parentes är lika med porternas verkliga tillstånd, d.v.s. på liknande sätt om vi skrev om (digitalRead (12) == 1).


slutsats

Varför finns det sådana svårigheter med porthantering om du kan använda praktiska standardfunktioner? Det handlar om hastighet och kodstorlek. När man använder den andra metoden, som diskuteras i artikeln, minskas kodstorleken avsevärt, och hastigheten ökar med flera storleksordningar. Standarden digitalWrite () utfördes på 1800 μs och inspelades direkt till porten i 0,2 μs och digitalRead () 1900 μs och blev också 0,2 μs. Denna kontrollmetod hittades på nätverkets öppna utrymmen och finns ofta i kod. färdiga projekt.

Se även på elektrohomepro.com:

  • Ansluta och programmera Arduino för nybörjare
  • Hur man ansluter inkrementell kodare till Arduino
  • PIC-mikrokontroller för nybörjare
  • Microcontroller Remote Control: IR Remote, Arduino, ESP8266, 433 ...
  • Mätning av temperatur och luftfuktighet på Arduino - ett urval av metoder

  •  
     
    kommentarer:

    # 1 skrev: Kipovets | [Cite]

     
     

    "Men med logiskt tillägg uppstår ett problem - du kan inte förvandla enheten till noll, eftersom:

    0 + 0 = 1 "(c)

    Liten övervakning: 0 + 0 = 0.

     
    kommentarer:

    # 2 skrev: chugou | [Cite]

     
     

    Kipovets ville han förmodligen säga:

    1 + 1 = 1

     
    kommentarer:

    # 3 skrev: | [Cite]

     
     

    Kipovets,
    Banal skrivfel! Du ser hur bra det är att specialister sitter på vår portal! Du måste bara skapa lämpligt innehåll!

     
    kommentarer:

    # 4 skrev: Serg | [Cite]

     
     

    I den sista delen står det PORTB | = 1 << 5 ... if (digitalRead (12) == 1). Men 5 stift port B, det är 13 stift arduino. Eller har jag misstag ?!

     
    kommentarer:

    # 5 skrev: p-a-h-a | [Cite]

     
     

    Om (PINB == B00010000) {} inte är detliknar om vi skrev om (digitalRead (12) == 1)
    snarare analog
    (digitalRead (12) == 1) &&(digitalRead (13) == 1) &&(digitalRead (14) == 1) &&(digitalRead (15) == 1) &&(digitalRead (11) == 1) ... och så 8 portstift

    Här behöver du antingen detta:
    om (
    ! (~ PORTB & (1 << PB4))) {} //avkastning0 eller 1
    antingen så här:
    om (PORTB & (1 << PB4)) {} // returnerar den skiftade enheten = 16, DEC
    antingen så här:
    om (
    bit_is_set (PORTB, 4)) {}// returnerar den skiftade enheten = 16, DEC