katedra Informatiky, VŠB-TU Ostrava, FEI, 2014 Návody do cvičení pro předmět Architektury počítačů a paralelních systémů Ing. Petr Olivka, email:
[email protected] Ing. David Seidl, Ph.D., email:
[email protected]
1
Část I
Programování mikropočítače
2
Kapitola 1
Teoretický úvod 1.1
Úvod k mikropočítačům
V oblasti mikroprocesorové techniky je dnes ve světě několik hlavních výrobců. Stejně jako u procesorů pro osobní počítače jsou hlavními světovými výrobci firmy AMD a Intel, tak v oblasti mikropočítačů se nejčastěji setkáme s mikropočítači PIC firmy Mikrochip a mikropočítači firmy Atmel. Samozřejmě že je možné setkat i s mikropočítači jiných výrobců, jako například Freescale (bývalá morotola) nebo Zilog. Výrobky prvních dvou výrobců jsou nejvíce využívané a s jejich mikropočítači je možné se setkat v mnoha profesionálních i amatérských konstrukcí. V první části cvičení z předmětu APPS budeme pracovat s mikropočítačem firmy Atmel ATmega32. Mikropočítač je součástka, která v sobě sdružuje jednak samotnou výpočetní jednotku CPU, paměťi RAM, programovou a datovou FLASH paměť a také několik vstupně/výstupních bran (pinů) a další periférie. ATmega je celá řada mikropočítačů firmy Atmel s procesorovým jádrem AVR, která je následníkem předešlé řady procesorů 8051. Mikropočítače AVR byly již od začátku navrhovány tak, aby pro ně bylo možné jednoduše vyvíjet programy v programovacím jazyku C, což je dnes dominantní způsob, jakým se pro mikrokontroléry vyvíjí software.
1.2
Atmel AVR mikropočítač ATmega32
Nedílnou součástí této dokumentace jsou i technické manuály výrobce, a to buď ve zkrácené verzi ATmega32-sum.pdf, nebo podrobný ATmega32.pdf. Podrobné informace o tomto procesoru je pak možné najít především na stránce výrobce http://www.atmel.com. 3
Pro práci ve cvičeních potřebujete znát jen základní informace. Procesor samotný obsahuje řadu periférií, jako jsou časovače, čítače, řadiče různých rozhraní, analogově digitální převodníky a pod. Pro práci ve cvičeních budete potřebovat ovládat vstupně výstupní porty procesoru. Použitý procesor ATmega32 je vybaven čtyřmi vstupně výstupními porty. Jsou označeny PA, PB, PC a PD. Každá periférie kterou procesor využívá, tedy i vstupně výstupní porty, je konfigurována pomocí registrů. Registr je místo v paměti procesoru. Každý registr má svou pevně definovanou adresu v adresním prostoru, která je v hlavičkových souborech vždy pro jednoduchost pojmenována konkrétním jménem. Každý ze čtyř portů procesoru se konfiguruje pomocí tří registrů. PORTx, DDRx, PINx kde x označuje konkrétní port A,B,C nebo D. ∙ DDRx - při zápisu log.1 na konkrétní bit tohoto registru určíme, že daný pin bude výstupní a opačně při log.0 bude vstupní. ∙ PORTx - Když je pin definován jako výstupní, určuje registr PORTx logickou hodnotu výstupu na konkrétním pinu. Když je některý pin definovaný jako vstupní a v registru PORTx je pro tento pin definována log. 1, je tento pin udržován v klidovém stavu na logické hodnotě 1. To je zařízeno připojením vnitřního tzv. pullup rezistoru. Při log.0 zapsané do registru PORTx je pull-up rezistor deaktivován. ∙ PINx - Pokud je port nastaven jako vstupní, lze pomocí registru PINx zjistit aktuální stav na příslušném pinu portu. Registr PINx je určen pouze pro čtení. Ve cvičeních se bude pracovat pouze s těmito registry.
1.3
Výukový vývojový AVR-KIT
Programy které se budou během cvičení vyvíjet, budou spouštěny na procesoru ATmega32, který je součástí výukového AVR-KITu. Výukový AVRKIT je deska plošných spojů, která je osazena samotným procesorem, dvěma paticema ZIF, čtyřmi tlačítky které jsou připojeny na PORTD procesortu, dvěma LED diodama taktéž připojenýma na PORTD procesoru a tlačítkem reset. Další součástky umístěné na desce plošných spojů jsou pomocné obvody, určené ke komunikaci s PC a programování procesoru ATmega32. Schéma AVR-KITu je na obrázku 1.1.
4
VCC
PA0 PA1 PA2 PA3 PA4 PA5 PA6 PA7
40 39 38 37 36 35 34 33
(T0/XCK)PB0 (T1)PB1 (AIN0/INT2)PB2 (AIN1/OC0)PB3 (SS)PB4 (MOSI)PB5 (MISO)PB6 (SCK)PB7
31 30 32
AGND AVCC AREF
(ADC0)PA0 (ADC1)PA1 (ADC2)PA2 (ADC3)PA3 (ADC4)PA4 (ADC5)PA5 (ADC6)PA6 (ADC7)PA7
9
RESET
GND
GND
1
2
PIND5 1
GND
VCC
R3
PD5 R2
PD4
R6
GND
VCC
PIND4 PIND3
2
PIND2
1
R5
R1
PD3
PD2
RESET
Sériová linka do PC
PD0 PD1
IC1
RESET
C0 C1 C2 C3 C4 C5 C6 C7 C8 C9 C10 C11
12
XTAL2
VCC
GND
13
XTAL1
VCC VCC GND GND
PD0 PD1 PD2 PD3 PD4 PD5 PD6 PD7
11 10
GND VCC
GND
ZIF-R
D0 D1 D2 D3 D4 D5 D6 D7 D8 D9 D10 D11
PC0 PC1 PC2 PC3 PC4 PC5 PC6 PC7
2
VCC
PD7
PB0 PB1 PB2 PB3 PB4 PB5 PB6 PB7
B0 B1 B2 B3 B4 B5 B6 B7 B8 B9 B10 B11
1 2 3 4 5 6 7 8
R4
A0 A1 A2 A3 A4 A5 A6 A7 A8 A9 A10 A11
PB0 PB1 PB2 PB3 PB4 PB5 PB6 PB7
(SCL)PC0 (SDA)PC1 (TCK)PC2 (TMS)PC3 (TDO)PC4 (TDI)PC5 (TOSC1)PC6 (TOSC2)PC7
VCC
VCC VCC GND GND
22 23 24 25 26 27 28 29
RESET
PA0 PA1 PA2 PA3 PA4 PA5 PA6 PA7
PC0 PC1 PC2 PC3 PC4 PC5 PC6 PC7
(RXD)PD0 (TXD)PD1 (INT0)PD2 (INT1)PD3 (OC1B)PD4 (OC1A)PD5 (ICP)PD6 (OC2)PD7
R7
GND
ZIF-L
14 15 16 17 18 19 20 21
PD6
VCC
AT-MEGA32 PD0 PD1 PD2 PD3 PD4 PD5 PD6 PD7
PIND6 1
GND
2
GND
PIND7 1
2
GND
.
Obrázek 1.1: Zapojení AVR-KITu V každém ze cvičení budete mít k AVR-KITu připojen modul, kterým se ke vstupně výstupním branám, připojí vždy jiné periférie. Bude se jednat o LED diody, segmentový LED displej, teploměr a expandér pro sběrnici I2 C, případně ještě další moduly. Konkrétní zapojení modulů ke vstupně výstupním portům procesoru je uvedeno v popisu každé úlohy.
1.3.1
Programování AVR-KITu
Pro programování výukového AVR-Kitu je určen program avrkit.exe. Program je součástí archívu avrkit.zip (viz dále) a je možné spustit s následujícími parametry:
5
>avrkit.exe -h Usage: AVRKIT [options] [file.hex] -h -d -e -l -n -s -t -v -x
show this help serial port device (def: ’COM1’) erase AVR flash only list available COM ports no terminal mode after programming show AVR flash only terminal mode only verify AVR flash memory only show HEX file only
Without options this program upload HEX file to AVR flash. Program očekává jako parametr HEX soubor, který obsahuje strojové instrukce programu pro mikroprocesor. AVT-KIT se v operačním systému jeví jako sériový port. Program avrkit.exe zadaný bez parametru posílá data na COM1. Je-li AVR-KIT připojen jako jiný sériový port, je možné ho definovat pomocí parametru -d. Dostupné sériové porty lze vylistovat pomocí parametru -l. Příklad nahrání testovacího programu demoleds.hex, za předpokladu že AVR-KIT se v systému jeví jako COM3, bude vypadat následovně: avrkit.exe -d COM3 demoleds.hex
1.3.2
Postup při programování mikropočítače AVR-KITu
Před započetím programování je nutné mikropočítač uvést do stavu kdy je ochoten přijímat nový program. Toho se docílí stlačením tlačítka PIND4, poté stlačením a uvolněním tlačítka RESET. Procesor se poté uvede do módu kdy očekává data z PC (aktivuje se tzv. BOOTLoader) a přijatá data zapisuje do programové paměti FLASH. Tento mód signalizuje mikropropočítač rozsvícenou LED diodou připojenou na PIND2. Poté co se program nahraje je nutné opět procesor restartovat stlačením a uvolněním tlačítka RESET. Procesor začne vykonávat nahraný program. Po ukončení programování procesoru programem avrkit.exe zůstane program aktivní a je připraven vypisovat data, které bude mikropočítač zapisovat na sériový port pomocí funkce printf. Nechcete-li tuto funkci programu avrkit.exe využívat je ji možné vypnou parametrem -n. Pro vyznavače nekomerčních operačních systémů je k dispozici i program avrkit.lin pro OS Linux. 6
1.4
Vývojové prostředí Atmel Studio
Pro vývoj software je na webových stránkách firmy Atmel volně k dispozici program Atmel Studio, který je určen pro OS Windows. S tímto plnohodnotným vývojovým prostředím je možné vyvíjet programy pro všechny procesory řady AVR. Program Atmel Studio využívá pro překlad volně šířený překladač pro mikropočítače AVR avr-gcc (je to varianta volně šířeného překladače gcc). Tento překladač je k dispozici nejen pro OS Windows ale i pro OS Linux. Od Atmel Studia můžete očekávat všechny pokročilé vlastnosti na které jste zvyklí z obdobných vývojových prostředí. Atmel Studio je založeno na základech MS Visual Studio. Pro práci ve cvičeních je pro vás připravena skupina projektů v archivu avr-kit.zip, která se v Atmel Studiu označuje jako „Solution“.
1.4.1
Obsah avr-kit.zip
Po rozbalení archívu vznikne adresář s následujícím obsahem: ./avrkit.exe ./avr-kit.avrsln ./avrkit ./leds ./lcd ./i2c ./demo
-> -> -> -> -> -> ->
Program pro programování AVR Kitu Skupina projektů pro Atmel Studio Adresář s knihovnou avrkit Adresář s projektem pro LED diody Adresář s projektem pro LCD displej Adresář s projektem pro sběrnici i2c Příklady pro jednotlivá cvičení
Obsah adresáře avrkit: ./avrkit.c ./avrkit.h
-> Zdrojový kód knihovny avrkit -> Hlavičkový soubor knihovny avrkit
Obsah adresáře leds: ./leds.avrgccproj ./main-leds.c ./Debug ./Release
-> -> -> ->
Projekt Atmel Studia Zdrojový kód programu i2c Adresář pro výstupní soubory Adresář pro výstupní soubory
7
Obsah adresáře lcd: ./lcd.avrgccproj ./main-lcd.c ./lcd-lib.c ./lcd-lib.h ./Debug ./Release
-> -> -> -> -> ->
Projekt Atmel Studia Zdrojový kód programu pro LCD Zdrojový kód funkcí pro LCD displej Hlavičkový soubor funkcí pro LCD Adresář pro výstupní soubory Adresář pro výstupní soubory
-> -> -> -> -> -> -> ->
Projekt Atmel Studia Zdrojový kód programu i2c Zdrojový kód funkcí pro sběrnici I2C Hlavičkový soubor funkcí pro I2C Funkce inicializace radiomodulu Prototyp funkce inicializace Adresář pro výstupní soubory Adresář pro výstupní soubory
Obsah adresáře i2c: ./i2c.avrgccproj ./main-i2c.c ./i2c-lib.c ./i2c-lib.h ./si4735-lib.c ./si4735-lib.h ./Debug ./Release
Obsah adresáře demo: ./demoleds.hex ./demo8x8.hex ./demoi2c.hex ./demolcd.hex
1.4.2
-> -> -> ->
Demo Demo Demo Demo
program program program program
pro pro pro pro
LEDky led displej sběrnici I2C LCD displej
Práce v Atmel Studiu
Po rozbalení souboru avr-kit.zip je ve vytvořené složce soubor avr-kit.avrsln, což je skupina projektů určená pro první část cvičení. Je možné ji otevřít pomocí menu File > Open > Projects/Solution, nebo kliknutím na ikonu. Po otevření skupiny projektů se v okně „Solution Explorer“ objeví složky (projekty) pro jednotlivá cvičení. Bude se zde taky vyskytovat soubor avrkit.c, což je soubor s funkcemi knihovny avrkit.h. Tento soubor prosím nijak neupravujte. Projekt lze přeložit pomocí Build > Build Solution, případně klávesou F7. Poté se ve složce Debug nebo Release daného projektu objeví HEX soubor, který je určený pro mikropočítač. To, zda jste v režimu Debug nebo Release se dá ovlivnit pomocí záložky v hlavní liště Atmel Studia. 8
1.5
Překladač AVR GCC - stručný přehled
Překladač AVR GCC je volně šířený překladač jazyka C. Tento překladač využívá volně šířené knihovny jazyka C AVR Libc. Jedná se o standardní překladač jazyka C a při psaní programů můžete využívat všechny základní programátorské konstrukce jazyka C. Tento překladač je standardně používaný překladač ve volně šířeném vývojovém prostředí Atmel Studio.
1.5.1
Datové typy
V programech můžete používat následující datové typy: ∙ signed char -128 ÷ 127 ∙ signed short, signed int -32768 ÷ 32767 ∙ signed long -2147483648 ÷ 2147483647 ∙ unsigned char 0 ÷ 255 ∙ unsigned short, unsigned int 0 ÷ 65535 ∙ unsigned long 0 ÷ 4294967295 Požadujeme-li typ bezznaménkový, musíme uvádět klíčové slovo unsigned. Pro znaménkové proměnné je slovo signed nepovinné.
1.5.2
Zápis čísel
Je možné použít následující zápisy čísel: Dekadický int i = 10578; char ch = -10; float f = 13.54; Hexadecimální int i = 0x12B7; char ch = 0xF1; Binární int i = 0b1101001010010110; char ch = 0b10001101;
9
Oktalový int i = 0737; char ch = 015;
Je potřeba si uvědomit, že 10 = 0xA = 0b1010 = 012. Jedná se o zápis jednoho čísla v různých číselných soustavách.
1.5.3
Aritmetické, logické a bitové operátory jazyka C
Aritmetické +, -, *, /, % První čtyři operátory viz základní škola. Operátor modulo % vrací zbytek po celočíselném dělení. Tedy 11 % 2 = 1, 13 % 5 = 3, 31 % 31 = 0. Zkrácený zápis aritmetických operátorů v jazyce C: x++, x--, x += x -= x *= x /= x %=
++x --x y y y y y
x x x x x x x
= = = = = = =
x x x x x x x
+ + * / %
1 1 y y y y y
Logické &&, ||, ! Logický součin lež && lež lež && pravda pravda && lež pravda && pravda
=> => => =>
Logický součet lež || lež lež || pravda pravda || lež pravda || pravda
lež lež lež pravda
Logická negace !lež => pravda !pravda => lež
Kde pravda je číslo nenulové a lež je číslo nula.
10
=> => => =>
lež pravda pravda pravda
Bitové &, |, ^, ~, <<, >> Bitový součin 0 & 0 => 0 0 & 1 => 0 1 & 0 => 0 1 & 1 => 1
Bitový součet 0 | 0 => 0 0 | 1 => 1 1 | 0 => 1 1 | 1 => 1
Bitový exclusive or 0 ^ 0 => 0 0 ^ 1 => 1 1 ^ 0 => 1 1 ^ 1 => 0
Bitová negace ~1 => 0 ~0 => 1
Bitový posun 0b01 << 1 => 0b10 0b10 >> 1 => 0b01
Příklady: 5 & 3 = 1 protože 0b101 & 5 | 3 = 7 protože 0b101 | 5 ^ 3 = 6 protože 0b101 ^ ~5 = 250 protože ~0b101 = je 5 osmi bitové
0b011 = 0b001 0b011 = 0b111 0b011 = 0b110 0b11111010, pokud bezznaménkové číslo
5 << 3 = 40 protože 0b101 << 3 = 0b101000 5 >> 3 = 0 protože 0b101 >> 3 = 0b000000
Zkrácený zápis logických operátorů v jazyce C: x x x x x
>>= y <<= y &= y |= y ^= y
x x x x x
= = = = =
x x x x x
>> y << y & y | y ^ y
11
Často dochází k záměně logických a bitových operátorů log. součtu a součinu. Příklad časté záměny: char x = 5; char y = 2; if(x && y) {...} //PRAVDA if(x & y)
1.5.4
{...} //LEŽ
Knihovna avr/io.h
V programech se vkládá jako hlavičkový soubor #include
. Tento hlavičkový soubor umožňuje použít všechny registry procesoru jako proměnné. Při překladu projektu se překladači uvede procesor pro který je program překládán a překladač dál definuje, který konkrétní hlavičkový soubor pro zvolený procesor se má do projektu vložit. Překladači předává tuto volbu Atmel Studio dle nastavení v projektu. Příklad programu, který nastaví port A jako výstupní a všechny piny nastaví na log.1: #include int main() { DDRA = 0xff; PORTA = 0xff; }
1.5.5
Knihovna avrkit.h
Tato knihovna je součástí vývojového kitu AVR-KIT. Obsahuje dvě funkce potřebné pro zastavení běhu programu na požadovaný čas. A dále funkci pro inicializaci AVR-KITu. Volání této funkce je nutné na začátku každého programu! Provede inicializaci zařízení a přesměruje textové výstupy na sériovou linku. Prototypy funkcí vypadají následovně: void avrkit_init( void ); void delay_ms( int ms ); void delay_01ms( int ms ); uchar read_butt( void );
// // // //
12
povinná inicializace AVR kitu zpoždění v milisekundách zpoždění v desetinách ms cteni stavu tlacitek, bity <4-7>
Ukázka použití je uvedena v příkladu programu následující podkapitoly.
1.5.6
Knihovna stdio.h
V programech se vkládá jako hlavičkový soubor #include <stdio.h>. Tento hlavičkový soubor umožňuje používat obvyklé funkce pro výstup (použitý vývojový KIT směřuje výstup těchto funkcí na sériovou linku, viz další kapitola). Příklad programu, který nastaví horní 4 piny portu D jako vstupní a bude pravidelně každou sekundu vypisovat stav připojených tlačítek AVRKITu. #include "avrkit.h" #include #include <stdio.h> int main() { avrkit_init(); DDRD = DDRD & 0x0F; while (1) { printf( "%03d %02x\n", read_butt(), read_butt() ); delay_ms( 1000 ); } }
13
Kapitola 2
Návody do cvičení 2.1 2.1.1
LED diody Zapojení LED na port mikropočítače
Na port mikropočítače je možno zapojit přímo LED diody. Dle schématu na obrázku 2.1 je vidět, že LED diody se aktivují vždy v úrovní logické 1. Aby proud protékající jednotlivými diodami nepřekročil přípustnou mez, LED0 PINC0 PINC1 PINC2 PINC3 PINC4 PINC5 PINC6 PINC7 LED7
Obrázek 2.1: Zapojení LED na port mikropočítače
14
1 0 1 0 1 0 1 0 1 0
0% 30% 50% 90% 100% T
0
2T
3T
t
Obrázek 2.2: Časový průběh signálů s různou střídou je každá dioda zapojena v sérii s ochranným odporem. Jednotlivé vývody PC0-PC7 odpovídají i v uvedeném pořadí osmi datovým bitům datového portu C mikropočítače.
2.1.2
Řízení jasu
Popis Úkolem je řízení jasu diod změnou střídy (duty cycle). Častěji je ale používán pojem pulsně šířková modulace (PWM - pulse wide modulation). Jde o měnící se poměr délky signálu a mezery při konstantní časové periodě. Vyjadřujeme jej v procentech. Na obrázku 2.2 je příklad několika takových signálů s odlišnou střídou. Příklady úkolů ve cvičení ∙ Rozsvítit každou diodu zadaným jasem, jednotlivé hodnoty stačí zadat do pole. ∙ Diody postupně rozsvítit a postupně zhasnout. Postupně se rozumí nejprve pomalu rozsvítit první, pak postupně druhou a první zůstává svítit, atd. A pak postupně pozhasínat. ∙ 4 a 4 diody se rozsvěcují a zhasínají současně. Buď prokládaně, nebo po čtveřicích.
15
Postup řešení ∙ Rozsvítit vybranou LED diodu. ∙ Rozblikat vybranou LED diodu se střídou 50%. ∙ Najít periodu 𝑇 = 1/𝑓 , tak aby nebylo blikání viditelné. ∙ Řídit jas jedné LED. ∙ Řídit jas dvou LED současně. Nebo zajistit postupné rozsvícení. Časovou periodu rozdělit po jedné 𝑚𝑠 a hledat místa, kdy se mění stavy LED diod. ∙ Dokončit zadání.
2.1.3
Skládání barev - RGB LED
Popis V počítačové technice se jako jedna metoda pro vytvoření libovolné barvy používá tzv. aditivní způsob míchání barev. Máme 3 základní barvy červenou, zelenou a modrou (RGB - red, green, blue). Pomocí těchto 3 základních barevných složek můžeme vytvořit libovolnou barvu z celého viditelného spektra. Pro míchání barev je nutno použít princip popsaný v předchozí kapitole o řízení jasu. Ve výsledné barvě je potřebné zastoupení každé základní barevné složky přímo úměrné zvolené střídě.
PINB0 PINB1 PINB2
PINB4 PINB5 PINB6
B G
RGB L
R
B G
RGB H
R
Obrázek 2.3: Zapojení RGB LED
16
Zapojení RGB LED je na obrázku 2.3. Jednotlivé barevné složky jsou připojeny na výstupy portu B. Dioda označená jako RBG L je připojena na dolní 4 bity a druhá, označená RGB H na horní bity. Příklady úkolů ve cvičení ∙ Rozsvítit jednotlivé základní barvy daným jasem. ∙ Plynulý přechod mezi dvěma základními barvami. ∙ Rozsvícení RGB LED barvou zadanou podle HTML standardu #RRGGBB ∙ Plynulý přechod mezi dvěma barvami podle HTML standardu. Postup řešení Postup programování stejný jako při řízení jasu.
2.1.4
Řízení frekvence blikání
Popis Úkolem je blikání diod s určitou frekvencí. Potřebná časová perioda je: 𝑇 = 1/𝑓 . Pozor! Tato perioda se musí rozdělit se střídou 50% na „svití/nesvítí“. Bude-li zvolená perioda použita pro svícení i zhasnutí, výsledná frekvence bude poloviční! Je to obvyklá chyba při programování! Příklady úkolů ve cvičení Podobné jako při řízení jasu, jen místo jasu se řídí frekvence. Postup řešení Hledat společný násobek všech potřebných frekvencí nelze. Jsou tedy dvě možnosti: můžeme mít tolik čítačů, jako je LED diod a po každé 𝑚𝑠 se každý čítač inkrementuje a kontroluje na přetečení. Nebo můžeme mít jeden „nekonečný“ čítač inkrementovaný opět po každé 𝑚𝑠 a pak celočíselným dělením tohoto čítače periodou pro každou LED dostaneme zbytky po dělení. Tento zbytek (modulo) bude pro každou LED nula nebo různý od nuly. Při nule nastane změna stavu příslušné LED (ideální je operace XOR, ale někdo raději provede OR/AND s vhodnou bitovou maskou). 17
První řešení umožňuje řídit i fázi, druhé je jednodušší. Způsobí ale drobnou asynchronnost při přetečení čítače, která je ale očima nepozorovatelná. Vybranou metodu řešení pak můžeme aplikovat v následujících krocích: ∙ Rozblikat jednu LED se zadanou frekvencí. ∙ Najít frekvenci, při která není blikání vidět. ∙ Rozblikat dvě diody, každou jinou frekvencí (ne celistvý násobek). ∙ Dokončit zadání.
18
2.2
Multiplexní řízení vícemístného displeje
Vícemístné LED a LCD displeje patří k základním zobrazovacím prvkům elektronických zařízení. Pro účely cvičení byly vybrány sedmiprvkové LED displeje. Zapojeno je osm těchto displejů (dále segmentů) vedle sebe. Zapojení osmi segmentů současně je zobrazeno v elektrickém schématu na obrázku 2.6. Jde o zapojení 64 LED (ve dvourozměrné matici 8 × 8). Zjednodušeně můžeme zapojení znázornit obrázkem 2.4 (podrobněji pak dále na obrázku 2.6). Podle obrázku 2.4 vybírá port B jeden s osmi segmentů. Port C pak vybírá LED v aktivovaném segmentu. Používáme kladnou řídící logiku a výběr segmentu i LED se provádí logickou úrovní 1 na příslušných vybraných pinech portů B a C.
PORT C LED A-G Segment 7
Segment 0 PORT B
Obrázek 2.4: Zjednodušené ovládání osmisegmentového displeje Rozložení a označení LED každého segmentu je na obrázku 2.5, včetně osmé LED označené jako DP - desetinná tečka (decimal point). A F
B G C
E
DP D
Obrázek 2.5: Rozmístění LED jednoho segmentového displeje Pro lepší pochopení principu činnosti uvádíme i přesnější elektrické schéma zapojení segmentů displeje na obrázku 2.6. Ze schématu je patrno několik důležitých technických informací:
19
SEGMENT 7 PINB7
PINC7 DP0
PINC6
G0
PINC5
F0
PINC4
E0
PINC3
D0
PINC2
C0
PINC1
B0
A0
DP1
G1
SEGMENT 1 PINB1
GND
F1
E1
D1
C1
B1
A1
DP7
G7
F7
E7
D7
C7
B7
A7
PINC0
.
SEGMENT 0 PINB0
GND
GND
Obrázek 2.6: Schéma zapojení osmi segmentů 1. Jednotlivé segmenty displeje A-G jsou připojeny na port C a jeho piny PC0-PC6. 2. Všechny LED jsou zapojeny se společnou katodou. Každá LED se tedy aktivuje pomocí logické úrovně 1 portu C. 3. Aktivní společná katoda každého segmentu 0-7 se vybírá tranzistorem NPN, jehož báze se aktivuje log. úrovní 1 pinu portu B v pořadí PB0PB7. 4. Není možné ovládat každou LED samostatně. Lze aktivovat jen LED pro vybraný segment. Chceme-li zobrazit informaci na více segmentech současně, musí se informace na jednotlivých segmentech střídat. Hovoříme tedy o tzv. časovém multiplexu.
Příklady úkolů ve cvičení ∙ Zobrazte aktuální datum v různých tvarech a přepínat mezi nimi tlačítkem. ∙ Zobrazte aktuální čas ve tvaru HH:MM:SS a blikajícími oddělovači. ∙ Zobrazte volitelný text do osmi znaků. ∙ Zobrazte „bežící“ text libovolné délky.
20
.
Postup řešení ∙ Nadefinujte si kombinaci LED tak, aby představovaly znaky nebo číslice. ∙ Ověřte na jednom vybraném segmentu, zda se znaky zobrazují správně. ∙ Zobrazte dva různé znaky na dvou segmentech současně. Je třeba využít znalost z předchozího cvičení, kdy lidské oko přestává vnímat blikání. Zobrazovací časovou periodu je pak potřeba rozdělit mezi dva segmenty. ∙ Zobrazte rozdílné znaky na všech osmi segmentech. ∙ Dokončete zadaný úkol.
21
2.3
LCD textový displej
Textové LCD displeje jsou v dnešní době součástí mnoha řídících, monitorovacích a diagnostických zařízení. Tyto LCD displeje se vyrábí jako hotové moduly v mnoha provedeních. Liší se počtem znaků na řádek a počtem řádků. Odlišné je také barevné provedení displejů a způsob podsvětlení. Pro ovládání těchto LCD displejů se vyrábí několik řadičů. Není se však třeba v praxi obávat roztříštěnosti programového ovládání. Výrobci těchto řadičů mezi sebou dodržují nepsaný standard pro jejich řízení. Nepatrné odchylky lze nalézt pouze při inicializaci LCD modulů. Pokud se tedy programátor seznámí s řízením jednoho LCD modulu, lze získané zkušenosti dále aplikovat i na LCD moduly s odlišným rozlišením, nebo moduly jiných výrobců. Pro cvičení v předmětu APPS byl vybrán LCD modul BC1602A se 16 znaky na řádek a dvěma řádky, podsvětlený pomocí žlutozelené LED. Výrobcem modulu je firma Bolymin a využívá řadič ST7066U firmy Sitronix. Fotografie celého modulu i s připojením na AVR-KIT je na obrázku 2.7. Nedílnou součástí tohoto textu jsou také datové listy výrobce LCD modulu - BC1602A.pdf, popisující podrobně celý modul, jeho konstrukci i ovládání. Pro práci ve cvičení budou potřeba zejména informace na straně 27 a 29.
Obrázek 2.7: LCD modul
22
2.3.1
Zapojení LCD modulu a popis komunikace
Zapojení LCD modulu je uvedeno na obrázku 2.8. Na schématu je vidět, že pro připojení LCD modulu slouží 16 pinů. Na obrázku 2.7 jsou tyto piny vidět nad horním okrajem černého rámečku. Pro přenos dat slouží 8 datových pinů D0 až D7. Tyto piny jsou připojeny přímo na port B mikropočítače Atmel. Pro řízení komunikace slouží piny R/W, RS a E. Pin R/W určuje směr komunikace. Pinem RS se rozlišuje, zda jsou LCD modulu předávána data, nebo příkazy. Třetí řídící pin E slouží pro synchronizaci přenosu dat. Podrobně je synchronní komunikace mezi procesorem a LCD modulem popsána v datových listech. Pro cvičení však není tuto komunikaci podrobně studovat. V přiložených zdrojových kódech jsou již připraveny pro komunikaci s LCD modulem 3 funkce. Budou popsány dále v textu. Kromě datových a řídících pinů je k modulu přivedeno napájení přes piny VDD a VSS. Kontrast LCD se ovládá pomocí pinu VO. Podsvětlení je zapojeno zcela odděleně od napájení řídícího obvodu přes piny BLK a BLA. BACKLIGHT C
LCD 2x16 BLK BLA D7 D6 D5 D4 D3 D2 D1 D0 E RW RS VO VDD VSS
16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1
L
PIND-7
RB T1
P
GND +5V
PINB-7 PINB-6 PINB-5 PINB-4 PINB-3 PINB-2 PINB-1 PINB-0 PINC-0 PINC-1 PINC-2
RKRK+ CONTRAST C
+5V
L P
RG R0 4k R1 2k
GND +5V
GND
R2 1k
GND PINA-0 PINA-1 PINA-2
Obrázek 2.8: Schéma zapojení LCD modulu
Ovládání podsvětlení a kontrastu Ze schématu LCD modulu 2.8 je vidět, že u zapojení podsvětlení i u pinu pro ovládání kontrastu, jsou zapojeny dvoupolohové přepínače. Tyto přepínače jsou na obrázku 2.7 označeny na horním a spodním okraji LCD modulu červenými kroužky. 23
Pokud je horní přepínač v poloze vlevo u nápisu BACKLIGHT, je podsvětlení trvale zapnuto. Chceme-li podsvětlení ovládat programově, je nutno tento přepínač přepnout směrem k nápisu PWM. Podsvětlení pak lze ovládat nejvyšším bitem portu D. Zápisem log. 1 na PIND7 se podsvětlení zapne a zápisem log. 0 vypne. Pomocí PWM tak můžeme ovládat intenzitu podsvětlení. Pro ovládání kontrastu jsou k dispozici také dvě možnosti. Pokud nevyžadujeme programové ovládání, stačí přepnout spodní přepínač do polohy CONTRAST a úroveň kontrastu bude dle pevně přednastavené hodnoty. Při přepnutí dolního přepínače do polohy D/A je možno kontrast ovládat programově. Jak je vidět ve schématu 2.8, úroveň kontrastu je možno ovládat pomocí jednoduchého D/A převodníku, realizovaného třemi rezistory R0 až R2. Tyto rezistory jsou připojeny na 3 piny portu A. Pomocí těchto 3 pinů tak lze nastavit 8 různých úrovní kontrastu.
2.3.2
Programové ovládání LCD modulu
Pro ovládání LCD displeje jsou připraveny 3 funkce. void lcd_init( void ) - inicializace LCD modulu. void lcd_send_cmd( char cmd ) - odeslání příkazu do LCD. void lcd_send_data( char ch ) - odeslání jednoho znaku do LCD. První funkci pro inicializaci lcd_init volá programátor vždy na začátku programu a během činnosti programu se již opakovaně volat nesmí. Další funkce lcd_send_cmd slouží k řízení LCD modulu. Seznam všech příkazů je uveden v technické dokumentaci na straně 29. Příkazů je celkem 8 a slouží především pro smazání displeje, nastavení chování kurzoru (velikost, zobrazení, posun), vypnutí/zapnutí displeje a definování vlastních znaků. Třetí funkcí lcd_send_data lze odeslat do LCD modulu osmibitovou ASCII hodnotu znaku, který se má zobrazit. Znak se zobrazí na aktuální pozici kurzoru. Chování kurzoru je přednastaveno tak, že se po zobrazení znaku kurzor automaticky posune na následující pozici směrem doprava. Příklad použití všech funkcí je možno uvést v následující ukázce programu:
24
#include "avrkit.h" #include "lcd-lib.h" int main() { avrkit_init(); lcd_init(); while ( 1 ) { lcd_send_cmd( 0x01 ); delay_ms( 1000 ); lcd_send_data( ’5’ ); lcd_send_data( ’$’ ); delay_ms( 1000 ); } }
// smazani LCD displeje // pauza 1 sekundu // zobrazeni znaku // pauza 1 sekundu
Uvedená ukázka kódu provede v nekonečné smyčce vždy na jejím počátku smazání displeje. Po krátké pauze zobrazí dvojici znaků "5$". Opět následuje krátké zpoždění a celý postup se opakuje od začátku. Adresy znaků, pozice kurzoru V předchozí podkapitole bylo uvedeno, že znaky se vypisují vždy na aktuální pozici kurzoru. Pro výpis znaků na displej je proto důležité správně nastavit pozici kurzoru před odesláním znaku na displej. Pro nastavení pozice kurzoru je možno v dokumentaci najít příkaz 0x80. K této hodnotě je nutno přidat ještě správnou adresu pozice, na kterou je potřeba kurzor nastavit. Pořadová čísla (adresy) znaků v řádku jsou uspořádány vzestupně za sebou. Druhý řádek však nenavazuje přímo na řádek předchozí. Přehledně jsou zobrazeny adresy pozic jednotlivých znaků na obrázku 2.9.
0x00
0x01
0x02
0x03
0x04
0x05
0x06
0x07
0x08
0x09
0x0A 0x0B 0x0C 0x0D 0x0E
0x0F
0x40
0x41
0x42
0x43
0x44
0x45
0x46
0x47
0x48
0x49
0x4A 0x4B 0x4C 0x4D 0x4E
0x4F
Obrázek 2.9: Adresy jednotlivých znaků LCD modulu Požadujeme-li například nastavení kurzoru na 10. pozici 2. řádku, musíme před výpisem znaku použít příkaz: lcd_send_cmd( 0x80 | 0x49 ); 25
Definice vlastních znaků LCD modul obsahuje ve své vnitřní paměti font 5×8 (šířka×výška), podle kterého se zobrazují na displeji jednotlivé znaky. Tento font je uložen v ROM a nelze jej tedy přepisovat. V dokumentaci je tvar všech znaků vyobrazen na straně 28. Řadič displeje však umožňuje uživateli nadefinovat několik vlastních znaků. V dokumentaci LCD modulu je formát vlastního fontu a jeho uložení v RAM paměti řadiče popsán na straně 27. Je možno definovat 8 znaků, jejichž ASCII hodnoty jsou v rozsahu ⟨0, 7⟩. Pro každý znak je potřeba definovat bitový vzor znaku pomocí 8 bajtů. Pro 8 znaků je tedy celková velikost RAM 64 bajtů. Počáteční adresa fontu pro každý znak je proto vždy celistvým násobkem čísla 8. Jak může vypadat definice fontu jednoho znaku, je vidět na obrázku 2.10. Ukázka představuje definice symbolu 𝜋. Velikost fontu je 5×8, proto je v každém bajtu trojice horních bitů ignorována. bit 7
6
5
4
3
2
1
0 0b00000000 / 0x00 0b00000000 / 0x00 0b00011111 / 0x1F 0b00001010 / 0x0A 0b00001010 / 0x0A 0b00001010 / 0x0A 0b00001010 / 0x0A 0b00000000 / 0x00
Obrázek 2.10: Bitová definice fontu jednoho znaku Jak může nyní programátor přenést svá připravená data představující font pro jeden znak do LCD řadiče? Mezi příkazy v dokumentaci LCD modulu na straně 29 je možno najít příkaz 0x40. Právě tento příkaz nastaví adresu RAM, kam se mají zapisovat data definující tvar znaku. Hodnotu 0x40 je tedy potřeba rozšířit o adresu znaku, který chceme předefinovat. Chceme-li například předefinovat znak 𝑧, kde ASCII hodnota 𝑧 ∈ ⟨0, 7⟩, může kód programu vypadat následovně.
26
.... char z = vybrany_znak_0_az_7; char font_z[ 8 ] = { ... }; lcd_send_cmd( 0x40 | ( z * 8 ) ); // prikaz pro zapis fontu for ( int f = 0; f < 8; f++ ) lcd_send_data( font_z[ f ] ); // zapis jednotivych bajtu fontu lcd_send_cmd( 0x80 | pozice ); // prepnuti zpet na zapis znaku lcd_send_data( z ); // vypis noveho znaku ....
Po zápisu fontu je důležité přepnout řízení displeje zpět do režimu zápisu znaků. To bylo v předchozí ukázce provedeno přesunem kurzoru na požadovanou pozici. Příklady úkolů pro cvičení ∙ Napiště funkci, která vypíše řetězec znaků na požadovanou pozici a řádek. ∙ Pomalu se posouvající dlouhý text. ∙ Zobrazte aktuální čas ve formátu HH:MM:SS s blikajícími ’:’. ∙ Stopky v obou řádcích, spuštění současně, zastavení každé zvlášť. ∙ Minutovník. Nastavit výchozí čas, spustit, po dosažení času 0 rozblikat podsvětlení. ∙ Tlačítky regulujte kontrast displeje. ∙ Tlačítky regulujte intenzitu podsvětlení. Využijte PWM integrované v procesoru. Úkoly se také mohou dle zadání vyučujících měnit a kombinovat.
27
2.4
Sběrnice I2 C
2.4.1
Popis sběrnice
Sběrnice I2 C byla navržena firmou Philips Semiconductors pro komunikaci jednočipových mikropočítačů s dalšími číslicovými obvody. I2 C je obousměrná dvouvodičová sběrnice. Někdy bývá ale nesprávně označována jako sériová linka. Zkratka I2 C označuje Inter Integrated Circuit Bus. Český překlad by mohl být meziobvodová sběrnice. Základní charakteristika Sběrnice se skládá ze dvou linek. SDA slouží pro obousměrný přenos dat a SCL linka slouží jako hodinový signál. Obě linky pracují v napěťových logických úrovních shodně s technologií TTL. V klidové stavu jsou obě linky v úrovni log. 1. Tento stav je udržovány dvěma zdvihacími (pull-up) rezistory. Výstupy číslicových obvodů jsou řešeny jako výstup typu otevřený kolektor. Tím je zaručena obousměrnost linky. Základní uspořádání systému můžeme vidět na obrázku 2.11. Na sběrnici může být připojeno více zařízení. Obvykle jedno zařízení označované jako Master řídí vysílání a příjem zpráv. Další zařízení, označovaná jako Slave, po výzvě nadřízeným obvodem data přebírají (receive), nebo odesílají (transmit). Na sběrnici smí být i více zařízení typy Master, ale taková zapojení již nepředstavují jednoduché systémy vhodné pro výuku. Ucc
SCL SDA
Master Receive Transmit
Slave Receive
Slave Receive Transmit
Slave Transmit
Obrázek 2.11: Uspořádání typického systému se sběrnicí I2 C
28
SCL
SCL 1
SDA
0
SDA
START a)
STOP b)
Obrázek 2.12: Průběhy signálů na sběrnici I2 C Přenos bitů Přenos bitů probíhá na sběrnici synchronně. Synchronizace se provádí hodinovým signálem SCL. Jeden bit je přenesen vždy v jednom hodinovém cyklu. Jak vypadá přenos hodnoty 1 a 0 můžeme vidět na obrázku 2.12a. Z obrázku je patrné, že datové signály se mění vždy jen v době, kdy je signál SCL v úrovni log. 0. Pokud dochází ke změně signálu SDA v době, kdy ke úroveň signálu SCL v log. 1, jde o signály řídící. Řídící signály START a STOP Vzhledem k počtu vodičů sběrnice I2 C, můžeme definovat jen dva řídící signály. Těmi jsou signály START (S) a STOP (P). Jak vypadá průběh těchto signálů můžeme vidět na obrázku 2.12b. Slovní popis je následující: z klidového stavu, kdy signál SDA i SCL jsou v log. 1 musíme přejít do komunikačního režimu signálem START. Tím rozumíme přechod signálu SDA z log. 1 na log. 0 při neměnné hodnotě signálu SCL v log. 1. Pak teprve musí následovat i přechod signálu SCL z log. 1 na log. 0. Chceme-li ukončit komunikaci, musíme uvést obě linky SDA i SCL do klidového stavu. Učiníme tak signálem STOP, který představuje nejprve nastavení SCL na log. 1 a poté nastavení i SDA na log. 1. Komunikace po bajtech Při přenosu dat mezi signály START a STOP není množství přenesených dat nijak omezeno. Data se ovšem nepřenáší po jednotlivých bitech, ale po celých bajtech. Průběh celého přenosu je vidět na obrázku 2.13. Z průběhu signálů a jejich popisu je patrné, že významově nejvyšší bit se přenáší jako první.
29
Master SCL
START
Master SDA
STOP 1
2
3
4
5
6
7
8
D7
D6
D5
D4
D3
D2
D1
D0
Slave SDA
9
ACK
Obrázek 2.13: Odeslání jednoho bajtu i s potvrzením na sběrnici I2 C Povrzování Na obrázku 2.13 je zobrazen nejen přenos jednoho bajtu, ale i další důležitá součást přenosu informace. Tou je potvrzování. Každý obvod musí příjem bajtu povrdit bitem ACK, což je log. 0 linky SDA v následujícím hodinovém cyklu po odvysílání bajtu. Potvrzení může být i NACK, tedy negovaný ACK, což je hodnota log. 1 linky SDA (master tak naznačuje, že ukončuje přenos dat). Všimněte si na obrázku 2.13 chování vysílače (Master) v devátém hodinovém cyklu, kdy se očekává signál ACK od přijímače (Slave). Vysílač nastaví SDA na log. 1, aby jeho výstup neovlivňoval linku SDA (viz výše informace o výstupu typu otevřený kolektor). Master musí nastavit SDA do klidového stavu na log. 1 před příjmem každého bitu od podřízeného obvodu. Zjednodušené zobrazení Pro další popis komunikace budeme používat zjednodušené zobrazení, jako na obrázku 2.14. Master
P
S D 7 D 6 D 5 D4 D 3 D 2 D 1 D0
Slave
A
Obrázek 2.14: Zjednodušené zobrazení průběhu komunikace na lince I2 C
Adresování Na sběrnici I2 C může být připojeno více obvodů současně, proto musí mít každý obvod svou jednoznačnou adresu, aby jej bylo možno „oslovit“. Každá adresa má osm bitů, které jsou rozděleny podle obrázku 2.15. Bity označené 𝐻0 ÷ 𝐻3 jsou dány výrobcem a nelezneme je vždy v technickém 30
H3 H2 H1 H0 A 2 A 1 A 0 RW Obrázek 2.15: Formát adresy obvodu na I2 C
1
+ 5 V
A 2
A 1
A 0
manuálu daného obvodu. Bity 𝐴0 ÷ 𝐴2 si při zapojení obvodu nastaví uživatel. Na vývojovém KITu se bity 𝐴0 ÷ 𝐴2 nastavují pomocí třech přepínačů dle zapojení na obrázku 2.16. Ze zapojení je patrné, že zapnutý přepínač znamená logickou úroveň 0. Na uvedený přepínač jsou připojeny oba dále popisované obvody.
2
A 0 1
2
A 1 1
2
A 2 G N D .
Obrázek 2.16: Určení adresových bitů A0-A2 pomocí přepínačů Poslední bit adresy je 𝑅/𝑊 . Tímto bitem říkáme, zda následující data budeme z pohledu řídícího obvodu do příslušného obvodu zapisovat (𝑅/𝑊 = 0), nebo budeme data číst (𝑅/𝑊 = 1).
2.4.2
Ověření adresy
Nejjednodušším příkladem komunikace je ověření ( „zaadresování“), zda daný obvod má skutečně přidělenou adresu dle dokumentace a uživatelského nastavení. Povinností obvodu, který přijme jeden bajt, je příjem potvrdit signálem ACK. Pokud má náš obvod DS1621 adresu 𝐴0 ÷𝐴2 , pak musí na zaslání bajtu dle obrázku 2.17 odpovědět. Tím máme jistotu, že obvod komunikuje. MASTER S
1
0
0
1
DS1621
P
A2 A1 A0 0 A
Obrázek 2.17: Příklad „zaadresování“ I2 C obvodu DS1621
31
2.4.3
8 bitový expandér PCF8574
Nedílnou a nezbytnou součástí následujícího textu je i technický manuál výrobce PCF8574.pdf. Pro výukové účely byl obvod PCF8574 vybrán záměrně. Jde o nejjednodušší dostupný obvod pro sběrnici I2 C. Neobsahuje žádné konfigurační registry a jeho chování nelze nijak měnit. Obsahuje pouze jediný 8 bitový registr, jehož každý bit je přímo vyveden na právě jeden výstupní pin pouzdra. Hodnotu tohoto registru lze jediným zápisem změnit a lze si aktuální nastavenou hodnotu i přečíst. Průběh komunikace s obvodem PCF8574 je znázorněn v manuálu na straně 10 a 11. Adresa Na straně 9 manuálu PCF8574 je uvedena adresa přidělená výrobcem pro nevyšší 4 bity 𝐻0 ÷ 𝐻3 adresy obvodu. Je to hodnota 0100b. Zbylé tři bity adresy 𝐴0 ÷ 𝐴2 se nastavují přepínači přímo u obvodu na vývojové desce. Příklad zápisu jednoho bajtu i s určením adresy může vypadat jako na obrázku 2.18. MASTER S
0
1
0
0
A2 A1 A0 0
PCF8574
0
1
0
1
1
0
1
P
0
A
A
Obrázek 2.18: Zaslání jednohy bajtu (0b01011010) obvodu PCF8574
Zapojení Pro možnost vizuální kontroly je na vývojové desce připojeno na vývody obvodu PCF8574 osm LED podle obrázku 2.19. Každému bitu registru odpovídá jedna LED označená 0-7. Jak je patrno z obrázku, LED se aktivují logickou úrovní 1.
32
LED0 1 2
SCL SDA
3
A0 PCF8574 A1 A2
4 5 6 LED7
Obrázek 2.19: Připojení LED k obvodu PCF8574
2.4.4
Digitální teploměr Dallas DS1621
Nedílnou a nezbytnou součástí následujícího textu je i technický manuál výrobce teploměru DS1621.pdf. Obvod DS1621 je digitální teploměr, který může pracovat jako teploměr pro spojité měření teploty, nebo provádět měření teploty na požádání, nebo pracovat jako termostat s nastavitelnou hysterezí. Pro výukové účely budeme preferovat použití teploměru pro spojité měření teploty. Formát teploty Na straně 4 manuálu DS1621 je uveden digitální formát naměřené teploty. Jde o devítibitové znaménkové číslo, kde nejnižší bit představuje rozlišení půl stupně. Protože devíti bity je překročen formát jednoho bajtu, je naměřená teplota předávána ve dvou bajtech za sebou. Adresa Na straně 8 manuálu DS1621 je uvedena adresa přidělená výrobcem pro nevyšší 4 bity 𝐻0 ÷ 𝐻3 adresy obvodu. Je to hodnota 1001b. Zbylé tři 33
bity adresy se nastavují instalovanými přepínači přímo na vývojové desce. Požadovaná hodnota bude zadána přímo na cvičení. Příkazy pro řízení teploměru Na straně 10 manuálu DS1621 jsou uvedeny všechny příkazy, kterými se teploměr ovládá. Stručný přehled s krátkým popisem uvádíme zde: ∙ Příkaz ACh (Access Config) slouží pro nastavení chování teploměru. Formát konfiguračního slova je na straně 5 manuálu DS1621. Pro funkci teploměru je důležitý bit označený jako 1SHOT, kterým se určuje, zda teploměr bude měřit teplotu spojitě, nebo na požádání. Při modifikaci konfiguračního slova by se měl nejprve aktuální stav přečíst, změnit potřebné bity a poté teprve zapsat. ∙ Příkaz EEh (Start Convert) spustí převod teploty. ∙ Příkaz 22h (Stop Convert) zastaví převod teploty. ∙ Příkaz AAh (Read Temperature) slouží pro čtění teploty. Obdrží-li obvod tento příkaz, vyšle následně 2 bajty s naměřenou teplotou. ∙ Příkaz A1h (Access TH) registr horního limitu termostatu. ∙ Příkaz A2h (Access TL) registr dolního limitu termostatu. Podrobnější popis a ostatní příkazy jsou v manuálu výrobce. Příklad komunikace Chceme-li předat obvodu nějaký příkaz, například požadavek na spuštění převodu teploty, zašleme příkaz EEh na požadovanou adresu. Postup je na obrázku 2.20. MASTER S
1
0
0
1
A2 A1 A0 0
DS1621
1
1
1
0
1
1
1
P
0
A
A
Obrázek 2.20: Zaslání příkazu Start Convert (EEh) obvodu DS1621 Další přesný popis všech komunikačních možností s obvodem DS1621 naleznete v dokumentaci DS1621 na straně 9.
34
Programátorské rozhraní Pro komunikaci s obvody na sběrnici I2 C je implementována následující množina funkcí: void I2C_Init() - inicializace, signály SDA a SCL jsou nastaveny na 1. void I2C_Start() - vygenerování sekvence START. void I2C_Stop() - vygenerování sekvence STOP. void I2C_Ack() - odeslání ACK. void I2C_NAck() - odeslání NACK. char I2C_getAck() - přečtení ACK. char I2C_Vystup( unsigned char value ) - odeslání bajtu a převzetí ACK. unsigned char I2C_Vstup() - příjem jednoho bajtu bez potvrzení. Příklady úkolů ve cvičení ∙ Prostudování dokumentace a připravených programů je součástí přípravy před cvičením. ∙ Prvním úkolem na cvičení bude nastavit obvodu DS1621 požadovanou tříbitovou adresu. ∙ Programem ověřit, zda je obvod na požadované adrese. Ten musí odpovědět signálem ACK. ∙ Čtení a zápis dat z/do expandéru PCF8574 ∙ Nastavit teploměr pro spojitý převod teploty. ∙ Spustit převod teploty, číst aktuální teplotu. ∙ Nastavit obvod DS1621 jako termostat
35
2.4.5
FM/AM radiomodul Si4735
Nedílnou součástí této dokumentace je i programátorská příručka výrobce FM radiomodulu SI4735-PG.pdf a text normy EN50067.pdf specifikující systém RDS. Modul FM rádia obsahuje digitální rádiový přijímač Si4735, který v sobě zahrnuje vše potřebné pro příjem rádiového signálu v pásmech FM/AM. Ve cvičení budeme využívat pouze FM pásmo. Tento obvod se běžně používá v mobilních telefonech jako miniaturní FM přijímač. Součástí FM modulu je i obvod PCF8574 s osmi LED, popsaný v kapitole 2.4.3. Pro ovládání obou obvodů bude použita sběrnice I2 C. Po správném nastavení obvodu rádia je na jeho výstupech k dispozici zvukový signál, který je dále zesílen v zesilovači a po stisknutí tlačítka je možné zvuk přehrát v integrovaném reproduktoru. Je také možné připojit si vlastní sluchátka, jejichž reprodukce již není závislá na stisku tlačítka.
Obrázek 2.21: Schéma zapojení radiového modulu Si4735 Adresa obvodu Si4735 na sběrnici I2 C je 0x22. Za touto adresou se dále uvádí konfigurační bajt, kterým se obvodu sděluje, jakou akci bude dále vykonávat. Některé konfigurační bajty je možné doplnit dalšími bajty jako argumenty. Vše je podrobně popsáno v dokumentaci výrobce.
36
Změna hlasitosti Pro změnu hlasitosti se využívá příkaz SET_PROPERTY 0x12, který má jako první argument 0x00 a jako další dvoubajtový argument podpříkaz RX_VOLUME 0x4000. Dále následuje nulový bajt a poslední bajt určuje svými pěti bity s nejnižší vahou hlasitost v úrovni 0-63. Podrobnější informace jsou uvedeny v technické dokumentaci na straně 65 a 117. Dotaz 0
1
2
3
4
5
0x12
0x00
0x40
0x00
0x00
0b000VVVVV*
*Bity V určují hlasitost
Ladění rozhlasové stanice Pro naladění obvodu na požadovanou frekvenci je možné využít dvou příkazů. První možností je příkaz FM_TUNE_FREQ 0x20, který obsahuje další 4 bajty jako argumenty. První a čtvrtý bajt mohou zůstat nulové. Druhý a třetí bajt obsahuje požadovanou frekvenci vynásobenou stem. Například pro frekvenci 97.3 MHz je nutné zadat hodnotu 9730 a to tak, že do druhého argumentu se zadá horní byte frekvence a do třetího spodní byte frekvence. Bližší informace jsou uvedeny v technické dokumentaci na straně 67-68. Dotaz 0
1
2
3
4
0x20
0x00
FreqHI
FreqLO
0x00*
*Bližší význam jednotlivých bitů je možné vyčíst z dokumentace
Druhou možností ladění stanic je proces automatického ladění pomocí příkazu FM_SEEK_START 0x21. Příkaz obsahuje pouze jeden argument, ve kterém je na místě druhého bitu uvedeno, zda se má po dosažení limitu rozsahu začne znovu na opačném konci rozsahu - log.1, nebo na konci rozsahu zastavit - log.0. Na pozici třetího bitu je log.1, pokud se provádí ladění směrem nahoru a log.0, pokud se ladí směrem dolů. Odpovědí na příkaz automatického ladějí je jeden byte. Bližší informace jsou uvedeny v technické dokumentaci na straně 69. Dotaz 0
2
0x21
0b0000SW00*
* S - ladění nahoru/dolu 0/1 W - na konci rozsahu začne ladění opět z opačného konce intervalu
37
Detekce stavu přijímače Příkaz FM_TUNE_STATUS 0x22 obsahuje pouze jeden argument, který je možné ponechat nulový. Po zadání tohoto příkazu je možné vyčíst osm bajtů. Ve druhém a třetím bajtu lze zjistit aktuálně naladěnou frekvenci. Ve čtvrtém bajtu je hodnota síly signálu a v pátém bajtu kvalita signálu po naladění stanice. Bližší informace jsou uvedeny v technické dokumentaci na straně 70-71. Dotaz 0
1
0x22
0x00*
*Bližší význam jednotlivých bitů je možné vyčíst z dokumentace Odpověď 0
1
2
3
4
5
6
7
S1*
S2*
FreqHI
FreqLO
RSSI
SNR
MULT*
CAP*
*Bližší význam jednotlivých bitů je možné vyčíst z dokumentace
Detekce kvality signálu Příkaz FM_RSQ_STATUS 0x23 obsahuje pouze jeden argument, který je možné ponechat nulový. Po zadání tohoto příkazu je možné vyčíst osm bajtů. Ve druhém bajtu je v nejnižším bitu 𝑉 informace, zda na aktuálně nastavené frekvenci byla rozpoznána nějaká stanice. Ve čtvrtém bajtu je hodnota síly signálu a v pátém bajtu kvalita signálu. Bližší informace jsou uvedeny v technické dokumentaci na straně 72-73. Dotaz 0
1
0x23
0x00*
*Bližší význam jednotlivých bitů je možné vyčíst z dokumentace Odpověď 0
1
2
3
S1*
S2*
0bxxxxxxxV*
STBL*
4
RSSI
5
6
7
SNR
MULT*
FREQ*
*Bližší význam jednotlivých bitů je možné vyčíst z dokumentace
Radio Data System (RDS) RDS je systém, který může doprovázet vysílání rádiových stanic. Slouží k přenosu datových informací do rádiového přijímače. Mezi tyto informace patří například název vysílané stanice, název právě přehrávaného pořadu, alternativní frekvence na kterých vysílá identická stanice, nebo hlášení o poloze a závažnosti dopravních nehod v okolí. 38
Pro získání jedné skupiny RDS dat z obvodu Si4735 je nutné zadat příkaz FM_RDS_STATUS 0x24. Tento příkaz je následován jedním bajtem, ve kterém je podstatný pouze bit I s nejnižší vahou. Bitem I=1 se povolí vnitřní přerušení pro příjem RDS dat. Jako odpověď na tento příkaz je přijato 13 bajtů. Ve druhém bajtu je nejnižším bitem S oznamováno, zda jsou RDS informace synchronizovány. Bez tohoto bitu nemá smysl další informace zpracovávat! Pro následné zpracování jsou nejdůležitější bajty označené jako BxHI a BxLO kde x je 1 až 4. Jedná se přímo o bloky dat přenášené v rámci jedné skupiny. Bližší informace jsou uvedeny v technické dokumentaci na straně 74-76. Dotaz 0
1
0x24
0b00000SMI*
* bit I zapíná vnitřní přerušení pro příjem RDS, význam bitů S a M je uveden v dokumantaci Odpověď 0
1
2
3
4
5
RDS0*
RDS1*
0bxxxxxxxS*
RDS3*
B1HI
B1LO
6
7
8
9
10
11
12
B2HI
B2LO
B3HI
B3LO
B4HI
B4LO
0baabbccdd**
*Bližší význam jednotlivých bitů je možné vyčíst z dokumentace ** Bity aa, bb, cc a dd určují stav jednotlivých bloků
Data v systému RDS se přenášejí ve skupinách. Každá skupina se dále dělí na čtyři bloky, viz obrázek 2.22. Obsah jednotlivých bloků je dán normou EN50067. Bity Checkword jsou zpracovány přímo obvodem Si4735 a nejsou v odpovědi na dotaz 0x24 obsaženy.
Obrázek 2.22: Obecná struktura RDS Z obrázku 2.22 je patrné, že v prvním bloku každé skupiny je vysílána 39
informace označená jako PI – Program Identification. Jedná se o jedinečné číslo, které je specifické pro každou rozhlasovou stanici. Druhý blok obsahuje v bitech A3 až A0 identifikaci skupiny. Dále bit B0, který určuje zdali se jedná o verzi A nebo B. Bit TP určuje, zdali se aktuálně vysílá dopravní hlášení. Bity PT4 až PT0 definují typ vysílaného programu (hudba, řeč, aj.). Význam zbylých bitů v bloku 2 a bitů v bloku 3 a 4 jsou již závislé na typu skupiny. Dekódování služby Program Service Služba Program Service (název stanice) se vysílá ve skupině číslo 0 a to jak ve verzi A, tak i B, přičemž text v obou verzích se může lišit. Rozložení jednotlivých bitů ve skupinách A a B je znázorněno na obrázcích 2.23 a 2.24. Pokud je detekována skupina 0, je v bloku 2 na posledních dvou bitech příznak, které dva znaky z osmiznakového názvu stanice se přenášejí. Název programu je tedy rozdělen na čtyři dvojice. Samotné znaky jsou vysílány v bloku 4 v horním a spodním bajtu.
Obrázek 2.23: Skupina 0A
Obrázek 2.24: Skupina 0B
40
Dekódování služby Alternative Frequency Služba alternativní frekvence je vysílána spolu se službou PS ve skupině 0 a to pouze ve verzi A. Verze B skupiny 0x00 se liší především ve třetím bloku, jak je patrné z obrázků 2.23 a 2.24. Ve verzi A jsou na pozici třetího bloku vysílány alternativní frekvence na pozici horního a dolního bajtu. Hodnota 0b00000001 odpovídá frekvenci 87.6MHz až hodnota 0b110011 odpovídá frekvenci 107.9MHz. Dekódování služby Radiotext Radiotext je obdoba služby PS s tím rozdílem, že znaků je 64. Znaky jsou rozděleny do čtveřic. Radiotext je vysílán ve skupině s označením 2A. Čtyři bity s nejnižší vahou v bloku 2 určují, která čtveřice znaků je přenášena. V blocích 3 a 4 jsou poté přenášeny čtyři znaky.
Obrázek 2.25: Skupina 2A
41
Příklady úkolů ve cvičení ∙ Nalaďte modul FM rádia na požadovanou frekvenci. ∙ Pomocí dvou tlačítek nastavujte úroveň hlasitosti. ∙ Pomocí dvou tlačítek spusťte automatické ladění rádia (nahoru nebo dolů). ∙ Využijte bargraf připojený k obvodu PCF8574 k indikaci síly přijímaného signálu. ∙ Nalaďte stanici vysílající RDS a zobrazte data přenášená službou Program Service. ∙ Nalaďte stanici vysílající RDS a zobrazte data přenášená službou Radiotex. ∙ Nalaďte stanici vysílající RDS a zobrazte alternativní frekvence na kterých je vysílána identická stanice.
42
Část II
Programování paralelních systémů
43
Kapitola 3
Vlákna 3.1
Využití výpočetního výkonu procesorů s více jádry pomocí vláken (threads)
V posledních letech se díky rozvoji moderních technologií výroby procesorů stalo běžným standardem výrobců, umístit do jednoho pouzdra více procesorů současně. Výpočetní výkon počítače se takto navyšuje prakticky tolikrát, kolik jader je celkově v daném počítači nainstalováno. Za tímto technickým vývojem ale zaostává vývoj programového vybavení počítače. Programy i operační systémy jsou za technickým vývojem stále pozadu. Ukázalo se to v posledních 20 letech velmi viditelně několikrát. Jako příklad vezměme čas, než se 64 bitové operační systémy staly standardem. Firma AMD představila svůj první 64 bitový procesor v roce 2000. Kdy se dostaly 64 bitové OS na servery a kdy na desktopy? Odpověď snadno naleznete na internetu. Problémem současnosti je vývoj programů pro využívání více procesorů paralelně. V roce 2010 ve svém článku „The Trouble With Multicore“ uvedl jeden z významných odborníků David Patterson, profesor na katedře informatiky Univerzity v Berkeley i následující odstavec: „One of the biggest factors, though, is the degree of motivation. In the past, programmers could just wait for transistors to get smaller and faster, allowing microprocessors to become more powerful. So programs would run faster without any new programming effort, which was a big disincentive to anyone tempted to pioneer ways to write parallel code. The La-Z-Boy era of program performance is now officially over, so programmers who care about performance must get up off their recliners and start making their programs parallel.“ Pokud tedy požadujeme, aby naše programy pracovaly rychleji, není do
44
budoucna jiná cesta, než je psát jako paralelní!
3.1.1
Programování s vlákny
Vlákny rozumíme samostatně (a paralelně) běžící podprogramy jednoho programu (procesu). Tato technologie je v operačních systémech Windows i Unixech implementována již téměř 20 let. Přináší programátorům větší pohodlí při psaní programů a to bez ohledu na počet procesorů počítače. Teprve však při dvou a více procesorech mohou vlákna otevřít programátorovi cestu k využítí vyššího výpočetního výkonu počítače. Podívejme se, jak využít vlákna v libovolném operačním systému Windows. V programátorské dokumentaci WINAPI rozhraní (např. na stránkách http://msdn.microsoft.com) můžeme najít následující informace. Každá funkce, která má být vykonávána jako samostatné vlákno, musí mít tento tvar: DWORD WINAPI jmeno_funkce( LPVOID par ) { /* tělo funkce */ } Máme-li takto deklarovanou funkci, můžeme z ní vytvořit vlákno pomocí funkce CreateThread, která má následující prototyp: HANDLE WINAPI CreateThread( LPSECURITY_ATTRIBUTES lpThreadAttributes, SIZE_T dwStackSize, LPTHREAD_START_ROUTINE lpStartAddress, LPVOID lpParameter, DWORD dwCreationFlags, LPDWORD lpThreadId );
Ze šesti parametrů funkce můžeme 4 parametry ponechat nastavené jako 0 - lpThreadAttributes, dwStackSize, dwCreationFlags, lpThreadId. Parametr lpStartAddress je název funkce, kterou chceme spustit jako samostatné vlákno. A lpParameter je parametr, který novému vláknu předáváme. Návratová hodnota je HANDLE nového vlákna, nebo informace o selhání. Pro čekání na ukončení vykonávání vlákna použijeme následující funkci: DWORD WINAPI WaitForSingleObject( HANDLE hHandle, DWORD dwMilliseconds ); Jako první parametr uvedeme HANDLE vlánka, které jsem si dříve vytvořili. Druhý parametr je maximální čas v milisekundách, po jaký na ukon45
čení vlákna budeme čekat. Pokud chceme počkat, až vlákno opravdu skončí, zadáme INFINITE. Příklad programu, který vytvoří jedno vlákno a počká na jeho ukončení může vypadat následovně: DWORD WINAPI funkce_vlakno( LPVOID str ) { printf( "Spustilo se vlakno %s.\n", ( char * ) str ); Sleep( 5000 ); return 0; } int main() { HANDLE vlakno = CreateThread( 0, 0, funkce_vlakno, "TESTOVACI", 0, 0 ); WaitForSingleObject( vlakno, INFINITE ); }
Další příklad na využití vláken je uveden v příloze tohoto studijního materiálu - vlakna.zip. Tento archiv obsahuje ukázku programu, kde se hledá pomocí dvou vláken maximální prvek v poli. Každé ze dvou vláken prohledává jen polovinu pole. Výsledný čas hledání je v případě spuštění na dvou a víceprocesorovém počítači poloviční. Zdrojový kód programu je velmi jednoduchý a je popsán ve vložených komentářích. Příprava na cvičení ∙ Seznámit se ukázkovým programem a způsobem měření doby běhu částí programu. ∙ Zopakovat si nejjednodušší algoritmy třídění - přímý výběr, přímé vkládání a bublinkové třídění. ∙ Připravit si třídící funkce tak, aby bylo možno třídit sestupně i vzestupně. ∙ Upravit třídící funkce tak, aby bylo možno setřídit jen část pole. ∙ Připravit si třídící funkce pro třídění pole s libovolnými typy prvků int, long, fload, double, ... ∙ Vyzkoušet si vygenerovat libovolně dlouhé pole náhodných čísel. ∙ Vyzkoušet si vytváření vláken. 46
Úkoly ve cvičení ∙ Setřídit určeným algoritmem pole náhodně vygenerovaných čísel. ∙ Setřídit část pole, např. horní a dolní polovinu pole. ∙ Spojit dvě setříděné části pole v jednu posloupnost. ∙ Spustit třídění částí pole paralelně. ∙ Změřit čas třídění.
47
Kapitola 4
CUDA Návody pro poslední dvě cvičení jsou v samostatném dokumentu na internetových stránkách pro tento předmět.
48