Ako zrýchliť operáciu digitalWrite()

Keďže vo väčšine svojich projektov Arduino používate funkciu digitalWrite(). Môžete prísť do bodu, keď je táto funkcia príliš pomalá, pretože ju musíte používať veľa a s vysokou frekvenciou. V tomto návode vám ukážem, ako vytvoriť rýchly digitalWrite(), aby ste mohli zrýchliť svoje programy.

Kedy by ste mali optimalizovať (a kedy nie)

Predtým, ako pôjdem ďalej, chcem zdôrazniť toto: nepokúšajte sa optimalizovať kód príliš skoro, najmä ak s ním nie je nič zlé. Ak vaša aplikácia pozostáva z prepínania digitálneho pinu každých 100 ms a ak nemáte žiadne obmedzenia v reálnom čase, potom sa neobťažujte optimalizáciou, len stratíte čas. “Predčasná optimalizácia je koreňom všetkého zla.” Uistite sa teda, predtým, ako ju začnete robiť , skutočne potrebujete optimalizáciu.

Meranie rýchlosti digitalWrite(). Optimalizovať veci je skvelé, ale ak neviete, čo a o koľko optimalizujete, potom to nemá zmysel. Pozrime sa teda, koľko času zaberie digitalWrite(). Potom ho budeme môcť vylepšiť a znova zmerať, aby sme zistili, koľko času ušetríme. Aby sme získali presné meranie, vykonáme digitalWrite() 1 000-krát a potom výsledok vydelíme 1 000. Často je lepšie vziať veľkú vzorku namiesto merania iba jednej akcie.

Tu je testovací kód :

Tento kód vytlačí celkové trvanie potrebné na vykonanie 1000 digitalWrite() a potom vytlačí priemerné trvanie iba pre jeden digitalWrite(). Ak teda spustíte tento kód a otvoríte sériový monitor, dostanete niečo také (na Arduino Uno):

Celkové trvanie: 3396 µs Trvanie jedného digitálneho zápisu(): 3,40 µs

Tu sme použili micros() na získanie času. micros() môže byť presné len do 4 mikrosekúnd, takže to je ďalší dobrý dôvod na výpočet priemeru, aby sme mohli mať oveľa lepšiu presnosť. 3,40 mikrosekúnd môže byť dosť dlhý čas na zmenu stavu jedného kolíka.

digitalWrite()

Namiesto použitia funkcie digitalWrite() budeme priamo manipulovať s portom, aby sme zmenili stav kolíka. Tu je mapovanie pinov pre dosky Atmega168 a Atmega328 Arduino.

Znamená ak chcete získať prístup k digitálnemu kolíku 8, použijete port B0.

V podstate máte 3 porty:

  • B: pre digitálne kolíky 8 – 13
  • C: pre analógové vstupné kolíky 0 – 5
  • D: pre digitálne kolíky 0 – 7

Použitie priamej manipulácie s portom namiesto digitalWrite()

Zachováme rovnaký kód ako predtým (pomocou digitálneho pinu 8). Jediná vec, ktorú zmeníme, je cyklus for.

Ako vlastne napísať tento kód?

Ak chcete zmeniť stav kolíka, musíte použiť „PORT“. Potom pridajte písmeno zodpovedajúce portu. V tomto prípade je port spojený s digitálnym kolíkom 8 B0, takže používame B, takže sa stáva PORTB. Pre akýkoľvek pin na porte C použijete PORTC a pre port D použijete PORTD. Potom tomuto portu priradíme bajt. Na to používame binárnu notáciu, počnúc B a nasledujúcou 8 číslami (0 alebo 1). Každý bit zodpovedá inému stavu kolíka.

Takže, aby sme zmenili stav PB0, jednoducho upravíme prvý bit sprava. Použitie 1 znamená, že kolík bude VYSOKÝ a 0 znamená, že kolík bude NÍZKY. O niečo neskôr poskytnem ďalšie vysvetlenia, teraz sa pozrime, či to zrýchli funkciu digitalWrite alebo nie.

Tu je výsledok zo sériového monitora. Celkové trvanie: 192 µs Trvanie jedného digitalWrite(): 0,19 µs To je oveľa rýchlejšie! Od 3,4 µs do 0,19 µs. Trvanie realizácie bolo rozdelené takmer 18. Teraz, ak chcete zmeniť stav iného pinu, musíte jednoducho zopakovať rovnaký proces.

Napríklad, ak chcete upraviť digitálny pin 11 (port B3), budete musieť upraviť 4. bit sprava: PORTB = B00001000; pre VYSOKÝ a PORTB = B00000000; pre NÍZKE.

Priama manipulácia s portom zmení všetky stavy kolíka Keď na nastavenie stavu kolíka používate priamu manipuláciu s portom, v skutočnosti nastavujete všetky stavy portu. Pri použití PORTB nastavujete všetky stavy pre kolíky 8-13.

Ak napíšete PORTB = B00100000;, nehovoríte len „Nastaviť digitálny kolík 13 na VYSOKÚ“, hovoríte aj „Nastaviť digitálne kolíky 8, 9, 10, 11, 12 na NÍZKU“. To môže byť veľmi výhodné, ak chcete ušetriť ešte viac času vykonávania a nastaviť viacero stavov pinov súčasne.

Napríklad s PORTB = B00100111; nastavujete digitálne kolíky 8, 9, 10 a 13 na HIGH a kolíky 11 a 12 nastavujete na LOW. Možno však nechcete nastaviť všetky kolíky naraz. Možno chcete nastaviť iba stav jedného kolíka. A tiež možno neviete, v akom stave sú momentálne všetky piny z portu. Ako sa s tým teda vysporiadať? Môžete použiť operátor AND alebo operátor OR. Pozrime sa na príklade.

Ak napíšete PORTB = PORTB | B00100000;, potom už len kolík 13 nastavíte na VYSOKÝ. Všetky ostatné kolíky zostanú v rovnakom stave.

Jednoducho preto:

  • 1 OR 0 = 1
  • 0 OR 0 = 0

Takže vytvorenie OR s 0 nemení hodnotu. Ak urobíte OR s 1, výsledok bude zakaždým 1, takže je ideálne nastaviť stav jedného kolíka na VYSOKÝ. A teraz, ak chcete nastaviť kolík 13 na LOW (a iba tento), môžete napísať PORTB = PORTB & B11011111;. Všetky ostatné kolíky zostanú v rovnakom stave.

Pretože:

  • 1 AND 1 = 1
  • 0 AND 1 = 0

Vytvorenie AND s 1 nezmení hodnotu. Ak urobíte AND s 0, výsledok bude zakaždým 0, takže je správne nastaviť stav jedného kolíka na NÍZKY. Túto techniku ​​​​môžete použiť aj na nastavenie viacerých stavov pinov, pričom všetky ostatné ponecháte v predchádzajúcom stave.

Teraz, ak to použijeme na náš predchádzajúci príklad kódu pre (digitálny kolík 8):

Tu je výsledok zo sériového monitora:

Celkové trvanie: 256 µs

Trvanie jedného digitálneho zápisu(): 0.26 µs

Ako vidíte, pri používaní operátorov OR a AND je to trochu pomalšie. Stále je to však 13-krát rýchlejšie ako funkcia digitalWrite(). Mali by ste sa pokúsiť použiť tento spôsob na zvládnutie priamej manipulácie s portom tak často, ako je to možné.

pozor na :

  • Pri priamej manipulácii s portami máte viac šancí pokaziť veci. Funkcia digitalWrite() je celkom bezpečná, s množstvom overení, ktoré sťažujú pokazenie. Keď túto funkciu obídete, beriete na seba zodpovednosť za to, čo robíte s kolíkmi. Takže skôr, ako spustíte kód, v ktorom priamo manipulujete s portami, skontrolujte a uistite sa, čo presne robíte.
  • Niektoré bity by sa nemali takto upravovať. Upravte len tie časti, o ktorých ste si istí. Napríklad PB6 a PB7 sa používajú pre kryštál. Skúste sa ich teda nedotknúť. Použite operátory OR a AND.
  • Serial na Arduine používa digitálne piny 0 a 1, ktoré zodpovedajú portom D0 a D1. Pri úprave pinu z portu D sa uistite, že používate PORTD = PORTD | Bxxxxxx00; alebo PORTD = PORTD & Bxxxxxx11; aby ste si nepokazili sériovú komunikáciu.

Použitie rýchleho digitalWrite() s priamou manipuláciou s portom je skutočne užitočným vylepšením, keď ho potrebujete. Len sa uistite, že viete, čo robíte

Prepíšme klasický príklad Blink LED pomocou vstavanej LED na kolíku 13.

Na zapnutie LED nastavíme pin 13 na HIGH s PORTB = PORTB | B00100000;. Tým sa nastaví iba stav kolíka 13 a ostatné sa nechajú v aktuálnom stave. Na vypnutie LED nastavíme pin 13 na LOW s PORTB = PORTB & B11011111;.

Všetky ostatné kolíky si opäť zachovajú svoj stav. Použitie priamej manipulácie s portom tu možno nie je dobrý nápad, pretože aplikácia nevyžaduje vysoký výkon. Použitie digitalWrite() pre takúto jednoduchú aplikáciu by bolo vhodnejšie. Ak teraz potrebujete zvýšiť frekvenciu alebo robiť veľa iných vecí súčasne (multitasking), možno budete musieť v určitom bode optimalizovať svoj kód, čo by sa mohlo hodiť.

Teraz môžete na svojich Arduino programoch napísať rýchly digitalWrite(). Tento tutoriál vám tiež poskytol úvod do priamej manipulácie s portami. Ako postupujete s Arduino, je dobrým zvykom pokúsiť sa nájsť to, čo sa skrýva za maskou štandardných funkcií Arduina. To vám umožní lepšie porozumieť a pomôže vám to napredovať rýchlejšie, najmä ak v budúcnosti plánujete písať kód pre iné mikrokontroléry.

Ak chcete ísť s týmto tutoriálom ešte ďalej, môžete tiež optimalizovať funkciu pinMode() s priamou manipuláciou s portom, ale zvyčajne režim pinu zostane dlhý čas rovnaký. Takže kompromis medzi „šancou pokaziť veci“ a „vyššou rýchlosťou“ tu nie je dobrý.

Pokračujte v používaní pinMode() vo funkcii setup() a v ​​prípade potreby optimalizujte digitalWrite().


Pridaj komentár

Vaša e-mailová adresa nebude zverejnená. Vyžadované polia sú označené *

Nemôžete kopírovať obsah tejto stránky