BI-VES Cvičení 1 - Úvod, Miroslav Skrbek (C)2010,2011 1 z 7 1. Úvod, návrhový systém MPLAB, úvod do programování v C Literatura 1. 2. 3. 4. MPLAB Starter Kit for PIC24F User s Guide, Technická dokumentace, Microchip Technology Incorporated, 2008. (http://www.microchip.com) MPLAB IDE User s Guide with MPLAB Editor and MPLAB SIM Simulator. Technická dokumentace, Microchip Technology Incorporated, 2009. (http://www.microchip.com) MPLAB C30 C COMPILER USER S GUIDE. Technická dokumentace Microchip Technology Incorporated, 2005. (http://www.microchip.com) PIC24FJ256GB110 Family Data Sheet. Technická dokumentace Microchip Technology Incorporated. 2009. (http://www.microchip.com) Programové vybavení předmětu Obsah 1. Úvod, návrhový systém MPLAB, úvod do programování v C Literatura Programové vybavení předmětu Hardwarový přípravek Mikrokontrolér PIC24FJ256GB106 Vytvoření projektu v návrhovém systému MPLAB Spuštění programu v simulátoru Spuštení programu v přípravku Ladění programu v přípravku Programování v jazyce C Jednoduché datové typy (MPLAB C30) Přiřazení a aritmetické výrazy Přetypování jednoduchých datových typů Bitové operace Přiřazení z/do speciálního funkčního registru Struktury (struct) Obsluha přerušení MPLAB IDE download www.microchip.com (úplně dole na stránce MPLAB IDE v8.63) MPLAB C30 Compiler download www.microchip.com (úplně dole na stránce MPLAB C Compiler for PIC24 and dspic v3.25 in LITE mode) Hardwarový přípravek
BI-VES Cvičení 1 - Úvod, Miroslav Skrbek (C)2010,2011 2 z 7 MPLAB Starter Kit for PIC24F MPLAB Starter Kit for PIC24F - Uživatelská příručka Aplikační část přípravku (vpravo od bílé dělící čáry) obsahuje mikrokontrolér PIC24F256GB106 (1), ke kterému je připojen displej (3), kapacitní dotyková klávesnice (7), tříbarevná RGB LED dioda (11), potenciometr (6), USB konektor typ A: host, On-The-Go (4) a USB konektor B - device (5). Mikrokontrolér (1) je programován programátorem, který se nachází vlevo od bílé dělící čáry. Programátor obsahuje mikrokontrolér (8) s USB rozhraním a s počítačem komunikuje přes konektor (2). Mikrokotrolér (1) běží na hodinovém kmitočtu 12MHz, který získává z programátoru přes externí hodninový vstup. Krystal 32768Hz (10) je určen pro realizaci hodin reálného času a je napojen na mikrokontrolér (1). Připojení přípravku k počítači Mini konektor USB kabelu připojte do konektoru (2) a druhý konec s USB konektorem A zasuňte do PC. Tím je přípravek připraven k použití. Přípravek je napájen přes USB kabel, nepotřebuje proto žádné externí napájení. Mikrokontrolér PIC24FJ256GB106 PIC24FJ256GB106 Datasheet (*.pdf) Vytvoření projektu v návrhovém systému MPLAB 1. 2. 3. 4. 5. 6. 7. 8. 9. Stiskněte Hlavní menu Project Project Wizard Další. Na panelu vybrat označení mikrokontroléru PIC24F256GB106. Stiskněte Další. Ve výběru Active Toolsuite vybrat Microchip C30 Toolsuite. Zkontrolovat položky v Toolsuite Contents. Pokud jsou na levé straně červené křížky, nemáte nainstalován balíček překladače C30. Stiskněte Další. V položce Create New Project File vyplňte cestu a jméno projektového souboru. Doporučuji si předem vytvořit projektový adresář a do něho uložit projektový soubor. Stiskněte Další. Na formuláři Step four nic nevyplňujte, stiskněte tlačítko Další a na dalším formuláři stiskněte
BI-VES Cvičení 1 - Úvod, Miroslav Skrbek (C)2010,2011 3 z 7 Dokončit. 10. 11. 12. 13. Nyní vytvořte nový zdrojový soubor Hlavní menu New a uložte jej funkcí File Save a nezapomeňte vyplnit cestu do projektového adresáře a jméno souboru s příponou *.c. Zařaďte zdrojový soubor do projektu kliknutím pravým tlačítkem myši na Source Files v projektovém okně a výběrem položky Add Files v pop-up menu. Zařaďte linker script do projektu. Klikněte pravým tlačítkem myši na Linker Script v projektovém okně a výběrem položky Add Files v pop-up menu. Linker script pro PIC24FJ256GB106 najdete v adresáři c:\program Files\Microchip\mplabc30\v3.25\support \PIC24F\gld\p24FJ256GB106.gld. Program přeložte Hlavní menu Project Build All. Spuštění programu v simulátoru HlavníMenu Debugger Select Tool MPLAB SIM HlavníMenu Debugger a dále užívejte ladící funkce Spuštení programu v přípravku HlavníMenu Programmer Select Tool Starter kits HlavníMenu Programmer Program Ladění programu v přípravku HlavníMenu Programmer Select Tool Starter Kits HlavníMenu Debugger a dále užívejte ladící funkce Programování v jazyce C Compiler C30 tools (GCC) Manual c30userguide.pdf Jednoduché datové typy (MPLAB C30) datový typ unsigned char počet bitů typ znaménko rozsah 8 I ne 0/255 (0x00/0xFF) char 8 I ano -128/127 (0x80/0x7F) poznámka unsigned int 16 I ne 0/65535 (0x0000/0xFFFF)! na x86 32 bitů int 16 I ano -32768/32767 (0x8000/0x7FFF) unsigned short 16 I ne 0/65535 (0x0000/0xFFFF) short 16 I ano -32768/32767 (0x8000/0x7FFF)! na x86 32 bitů
BI-VES Cvičení 1 - Úvod, Miroslav Skrbek (C)2010,2011 4 z 7 unsigned long 32 I ne 0x00000000/0xFFFFFFFF long 32 I ano 0x80000000/0x7FFFFFFF float 32 FP ano double 32 FP ano! na x86 64 bitů void* 16! na x86 32 bitů obecně jakýkoliv ukazatel Při portování existujících programů (např. algoritmů pro kryptografii) z PC je třeba dát pozor na kratší int. Přiřazení a aritmetické výrazy int main() { int a,b,c; a = 1; b = 2; c = a + b; } return 0; Přetypování jednoduchých datových typů INT char c = 0x80; int a; a = c; // v a bude 0xFF80 (znaménkové rozšíření) // Protože char je datový typ se znaménkem, dojde při konverzi do širšíh // typu se znaménkem k znaménkovému rozšíření. Proto bude v a hodnota 0x unsigned char c = 0x80; int a; a = c; // v a bude 0x0080, unsigned char je datový typ bez znaménka (hodnota v // proto horní bity zůstávají nulové. char c = 0x80; unsigned int a; a = c; // v a bude 0xFF80, nejprve dojde ke znaménkovému rozšíření na defaultní // do proměnné unsigned int. FLOAT (DOUBLE) float c = 1.8; int a = c; // desetinná část datového typu float se ořízne, v a je tedy 1 (nez float c = 1.8; int a = c + 0.5; // převod na int se zaokrouhlením Bitové operace
BI-VES Cvičení 1 - Úvod, Miroslav Skrbek (C)2010,2011 5 z 7 // ~ - bitová negace // - bitový or // & - bitový and // ^ - birový xor // = - bitový or (read-modify-write) a = 5; je totéž co a = a 5; // &= - bitový and (read-modify-write) a &= 5; je totéž co a = a & 5; // ^= - bitový xor (read-modify-write) a ^= 5; je totéž co a = a ^ 5; unsigned int a = 0xFF00; a = 0x0001; nastavení bitu 0 na jedničku v a a &= ~0x0100; nastavení bitu 8 na nulu v a a ^= 0x0001; negace bitu 0 v a Pozor!!! není totéž co, & není totéž co &&. Např. 5 & 8 je 0x00, kdežto 5 && 8 je 0x01 (5 a 8 jsou považovány za true, proto je výsledek true, tj. 1) Přiřazení z/do speciálního funkčního registru #include <p24fxxxx.h> int main() { TRISB = 0x000F; // hexadecimální hodnota LATB = 0b0001000100001111; // binární hodnota LATC = 128; // dekadicky unsigned int b = PORTB; unsigned short c = PORTC; } return 0; TRISB, LATB, LATC, PORTB a PORTC jsou názvy speciálních funkčních registrů. Tyto registry jsou deklarovány v p24fxxxx.h a navazujících hlavičkových souborech. p24fxxxx.h je univerzální hlavičkový soubor pro všechny typy mikrokontrolérů řady PIC24F. Výběr konkrétního typu se provádí automaticky na základě mikropočítače uvedeného v projektu. Tím je zajištěna určitá portabilita zdrojového kódu. Struktury (struct) Zde se seznámíme s problémem, se kterým se můžete setkat i na systémech x86 a který vede na poměrně zákeřné chyby v programu. Tento problém se vyskytuje u všech architektur vyšších než osmibitových a pramení z nestejné efektivity přístupu do paměti a snahy překladačů generovat co nejoptimálnější kód. U 32 bitových procesorů x86 je možné provést jakékoliv čtení nebo zápis v délce 1, 2 nebo 4 byty, a to na jakékoliv adrese. Ale ne všechny se provedou stejně efektivně. Například 32 bitové čtení z adresy 1 bude rozloženo do dvou čtecích cyklů, protože paměť je organizovaná po 32 bitech a z adresy 0 se jedním čtením přečtou data z adres 1,2,3 a z adresy 4 se přečte nejnižší byte. Podobně bude vypadat 32 bitové čtení z adres 2 a 3 a šestnáctibitové čtení z adresy 3. U PIC24F, který má šestnáctibitovou architekturu, budou činit potíže 16 bitová čtení z lichých adres. Na rozdíl od x86, PIC24F v rámci jednoduchosti hardwaru taková čtení přímo zakazuje a pokus o takovéto čtení končí výjimkou. Proto tam, kde se nelze takovému čtení vyhnout, musí překladač generovat bytové instrukce i pro 16 bitové zápisové a čtecí operace. Mějme následující strukturu v programu pro PIC24F struct { char a; int b;
BI-VES Cvičení 1 - Úvod, Miroslav Skrbek (C)2010,2011 6 z 7 char c; } s; Logicky předpokládáme, že když proměnná s bude ležet na adrese řekněme 0x100, pak a bude na adrese 0x100, b bude na adrese 0x101 a c bude na adrese 0x103 a sizeof(s) bude vracet hodnotu 4. Schválně si to vyzkoušejte a uvidíte, že tomu tak není. a bude ležet na 0x100, b bude na adrese 0x102 a c bude na 0x104 a sizeof(s) bude vracet hodnotu 6. Byty na adresách 0x101 a 0x105 nebudou přístupné a nebudou tedy využity. Pak proměnnou b bude možno číst a zapisovat šestnáctibitovou operací, protože leží na sudé adrese 0x102. Pokud struktury používáte v rámci programu, pak nevznikne žádný problém a vše bude fungovat dobře. Problém nastane v okamžiku, kdy nějaká data načtete z vnějšku (například po sériové lince, síti, z SD karty, USB apod.) do pole a pak pole přetypujete na strukturu. Příklad Předpokládejme, že po sériové lince přijdou data, která budou mít hlavičku ve formátu 1. byte adresát, 2. a 3. byte délka, 4. byte příkaz. V programu budeme chtít zjistit, zda zpráva patří nám (porovnáme pole adresát). Pokud ano, vykonáme příkaz a parametry příkazu budou následovat za hlavičkou v délce, kterou udávají byty 2(LSB) a 3(MSB). Pro hlavičku si vytvoříme následující strukturu: typedef struct { unsigned char adresat; // 1B unsigned int delka; // 2B unsigned char prikaz; // 1B } hlavicka_t; Pak napíšeme následující program... // deklarujeme buffer o délce 255 bytů #define BUF_SIZE 255 unsigned char buffer[buf_size]; // zavoláme funkci pro přečtení dat ze sériové linky, která // naplní buffer daty a vrátí délku prectenych dat int len = serial_read(buffer, BUF_SIZE); // Nyní přetypujeme buffer na ukazatel na hlavicku hlavicka_t* hlavicka = (hlavicka_t*)buffer; // Ted můme vyčíst jednotlivé položky unsigned char a = hlavicka->adresat; unsigned int l = hlavicka->delka; unsigned char p = hlavicka->prikaz;... Z pohledu jazyka C je to korektní program a při jeho prohlížení neshledáme žádnou chybu. Přesto pro následující hodnoty v poli buffer: 0x01, 0x02, 0x00, 0x0F, 0xAA, 0x55 (adresát 1, délka 2, příkaz 15 (0x0F)) přečteme do proměnných a = 0x01 (OK), l = 0x0F00 (Chyba), p = 0xAA (Chyba). Řešení tohoto problému Musíme použít atribut packed. Atributy můžeme chápat jako jistá upřesňující doporučení pro překladač, aby překládal určitým nestandardním způsobem. S tímto atributem bude deklarace hlavičky vypadat takto:
BI-VES Cvičení 1 - Úvod, Miroslav Skrbek (C)2010,2011 7 z 7 typedef struct attribute ((packed)) { unsigned char adresat; // 1B unsigned int delka; // 2B unsigned char prikaz; // 1B } hlavicka_t; Atribut packed můžeme také aplikovat na jednotlivé položky, alternativní deklarace vypadá takto: typedef struct { unsigned char adresat; // 1B unsigned int delka attribute ((packed)); unsigned char prikaz; // 1B } hlavicka_t; // 2B Obsluha přerušení PIC24 obsahuje tabulku vektorů přerušení, kam se ukládají adresy podprogramů (funkcí v C), které jednotlivá přerušení obsluhují. Implicitně linker tabulku vyplní tak, že vektory přerušení směřují na implicitní obslužný podprogram, který provede reset mikropočítače. Pokud chceme nainstalovat pro některé přerušení vlastní obslužný podprogram (funkci v C), pak musíme následovat tato pravidla: funkce má přesně dané jméno, které koresponduje s typem přerušení, např. _T1Interrupt. Seznam dostupných jmen nalezneme v c30userguide.pdf tabulka 7-1, návratový typ funkce je void a parametry jsou také void, deklarace funkce musí obsahovat atributy interrupt a auto_psv. void attribute ((interrupt, auto_psv)) _T1Interrupt(void) { } Atribut interrupt zajistí transparentnost funkce, tj. všechny registry modifikované funkcí obsluhy přerušení, případně funkcemi z ní volané. Na kód uvnitř funkce nejsou kladena z pohledu jazyka žádná omezení. Platí zásada, že program obsluhy přerušení musí být mikrokontrolérem vykonán v kratším čase než je perioda vzniku žádostí o toto přerušení. Proto v obsluze nepoužívejte složité funkce, jako je například zobrazování na displeji, kód obsahující dlouhá čekání např. prodleva několik milisekund, čekání na stisk klávesy, apod.