Digitális I/O
A fejezet tartalma:1. Digitális ki- és bemenetek kezelése
- DigitalOut
- DigitalIn
- Mintapélda: LED vezérlése nyomógombbal (led_button)
- DigitalInOut
- Mintapélda: LED villogtatása egy kicsit másképp (ledblink_other_way)
- BusOut
- Mintapélda: RGB LED kezelése BusOut
használatával (busout_rgbled)
- BusIn
- BusInOut
- PortOut
- Mintapélda:
LED-ek villogtatása PortOut használatával (portout_ledblink)
- PortIn
- PortInOut
Az alábbiakban az mbed API (alkalmazásprogramózói interfész) által a digitális ki- és bemenetek kezelésre szolgáló objektumosztályait tekintjük át.
- Egyetlen ki/bemenet kezelése: DigitalIn, DigitalOut, DigitalInOut
- Egy porthoz tartozó ki/bemenetek csoportos kezelése: PortIn, PortOut, PortInOut
- Tetszőleges ki/bemenetek csoportos kezelése: BusIn, BusOut, BusInOut
1. Digitális ki- és bemenetek kezelése
A digitális be- és kimenetek kezelésére az mbed API a DigitalIn, DigitalOut és DigitalInOut komponenseket nyújtja.DigitalOut
A DigitalOut komponens általános célú digitális kimenetek konfigurálására és kezelésére szolgál. A DigitalOut komponens előfordulása programunkban létrehozza a DigitalOut nevű C++ objektumosztályt, amely az alábbi táblázatban látható tagfüggvényekkel rendelkezik.Függvény |
Használat |
---|---|
DigitalOut
név(pin) |
Létrehoz egy "név" nevű DigitalOut objektumot és a pin
paraméterrel megadott kimenethez rendeli |
write(data) |
A kimenet beállítása 0 vagy
1 állapotba |
read() |
Az int típusú visszatérési érték
a kimenet állapotát adja meg (0 vagy 1) |
operator = |
Rövidített alak write(data) helyett |
operator int() |
Rövidített alak read() helyett |
Megjegyzés: A konstruktor függvény hívásakor opcionálisan a kimenet kezdeti állapotát is megadhatjuk második paraméreként. Szintaxis: DigitalOut név(pin,állapot).
A write() és read() tagfüggvények segítségével a kimenetre írhatunk vagy annak állapotát olvashatjuk. Ezek a létrehozott objektum tagfüggvényei, tehát a formátumuk myled.write(), illetve myled.read(). Használhatjuk azonban a létrehozott myled objektumra a táblázatban feltüntetett egyszerűsített módokat amelyek az értékadás műveletre ( = ) alkalmazhatók. Így tehát írhatjuk azt is, hogy:
myled = 1;
Ennek hatására nem csupán az objektum belső változójában tárolt érték
változik meg, hanem az érték megjelenik a az objektumhoz rendelt
kimeneten is.Emlékeztetőül nézzük meg mégegyszer a test01/main.cpp program listáját, s figyeljük meg benne a program szerkezét, az #include, main(), while() és a DigitalOut elemek használatát!
1. lista: A test01/main.cpp program listája
#include "mbed.h"
DigitalOut myled(LED1);
int main() {
while(1) {
myled = 1;
wait(0.2);
myled = 0;
wait(0.2);
}
}
A DigitalOut
használhatával kimenetként konfigurálhatjuk mikrovezérlőnk mindazon
kivezetéseit, amely az alábbi ábrán világoskék címkével van
megjelőölve,
továbbá a kártyára épített RGB LED-ekhez tartozó kivezetéseket is (LED_RED, LED_GREEN, LED_BLUE, vagy
más néven LED1, LED2, LED3, LED4).Megjegyzés: A LED1...LED4 elnevezések csupán az eredeti LPC1768 alapú mbed kártyával való szoftver kompatilitás kedvéért vannak definiálva, de a FRDM-KL25Z kártya esetében LED1 valójában a vörös, LED2 a zöld, LED3 és LED4 pedig egyaránt a kék RGB színkomponenst vezérli.
1.
ábra: A kék címkével megjelölt kivezetések kimenetként definiálhatók a
DigitalOut interfésszel
DigitalIn
A DigitalIn komponens általános célú digitális bemenetek konfigurálására és kezelésére szolgál. A DigitalIn komponens előfordulása programunkban létrehozza a DigitalIn nevű C++ objektumosztályt, amely az alábbi táblázatban látható tagfüggvényekkel rendelkezik.Függvény |
Használat |
---|---|
DigitalIn
név(pin) |
Létrehoz egy "név" nevű
objektumot, amelyet a "pin" bemenethez rendel |
read() |
Az objektumhoz rendelt bemenet
állapotának beolvasása (0 vagy 1) |
mode() |
Az objektumhoz rendelt bemenet
üzemmódjának beállítása (PullUp,
PullNone) |
operator
int() |
Rövidített alak read() helyett |
A mode() taggfüggvény segítségével a bemenet üzemmódja állítható be. Freescale Kinetis KL25Z mikrovezérlők esetén csak a PullUp, PullNone módok állíthatók be, a PullDown és OpenDrain módok itt nem definiáltak.
A read() tagfüggvény segítségével a a bemenet állapotát olvashatjuk be (0 vagy 1 állapot). Használhatjuk azonban helyette a táblázatban feltüntetett egyszerűsített módot is.
Megjegyzés: A konstruktor függvény hívásakor opcionálisan a kezdeti üzemmód beállítását is megadhatjuk második paraméreként. Szintaxis: DigitalIn név(pin,mód).
Mintapélda: LED vezérlése nyomógombbal
Az alábbi led_button nevű programban belső felhúzással ellátott digitális bemenetnek állítjuk a D3 (PTA12) bemenetet. A bemenet és a föld közé majd egy nyomógombot kell kötni a vezérléshez. Digitális kimenetnek állítjuk a LED1 (PTB18) kimenetet - ehhez a kivezetéshet van kötve a kártyára szerelt RGB LED vörös LED-jének a katódja. A főprogram végtelen ciklusában beolvassuk a nyomógombbal vezérlelt bemenet állapotát és ennek megfelelően állítjuk be a LED1 kimenentet. Amikor a nyomógomb le van nyomva, a LED világít.Hardver követelmények:
- FRDM-KL25Z kártya
- A D3 (PTA12) bemenet és a GND közé egy nyomógombot kell kötni az alábbi ábra szerint.
2. ábra: A nyomógomb bekötése a led_button programhoz
2. lista: A led_button/main.cpp program listája
#include "mbed.h"
DigitalIn mybutton(D3,PullUp);
DigitalOut myled(LED_RED);
int main()
{
while (true) {
myled = mybutton;
wait_ms(20);
}
}
Vegyük észre, hogy a DigitalIn konstruktor meghívásánál egyúttal a bemenet üzemmódját is megadjuk a második paraméter megadásánál. A PullUp paraméter belső felhúzást jelent, azaz a szabadon hagyott bemenet fixen magas szintre lesz húzva. A D3 bemenet és a GND közé kötött nyomógomb zárásakor pedig alacsony szintre húzzuk a bemeneti szintet.
DigitalInOut
A DigitalInOut komponens kétirányú digitális be/kimenetek konfigurálására és kezelésére szolgál. A DigitalIn komponens előfordulása programunkban létrehozza a DigitalInOut nevű C++ objektumosztályt, amely az alábbi táblázatban látható tagfüggvényekkel rendelkezik.Függvény |
Használat |
---|---|
DigitalInOut
név(pin) |
Létrehoz egy "név" nevű
objektumot, amelyet a "pin" kivezetéshez rendel |
input() |
Bemenetre állítja át a kivezetést |
output() |
Kimenetre állítja át a kivezetést |
write(data) |
A kimenet beállítása 0 vagy
1 állapotba |
read() |
Az objektumhoz rendelt bemenet
állapotának beolvasása (0 vagy 1) |
mode() |
Az objektumhoz rendelt bemenet
üzemmódjának beállítása (PullUp,
PullNone) |
operator
= |
Rövidített alak write(data)
helyett |
operator
int() |
Rövidített alak read() helyett |
Mintapélda: LED villogtatása egy kicsit másképp
Az alábbi ledblink_other_way
nevű programban egy kicsit szokatlan módon villogtatjuk a FRDM-KL25Z
kártyán a zöld LED-et. A LED_GREEN
(PTB19)
kivezetést kétirányú digitális ki/bemenetként konfiguráljuk.
Kimenetnek kapcsolva '0'-ra állítjuk - ekkor a LED világít,
mivel a katódja van a PTB19 lábra kötve, tehát lehúzásra gyullad ki.
Némi várakozás után bemenetre állítjuk a LED_GREEN (PTB19)
kivezetést. Ekkor a LED kialszik, mert a bemeneti módban
nagyimpedanciás (tri-state) állapotba kerül, így megszűnik a lehúzás a
LED katódján. Ebben a kikapcsolt állapotban is várakozunk 0.2 s-ig,
majd végtelen ciklusban felváltva ismételjük a kimenetre, illetve
bemenetre állítást. Hardver követelmények:
- FRDM-KL25Z kártya
#include "mbed.h"
DigitalInOut myled(LED_GREEN);
int main() {
while(1) {
myled.output();
myled = 0;
wait(0.2);
myled.input();
wait(0.2);
}
}
2. Digitális ki- vagy bemenetek csoportos kezelése
Néha kényelmesebb a programot megírni úgy, ha több digitális ki- vagy bemenetet összefoghatunk egy bitcsoporttá és egy értékadással állíthatjuk be azokat. A digitális ki- vagy bemenetek csoportos kezelésére az mbed API a BusOut, BusIn és BusInOut komponenseket nyújtja.BusOut
A BusOut objektumosztály, melynek segítségével legfeljebb 16 kimenetet foghatunk össze egyetlen egységgé. A BusOut nevű C++ objektumosztály az alábbi táblázatban látható tagfüggvényekkel rendelkezik.Függvény |
Használat |
---|---|
BusOut
név(pin1,pin2,...) |
Létrehoz egy "név" nevű BusOut objektumot melynek bitjeit rendre a pin1, pin2,... paraméterekkel megadott kimenetekhez rendeli. |
write(data) |
A kimenetek beállítása a 'data'
bitjeivel megadott állapotba |
read() |
Az int típusú visszatérési érték
bitjei a kimenetek állapotát adják meg |
operator = |
Rövidített alak write(data) helyett |
operator int() |
Rövidített alak read() helyett |
4. lista: Részletek BusOut.cpp forráskódjából
#include "BusOut.h"
BusOut::BusOut(PinName p0, PinName p1, PinName p2, ... , PinName p15) {
PinName pins[16] = {p0, p1, p2, ..., p15};
_nc_mask = 0;
for (int i=0; i<16; i++) {
_pin[i] = (pins[i] != NC) ? new DigitalOut(pins[i]) : 0;
if (pins[i] != NC) {
_nc_mask |= (1 << i);
}
}
}
void BusOut::write(int value) {
for (int i=0; i<16; i++) {
if (_pin[i] != 0) {
_pin[i]->write((value >> i) & 1);
}
}
}
int BusOut::read() {
int v = 0;
for (int i=0; i<16; i++) {
if (_pin[i] != 0) {
v |= _pin[i]->read() << i;
}
}
return v;
}
Mintapélda: RGB LED kezelése BusOut használatával
Az alábbi mintaprogramban a FRDM-KL25Z kártyára szerelt RGB LED kivezetéseit fogjuk egy egységbe rgbled néven, hogy egyetlen értékadással beállíthassuk mindhárom színkomponens '0' vagy '1' állapotát. A közös anódú RGB LED negatív logikája miatt ('0' kimenetnél világít az adott színkomponens) a programban invertáltuk a biteket (rgbled = 7-i;), hogy a szokásos sorrenben jelenjenek meg a színek: sötét, vörös, zöld, sárga, kék, magenta, cián, fehér. Természtesen invertálás nélkül (rgbled = i;) is működne a program, csak a színek fordított sorrendben jelennének meg.Hardver követelmények:
- FRDM-KL25Z kártya
#include "mbed.h"
BusOut rgbled(LED_RED,LED_GREEN,LED_BLUE);
int main()
{
while (true) {
for(int i=0; i<8; i++) {
rgbled = 7-i;
wait(0.5);
}
}
}
BusIn
A BusIn komponens általános célú digitális bemenetek egyetlen objektumban összefogott konfigurálására és kezelésére szolgál. A BusIn objektumosztály használata nagymértékben megegyezik a DigitalIn objektumosztályéval, azzal a különbséggel, hogy egynél több bemenetet kezelünk vele. A BusIn nevű C++ objektumosztály az alábbi táblázatban látható tagfüggvényekkel rendelkezik.Függvény |
Használat |
---|---|
BusIn
név(pin1,pin2,...) |
Létrehoz egy "név" nevű BusIn objektumot melynek
bitjeit rendre a pin1, pin2,...
paraméterekkel megadott (legfeljebb 16 db) bemenetekhez rendeli |
read() |
Az int típusú visszatérési érték bitjei a hozzájuk rendelt kimenetek állapotát adják meg |
mode(pull) |
A BusIn objektumhoz rendelt mindegyik
bemenet
üzemmódját egységesen beállítja a pull
paraméterrel megadott üzemmódba (esetünkben PullUp vagy
PullNone mód használható) |
mask() |
A visszatérési érték bitjei az
adott sorszámú bemenet definiáltságát jelzik (0: nem definiált, 1:
definiált). Például BusIn
buttons(D3,D4); megadása után buttons.mask()
visszatérési értéke 3 lesz. |
operator
int() |
Rövidített alak read() helyett |
operator[index] |
A BusIn objektumhoz rendelt bemenetek
közül az index sorszámú
bemenet állapotának beolvasása (0 vagy 1) |
Felhasználási ötlet
A BusIn objektumosztály jólhasználható egy kapcsolósoron beállított bináris szám beolvasására, amivel a programban valamit vezérlhetünk vagy kiválaszthatunk (pl. dallamcsengőn a dallamot).Az alábbi rajz szerint bekötött kapcsolósor esetén ( ahol a kapcsolók rendre a D3, D4, D5, D6 bemenetekre csatlakoznak - bár itt jegyezzük meg, hogy nem követelmény, hoyg egymás melletti bemeneteket használjunk!) például így hozhatjuk létre a myswitch nevű BusIn típusú objektumot:
BusIn myswitch(D3, D4, D5, D6);
A kapcsolósoron beállított értéket pedig így olvashatjuk be:
int state = myswitch.read();
3.
ábra: Kapcsolósor csatlakoztatása
a FRDM-KL25Z kártyához
a FRDM-KL25Z kártyához
BusInOut
A BusInOut komponens általános célú kétirányú digitális ki/bemenetek egyetlen objektumban összefogott konfigurálására és kezelésére szolgál. A BusInOut objektumosztály használata nagymértékben megegyezik a DigitalInOut objektumosztályéval, azzal a különbséggel, hogy egynél több bemenetet kezelünk vele. A BusInOut nevű C++ objektumosztály az alábbi táblázatban látható tagfüggvényekkel rendelkezik.Függvény |
Használat |
---|---|
BusInOut
név(pin1,pin2,...) |
Létrehoz egy "név" nevű BusInOut objektumot melynek
bitjeit rendre a pin1, pin2,...
paraméterekkel megadott (legfeljebb 16 db) kivezetésekhez rendeli |
input() |
Bemenetre állítja át az
objektumhoz rendelt kivezetéseket |
read() |
Az int típusú visszatérési érték bitjei a hozzájuk rendelt kivezetések állapotát adják meg |
mode(pull) |
A BusInOut objektumhoz rendelt
mindegyik bemenet
üzemmódját egységesen beállítja a pull
paraméterrel megadott üzemmódba (esetünkben PullUp vagy
PullNone mód használható) |
output() | Kimenetre állítja át az objektumhoz rendelt kivezetéseket |
write(data) |
A kimenetek beállítása a data paraméter bitjeivel megadott állapotba |
mask() |
A visszatérési érték bitjei az
adott sorszámú bemenet definiáltságát jelzik (0: nem definiált, 1:
definiált). Például BusIn
buttons(D3,D4); megadása után buttons.mask()
visszatérési értéke 3 lesz. |
operator
= data |
Rövidített alak write(data) helyett |
operator
int() |
Rövidített alak read() helyett |
operator[index] |
A BusIn objektumhoz rendelt bemenetek
közül az index sorszámú
bemenet állapotának beolvasása (0 vagy 1) |
- Egy BusInOut objektumhoz rendelt kivezetések adatáramlási iránya csak együttesen változtatható (vagy mindegyik kimenet, vagy mindegyik bemenet).
- Egy BusInOut objektumhoz rendelt bemenetek üzemmódja csak együttesen változtatható: vagy mindegyik felhúzott bemenet (PullUp mód), vagy egyik sem (PullNone mód).
3. Egy porthoz tartozó digitális ki- vagy bemenetek csoportos kezelése
Az egy porthoz tartozó több digitális ki- vagy bemenetet csoportos kezelésére az mbed API a PortOut, PortIn és PortInOut komponenseket nyújtja.PortOut
A PortOut interfész arra szolgál, hogy egy I/O portot, vagy annak valamelyik bitcsoportját egy objektumként kezelhessük és egyetlen utasítással írhassuk/olvashassuk. Ez így lényegesen gyorsabb és hatékonyabb, mint a BusOut használata, de kevésbé flexibilis, mert csak az egy fizikai porthoz tartozó kivezetéseket foghatjuk vele össze. A konstruktor hívásakor megadhatunk egy bitmaszkot, amelyikkel kijelöljük, hogy a megnevezett port mely bitjei tartoznak a létrehozott objektum példányhoz. A PortOut nevű C++ objektumosztály az alábbi táblázatban látható tagfüggvényekkel rendelkezik.Függvény |
Használat |
---|---|
PortOut
név(port,mask) |
Létrehoz egy "név" nevű PortOut objektumot melyhez a megadott port-ot rendeli (PortA, PortB,...) és amelynek csak a mask-kal megadott bitjeit akarjuk írni. |
write(data) |
A kimenetek beállítása a 'data'
bitjeivel megadott állapotba |
read() |
Az int típusú visszatérési érték
bitjei a kimenetek állapotát adják meg |
operator = |
Rövidített alak write(data) helyett |
operator int() |
Rövidített alak read() helyett |
Mintapélda: LED-ek villogtatása PortOut használatával
Az alábbi mintaprogramban a FRDM-KL25Zkártyára szerelt RGB LED piros és zöld LED-jét felváltva villogtatjuk. A közös anódú RGB LED-nek csak ez a két kivezetése tartozik azonos porthoz (PortB 18. és 19. bitek). Ezeket a PortOut segítségével egyetlen objektumba foglaljuk, így a színeket egyetlen értékadással átbillenthetjük.Hardver követelmények:
- FRDM-KL25Z kártya
#include "mbed.h"
#define LED_MASK 0x000C0000 //bit 18 és bit 19
#define GREEN_MASK 0x00080000 //bit 19: LED_GREEN
#define RED_MASK 0x00040000 //bit 18: LED_RED
PortOut ledport(PortB, LED_MASK);
int main() {
while(1) {
ledport = RED_MASK;
wait(0.5);
ledport = GREEN_MASK;
wait(0.5);
}
}
A PortOut konstruktor
meghívásakor PortB és a LED_MASK konstans jelölik ki a PTB18 és PTB19 kimeneteket, amelyeket
összefogva ledport néven
érhetünk el. A LED_MASK mint
bitmaszk megadása azt is eredményezi, hogy a későbbi értékadásoknál
csak ezek a bitek módosulnak. Például a ledport
= 0; értékadás tehát nem azt jelenti, hogy PortB minden bitjét töröljük, hanem
csupán azt, hogy a 18. és 19. bitjét 0-ba állítjuk. Megjegyzés: Az RGB LED bekötése (közös anódú) miatt a portbeállítások fordítva működnek. Amikor például a RED_MASK értéket adjuk ét ledport-nak, valójában a vörös LED alszik ki és a zöld LED gyullad fel, és viszont.
PortIn
A PortIn interfész arra szolgál, hogy egy I/O portot, vagy annak valamelyik bitcsoportját egy objektumként kezelhessük és egyetlen utasítással olvashassuk. Ez így lényegesen gyorsabb és hatékonyabb, mint a BusIn használata, de kevésbé flexibilis, mert csak az egy fizikai porthoz tartozó kivezetéseket foghatjuk vele össze. A konstruktor hívásakor megadhatunk egy bitmaszkot, amelyikkel kijelöljük, hogy a megnevezett port mely bitjei tartoznak a létrehozott objektum példányhoz. A PortIn nevű C++ objektumosztály az alábbi táblázatban látható tagfüggvényekkel rendelkezik.Függvény |
Használat |
---|---|
PortIn
név(port,mask) |
Létrehoz egy "név" nevű PortIn objektumot melyhez a megadott port-ot rendeli (PortA, PortB,...) és amelynek csak a mask-kal megadott bitjeit akarjuk olvasni. |
mode(pull) |
A bemenetek módjának beállítása (pull paraméter PullUp vagy PullNone) |
read() |
Az int típusú visszatérési érték
megfelelő bitjei a hozzájuk tartozó bemenetek állapotát adják meg |
operator int() |
Rövidített alak read() helyett |
PortInOut
A PortInOut interfész arra szolgál, hogy egy I/O portot, vagy annak valamelyik bitcsoportját egy objektumként kezelhessük és egyetlen utasítással írhassuk/olvashassuk. Ez így lényegesen gyorsabb és hatékonyabb, mint a BusInOut használata, de kevésbé flexibilis, mert csak az egy fizikai porthoz tartozó kivezetéseket foghatjuk vele össze. A konstruktor hívásakor megadhatunk egy bitmaszkot, amelyikkel kijelöljük, hogy a megnevezett port mely bitjei tartoznak a létrehozott objektum példányhoz. A PortInOut nevű C++ objektumosztály az alábbi táblázatban látható tagfüggvényekkel rendelkezik.Függvény |
Használat |
---|---|
PortInOut
név(port, mask) |
Létrehoz egy "név" nevű PortInOut objektumot melyhez a megadott port-ot rendeli (PortA, PortB,...) és amelynek csak a mask-kal megadott bitjeit akarjuk írni, vagy olvasni. |
input() |
Bemenetre állítja át az
objektumhoz rendelt kivezetéseket |
read() |
Az int típusú visszatérési érték megfelelő bitjei a hozzájuk rendelt kivezetések állapotát adják meg |
mode(pull) |
A PortInOut objektumhoz rendelt
mindegyik bemenet
üzemmódját egységesen beállítja a pull
paraméterrel megadott üzemmódba (esetünkben PullUp vagy
PullNone mód használható) |
output() | Kimenetre állítja át az objektumhoz rendelt kivezetéseket |
write(data) |
A kimenetek beállítása a data paraméter bitjeivel megadott állapotba |
operator
= data |
Rövidített alak write(data) helyett |
operator
int() |
Rövidített alak read() helyett |
- Egy PortInOut objektumhoz rendelt kivezetések adatáramlási iránya csak együttesen változtatható (vagy mindegyik kimenet, vagy mindegyik bemenet).
- Egy PortInOut objektumhoz rendelt bemenetek üzemmódja csak együttesen változtatható: vagy mindegyik felhúzott bemenet (PullUp mód), vagy egyik sem (PullNone mód).