Nastavenie a nulovanie bitov v registri
Programovanie MCU je založené na nastavovaní registrov, ktoré plnia špecifickú funkciu. V prípade MCU z rodiny AVR, kam patrí aj ATmega328P, sú všetky registre 8-bitové. Nevyhnutnosťou je vedieť nastavovať logickú 1 alebo logickú 0 na príslušnom bite v registri. Nastavenie logickej jednotky označujeme ako nastavenie bitu, naopak, nastavenie logickej nuly nazývame nulovanie bitu. Každý register má svoju špecifickú adresu. Aby sa zjednodušil a sprehľadnil prístup k registrom, tak je k adrese registra priradený jedinečný názov. Napríklad register PORTB má adresu 0x05, ale pristupujeme k nemu pomocou jeho názvu PORTB. Názvy registrov sú pre MCU ATmega328P definované v hlavičkovom súbore iom328p.h. Spomínaný PORTB je v tomto súbore definovaný nasledovne:
#define PORTB _SFR_IO8(0x05)
Poznámka: SFR (Special Function Registers) sú špeciálne registre určené na riadenie periférnych obvodov MCU.
Podobne ako v prípade registrov, tak aj k jednotlivým bitom sú priradené jedinečné názvy. Nižšie sú názvy jednotlivých bitov pre register PORTB, ktoré sú uvedené v iom328p.h:
#define PORTB0 0
#define PORTB1 1
#define PORTB2 2
#define PORTB3 3
#define PORTB4 4
#define PORTB5 5
#define PORTB6 6
#define PORTB7 7
#define PORTB1 1
#define PORTB2 2
#define PORTB3 3
#define PORTB4 4
#define PORTB5 5
#define PORTB6 6
#define PORTB7 7
Na základe hore uvedených definícií bitov, už pri nastavení bitu nepoužívame poradové číslo bitu, ale jeho názov, čo výrazne zvýši prehľadnosť kódu.
Nastavenie bitov si ukážeme na konkrétnom príklade. Vývojová doska ABB má k portu PORTB pripojených 8 LED diód. LED0 je pripojená k pinu PORTB0 , LED1 je pipojená k pinu PORTB1 , atď. Predpokladajme, že celý PORTB je nastavený ako výstupný (DDRB=255) a cheme rozsvietiť LED3 (pripojená k PORTB3). Môžeme to urobiť nasledovne:
PORTB=0b00001000; //binárny zápis, neprehľadné
Prehľadnejší spôsob využíva bitový posun, z ktorého je hneď jasné, ktorý bit registra nastavujeme:
PORTB=(1<<PORTB3); //bitový posun vľavo s vyžitím názvu bitu
Zápis je v poriadku, ak chceme rozsvietiť LED3 a všetky ostatné zhasnúť. V prípade, že pôvodne svietila LED0, tak tú by sme príkazom PORTB=(1<<PORTB3) zhasli. Ak chceme rozsvietiť LED3 a zachovať pôvodný stav, tak sa zápis zmení nasledovne:
PORTB|=(1<<PORTB3); //bitový posun vľavo s využitím bitového súčtu (OR=|), zachová sa pôvodný stav ostatných bitov registra PORTB
Ak chceme nastaviť bit s názvom BIT v registri s názvom REG bez ovplyvnenia ostatných bitov, tak použijeme nasledovný zápis:
REG|=(1<<BIT); //nastavenie bitu v registri
Nulovanie bitu si tiež ukážeme na príklade. Predpokladajme, že máme rozsvietenú LED3 (pripojená na PORTB3), ktorú chceme zhasnúť:
PORTB=0b00001000; //svieti LED3
PORTB=0b00000000; //zhasneme LED3 pomocou binárneho zápisu, neprehľadné
PORTB=0b00000000; //zhasneme LED3 pomocou binárneho zápisu, neprehľadné
Hore uvedený zápis je nepraktický, pretože musíme poznať presnú polohu bitu, ktorý chceme znulovať a môžeme sa ľahko pomýliť. Ak by svietilo viac LED diód, tak pomocou zápisu dôjde k zhasnutiu všetkých, čo nechceme. Na zhasnutie diódy LED3 bez toho, aby sme ovplyvnili stav ostatných diód použijeme nasledujúci zápis:
PORTB&=~(1<<PORTB3); //bitový posun vľavo s využitím bitového súčinu (AND=&) a bitovej negácie (~), zachová sa pôvodný stav ostatných bitov registra PORTB
Vo všeobecnosti platí, že ak chceme nulovať bit s názvom BIT v registri s názvom REG bez ovplyvnenia ostatných bitov, tak použijeme nasledovný zápis:
REG&=~(1<<BIT); //nulovanie bitu v registri
Zistenie stavu bitu v registri
Na zistenie stavu bitu v registri sa používa takzvané bitové maskovanie pomocou logickej operácie AND (&). Zistenie stavu bitu si ukážeme na všeobecnom príklade. Register PIND slúži na zisťovanie stavu vývodu na porte D v prípade, že je daný bit registra nakonfigurovaný ako vstupný. Napríklad, ak chceme zistiť stav bitu PIND3, tak použijeme nasledujúci zápis:
if (PIND&(1<<PIND3)) {
//bit PIND3=1
} else {
//bit PIND3=0
}
//bit PIND3=1
} else {
//bit PIND3=0
}
Poďme si horeuvedený príklad rozobrať podrobnejšie. Výsledok bitového posunu (1<<PIND3) je v binárnej forme 0b0000 1000. Ak následne použijeme bitový súčin (&), tak v závislosti od stavu bitu PIND3 môžeme dostať dva rôzne výsledky podľa obrázka:

Podmienka if je splnená, ak výraz v zátvorke nadobúda kladnú nenulovú hodnotu a preto nie je potrebné špecifikovať, že sa musí jednať o hodnotu 8. Naopak, ak bit PIND3 = 0, tak bude výsledok bitovej operácie & vždy nulový a podmienka splnená nebude.
Vo všeobecnosti teda platí, že ak chceme zistiť hodnotu bitu s názvom BIT v registri s názvom REG, tak použijeme nasledovný zápis:
if (REG&(1<<BIT)) {
//bit BIT=1
} else {
//bit BIT=0
}
//bit BIT=1
} else {
//bit BIT=0
}