1. Úvod, návrhový systém úvod do programování v C
MPLAB,
− −Obsah 1. Úvod, návrhový systém MPLAB, úvod do programování v C Literatura Programové vybavení předmětu
Literatura 1.
Hardwarový přípravek
MPLAB Starter Kit for PIC24F User´s Guide, Technická dokumentace, Microchip Technology Incorporated, 2008. (http://www.microchip.com)
2.
MPLAB® IDE User’s Guide with MPLAB Editor and MPLAB SIM Simulator. Technická dokumentace, Microchip Technology Incorporated, 2009. (http://www.microchip.com)
3.
MPLAB® C30 C COMPILER USER’S GUIDE. Technická dokumentace Microchip Technology Incorporated, 2005. (http://www.microchip.com)
4.
PIC24FJ256GB110 Family Data Sheet. Technická dokumentace Microchip Technology Incorporated. 2009. (http://www.microchip.com)
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í
Programové vybavení předmětu 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
1z7
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. Stiskněte Hlavní menu→Project→Project Wizard…→Další. 2. Na panelu vybrat označení mikrokontroléru PIC24F256GB106. 3. Stiskněte Další. 4. Ve výběru „Active Toolsuite“ vybrat „Microchip C30 Toolsuite“. 5. Zkontrolovat položky v „Toolsuite Contents“. Pokud jsou na levé straně červené křížky, nemáte nainstalován balíček překladače C30. 6. Stiskněte Další. 7. 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. 8. Stiskněte Další. 9. 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
2z7
Dokončit. 10. 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. 11. 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. 12. 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 .
13. 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
počet bitů
typ znaménko rozsah
unsigned char
8 I
char
8 I
unsigned int
16 I
int
16 I
unsigned short
16 I
short
16 I
poznámka
ne 0/255 (0x00/0xFF) ano -128/127 (0x80/0x7F) ne 0/65535 (0x0000/0xFFFF) ano
-32768/32767 (0x8000/0x7FFF)
! na x86 32 bitů ! na x86 32 bitů
ne 0/65535 (0x0000/0xFFFF) ano
-32768/32767 (0x8000/0x7FFF)
BI-VES Cvičení 1 - Úvod, Miroslav Skrbek (C)2010,2011
3z7
unsigned long
32 I
ne 0x00000000/0xFFFFFFFF
long
32 I
ano 0x80000000/0x7FFFFFFF
float
32 FP
ano
double
32 FP
ano
void*
16
! na x86 64 bitů ! 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
4z7
// // // // // // //
~ - 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
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
5z7
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; unsigned int delka; unsigned char prikaz; } hlavicka_t;
// 1B // 2B // 1B
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
6z7
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.
BI-VES Cvičení 1 - Úvod, Miroslav Skrbek (C)2010,2011
7z7