Vaša IP adresa: 3.137.203.53
Počet návštev: 42605

Lekcia 1: Vstupno-výstupné porty

Mikrontrolér (MCU) ATmega328P obsahuje tri vstupno/výstupné porty: PORTB, PORTC a PORTD. Portom môžeme rozumieť skupinu vývodov, ktoré sú dostupné z vonkajšej strany MCU. Každý z portov má 8 bitov (8 vývodov). Každý z vývodov môžeme nastaviť ako vstupný alebo výstupný, prípadne môže plniť nejakú špecifickú funkciu ako napr. komunikačný vývod rozhrania UART. Na obrázku nižšie je ekvivalentná schéma zapojenia vývodu. Každý vývod obsahuje ochranné diódy a nastaviteľný pull-up rezistor.

Ekvivalentná schéma I/O vývodu. Ekvivalentná schéma I/O vývodu.

Na prácu s vstupno/výstupnými portami slúžia tri registre: PORTx (Data Register), DDRx (Data Direction Register) a PINx (Port Input Pins), kde x reprezentuje písmeno portu, t.j. B, C alebo D. Registre PORTx a DDRx umožňujú čítanie a zápis jednotlivých bitov, register PINx je určený iba na čítanie. Zápis do registra PINx spôsobí zmenu hodnoty zodpovedajúceho bitu v dátovom registri PORTx.

Konfigurácia vývodov

Register DDRx slúži na nastavenie „smeru“ daného vývodu, t.j. či je vývod vstupný alebo výstupný. Jednotlivé bity tohto registra sú označené ako DDxn, kde n je poradové číslo daného bitu v registri DDRx. Ak je hodnota bitu DDxn nastavená na logickú jednotku, tak daný vývod n bude nakonfigurovaný ako výstupný. Naopak, ak je hodnota bitu nastavená na logickú nulu, tak je vývod n konfigurovaný ako vstupný.

V prípade zápisu do registra PORTx môžu nastať dve rôzne situácie vzhľadom na stav príslušného registra DDRx:

  1. V prípade, že je vývod portu nastavený ako výstupný (DDxn=log.1), tak zápisom logickej jednotky na príslušný bit dátového registra (PORTxn=log.1) dochádza k nastaveniu logickej jednotky (vysokej úrovne napätia) na príslušnom vývode. V prípade zápisu logickej nuly (PORTxn=log.0) dochádza k nastaveniu logickej nuly (nízkej hodnote napätia) na danom vývode.
  2. V prípade, že je vývod portu nastavený ako vstupný (DDxn=log.0), tak zápisom logickej jednotky na príslušný bit dátového registra (PORTxn=log.1) dochádza k aktivácii pull-up rezistora na danom vývode. V prípade, že je bit dátového registra nastavený na logickú nulu (PORTxn=log.0), tak je pull-up na danom vývode nezapojený.

Stav daného vývodu je možné zistiť čítaním bitu vstupného registra PINxn bez ohľadu na nastavenie bitu DDxn v registri DDRx. Zápis logickej jednotky na bit PINxn spôsobuje zmenu hodnoty bitu PORTxn bez ohľadu na stav bitu DDxn.

Dôležité registre

Nižšie sú uvedené všetky registre, ktoré sa používajú na konfiguráciu vývodov. Pri popise registrov je v prvom riadku uvedené poradové číslo bitu. O riadok nižšie je uvedený názov daného bitu (orámovaná časť). Na ďalšom riadku je uvedené, či je bit určený na zápis (W), čítanie (R) alebo pre čítanie aj zápis (R/W). V poslednom riadku je uvedená prednastavená hodnota bitu (po resete alebo pripojení mikrokontroléra na napájanie). Väčšinou je táto hodnota nulová, ale môže byť aj jednotková, preto treba vždy túto hodnotu skontrolovať v datasheete! Ak ešte nemáte skúsenosti s nastavovaním alebo zisťovaním stavu bitov v registroch, tak prejdite na prácu s registrami a dozviete sa viac.


PORTB, DDRB, PINB - Registre slúžiace na konfiguráciu vstupno/výstupných vývodov portu B.

reg_PORTB.png reg_DDRB.png reg_PINB.png

PORTC, DDRC, PINC - Registre slúžiace na konfiguráciu vstupno/výstupných vývodov portu C.
Pozor! Port C má iba 7 vývodov!

reg_PORTC.png reg_DDRC.png reg_PINC.png

PORTD, DDRD, PIND - Registre slúžiace na konfiguráciu vstupno/výstupných vývodov portu D.

reg_PORTD.png reg_DDRD.png reg_PIND.png
Príklad č. 1 (Nastavenie výstupu)
Vytvorte jednoduchý program, ktorý bude blikať diódou LED0 s frekvenciou 1 Hz, t.j. 0,5 s bude LED0 zasvietená a 0,5 s zhasnutá. LED0 je pripojená na vývod PORTB0.

#define F_CPU 8000000UL //definícia frekvencie MCU, nutné pre knižnicu delay.h
#include <avr/io.h>
#include <util/delay.h>//knižnica pre _delay_ms()

int main(void)
{
DDRB=255;//dekadický zápis, všetky vývody portu B ako výstupné

while (1)
{
PORTB|=(1<<PORTB0);//zasvietenie LED0
_delay_ms(500);//pauza 500ms
PORTB&=~(1<<PORTB0);//zhasnutie LED0
_delay_ms(500);//pauza 500ms
}
}

Poznámka: Je potrebné si uvedomiť, že frekvencia MCU je vysoká (8 MHz) a bez pauzy by blikanie LED bolo veľmi rýchle a okom nepostrehnuteľné. Pri programovaní MCU treba vždy pamätať na vysokú rýchlosť vykonávaných inštrukcií!
Príklad č. 2 (Zistenie stavu vstupu)
Vytvorte jednoduchý program, ktorý po stlačení tlačidla S7 bude blikať diódou LED0 a po stlačení S6 bude blikať diódou LED1. LED0 je pripojená na vývod PORTB0, LED1 na vývod PORTB1, tlačidlo S7 na vývod PORTD7 a tlačidlo S6 na vývod PORTD6.

#define F_CPU 8000000UL //definícia frekvencie MCU, nutné pre knižnicu delay.h
#include <avr/io.h>
#include <util/delay.h>//knižnica pre _delay_ms()

int main(void)
{
DDRB=255;//všetky vývody portu B ako výstupné - LEDky
DDRD=0;//všetky vývody portu D ako vstupné - tlačidlá
PORTD=255;//zapnutie pull-up rezistorov na celom porte D, nestlačené tlačidlo má log. 1
uint8_t blikLED=0;//ak blikLED=0 -> bliká LED0; ak blikLED=1 -> bliká LED1

while (1)
{
//zistím, či bolo stlačené S7
if (PIND&(1<<PIND7)==0)//stlačením tlačidla privediem log. 0 na PIND7
{
blikLED=0;//bude blikať LED0
}
//zistím, či bolo stlačené S6
if (PIND&(1<<PIND6)==0)//stlačením tlačidla privediem log. 0 na >PIND6
{
blikLED=1;//bude blikať LED1
}

if (blikLED==0)
{
PORTB|=(1<<PORTB0);//zasvietenie LED0
_delay_ms(500);//pauza 500ms
PORTB&=~(1<<PORTB0);//zhasnutie LED0
_delay_ms(500);//pauza 500ms
}
else
{
PORTB|=(1<<PORTB1);//zasvietenie LED1
_delay_ms(500);//pauza 500ms
PORTB&=~(1<<PORTB1);//zhasnutie LED1
_delay_ms(500);//pauza 500ms
}
}
}

Poznámka 1: Zápis DDRD=0 nie je nutný, pretože prednastavená hodnota registra je 0 (pozri registre vyššie). Je však dobrým zvykom aj takomto prípade, hodnoty registrov nastaviť, aby boli zrejmé ich hodnoty z kódu a nemuseli sme sa spoliehať na prednastavené hodnoty v registroch.
Poznámka 2: Uvedený kód má svoje limitácie. Používa sa pauza 500ms pomocou funkcie _delay_ms(500). Táto funkcia blokuje vykonávanie ďalších inštrukcií MCU a preto nebude zaregistrované stlačenie tlačidla počas týchto relatívne dlhých páuz. Preto treba niekedy tlačidlo dlhšie podržať, aby sa zmenila blikajúca LED. Riešením je použitie externého prerušenia, o ktorom sa dozviete v lekcii 4.

Žiadne komentáre

Comments are closed

The comments for this content are closed.

O BB Pages

Web BB Pages je určený pre všetkých, ktorí sa zaujímajú o elektroniku a programovanie mikrokontrolérov. Web môže slúžiť ako výučbová platfoma pre programovanie mikrokontrolérov z rodiny AVR (napr. ATmega328P) v jazyku C.

Verím, že Vás web BB Pages zaujme a pomôže Vám zorientovať sa vo svete programovania mikrokontrolérov a elektroniky.

Autor webu: Branko Babušiak

Projekt Angry Bear

angry_bear_white.png
Výučbová platforma pre programovanie MCU v jazyku C. Platforma zahŕňa vývojovú dosku a výučbové lekcie, ktoré Vás postupne naučia programovať MCU v jazyku C. Navštívte stránku Angry Bear projekt.

Kontakt

kontakt@bbpages.eu