A WebElektronika korábbi cikkeiben már foglalkoztunk egy projekt létrehozásával, illetve a portkezeléssel is. A most induló sorozatunkban ugyanakkor olyan alkalmazásokat készítünk, és mutatunk be, amelyek a MikroElektronika Fusion V7-es paneljére készültek. Természetesen ezek a megoldások (minimális) módosítások elvégzése után más fejlesztőpaneleken is futtathatók.
A telepítés után indítsuk el a MpLAB X-et, és hozzunk létre egy projektet. Ezt a "File/New Project" menüpont kiválasztásával lehet (1 ábra) megtenni.
1. ábra Új projekt létrehozásának első lépése az MpLAB X-nél
Ezután a felbukkanó ablakban tudjuk kiválasztani a projektünk típusát. Használjuk a "Microchip Embedded/Standalone Project" sablont (2. ábra).
2. ábra Az új projekt létrehozásakor kiválasztásra kerül a használni kívánt sablon
Ezt követően tudjuk megadni az alkalmazni kívánt mikrovezérlőt, amely később a fejlesztés során természetesen megváltoztatható. Tekintettel arra, hogy MikroElektronika PIC Fusion V7-es paneljét fogjuk használni, amely a PIC32MX795F512L mikrovezérlőt tartalmazza, ezért ezt a családtagot válasszuk ki a legördülő listából (3. ábra).
3. ábra A PIC3MX795F512L mikrovezérlő kiválasztása
Az MpLAB X egy keretkörnyezet, amely alá tudjuk telepíteni a különböző nyelvű/verziójú fordítókat. A fordító kiválasztása a következő feladat, amikor egy új projektet hozunk létre (4. ábra). Természetesen utólag ez is megváltoztatható.
4. ábra A fordító kiválasztása
Az új projekt létrehozásának a végén kell megadni a projekt nevét, illetve az elérési helyét (5. ábra).
5. ábra A projekt nevének és elérési helyének a megadása a következő lépés
A projektünket sikeresen létrehoztuk, viszont még teljesen üres, nem tartalmaz egy file-t sem. Ezért adjunk hozzá egy "C" file-t, amely tartalmazni fogja természetesen a "main()" függvényt, amely a projekt belépési pontja. Tehát, amikor majd a lefordított, a mikrovezérlő memóriájába letöltött alkalmazásunkat elindítjuk, akkor a "main()" függvény fog először elindulni.
Kattintsunk az egér jobb gombjával a "Source Files" könyvtárnévre, majd a "xc32_newfile.c..." menüpontra (6. ábra).
6. ábra Új "C" file hozzáadása a projekthez
A felbukkanó ablakban adjuk meg a file nevét (portkezel1), majd mentsük el (7. ábra).
7. ábra Új file hozzáadása a projekthez
Ezután megjelenik az MpLAB X keretkörnyezetben a "portkezel1' szövegeditor, ahol a "C" kódunkat tudjuk írni. Másoljuk ide be a következő programot.
#include <p32xxxx.h>
main()
{
TRISAbits.TRISA2 = 1;
TRISD = 0x0000;
LATD = 0x5555;
while(1);
}
A "main()" függvényben először az "A.2" bitet beállítjuk bemenetre, majd a "D" port alsó 16 bitjét pedig kimenetre. Az "A" port többi bitjének az irányát nem állítjuk be.
Ezután a "D" port alsó 16 bitjének értéket adunk úgy, hogy a "LATD" regisztert írjuk. Hexadecimális formában kap értéket, de lehetőségünk van használni a kettes, a nyolcas, illetve akár a tízes számrendszert is. Mi törekszünk a tízenhatos számrendszer használatára.
Végül egy végtelen ciklus következik, amely megakadályozza azt, hogy a vezérlésünk kilépjen a "main()" függvényből. Ez azért fontos, mert ha kilépünk abból, akkor olyan memóriaterületről olvasnánk be a következő programrészletet, amelyet nem használunk, általunk nem ismert tartalmat futtatnánk.
A 8. ábrán látható az első programunk, ahol nem olvassuk még be a bemeneti értéket, noha az "A.2" bitet már beállítottuk bemenetre.
8. ábra A projekt első portkezelését megvalósító programja
Ezután fordítsuk le a projektünket, amely még egy szöveges file-t tartalmaz. Ebből kell nekünk ún. hexa file-t készíteni, amelyet már le tudunk tölteni a mikrovezérlő programmemóriájába. A fordításra több lehetőségünk is van, kattinthatunk a "kalapács" ikonra (9. ábra), de akár az "F11" funkcióbillentyűt is megnyomhatjuk.
9. ábra Fordítás
Egészítsük ki most az előbb bemutatott programot, vagy adjunk hozzá egy új file-t a projekthez. Fontos, hogy a projektünk csak egy "main()" függvényt tartalmazhat (a projekt csak egy helyről indulhat el), ezért az előző programot vegyük ki a projektből.
#include <p32xxxx.h>
main()
{
TRISAbits.TRISA2 = 1;
TRISD = 0x0000;
while(1)
{
if(PORTAbits.RA2)
LATD = 0xAAAA;
else
LATD = 0x5555;
}
}
Az "A.2" bitet az előbb nem használtuk fel, de most alkalmazni fogjuk. Figyeljük ennek a portbitnek az állapotát a végtelen ciklusban. Azaz, állandóan beolvassuk az "A.2" portbit értékét. Ha a beolvasott érték logikai "1", akkor a "D" portra a 0xAAAA"-t (0B1010101010101010) tesszük ki, ha az "A.2" értéke "0", akkor a 0x5555-öt (0B0101010101010101).
Látható a "main()" függvény törzsében a különböző speciális file regisztereknek (SFR) az értékadása. Viszont mi van akkor, ha egy másik fejlesztőpanelt használunk, ahol nem a "D" porton helyezkednek el a LED-ek? Illetve az "A" port 2. bitjére nincsen nyomógomb kötve? Ekkor át kell írni az alkalmazásunkat, módosítani kell a speciális file regisztereknek a nevét, amely egy nagyobb méretű projektnél már nem szerencsés. Ezért használjunk definíciókat, illetve makrókat.
Nevezzük el az "A.2" bitet "BTN"-nek (Button), a 16 db LED-et meghajtó "D" portot "LEDs"-nek, illetve hozzuk létre azokat a definíciókat is, amelyek a portregiszterek irányának a beállításáért felelnek (BTN_Tr, LEDs_Tr). Továbbá, a későbbi alkalmazások miatt adjunk nevet a "D" port legkisebb helyiértékének is, a "D.0"-nak.
Ezeknek megfelelően módosítsuk az előbbi programot.
#include <p32xxxx.h>
#define BTN PORTAbits.RA2
#define BTN_Tr TRISAbits.TRISA2
#define LEDs LATD
#define LEDs_Tr TRISD
#define LEDD0 LATDbits.LATD0
#define LEDD0_Tr TRISDbits.TRISD0
#define LEDsA() { LEDs = 0xAAAA; }
#define LEDs5() { LEDs = 0x5555; }
main()
{
BTN_Tr = 1;
LEDs_Tr = 0x0000;
while(1)
{
if(BTN)
LEDs = 0xAAAA;
else
LEDs = 0x5555;
}
}
Látható, hogy a "main()" függvényben már nem szerepelnek a speciális file regiszterek nevei, hanem azoknak az elnevezései. A "LATD = 0xAAAA;" értékadás helyett már a "LEDs = 0xAAAA;" szerepel.
Ha ezt az alkalmazást áttesszük egy másik fejlesztőpanelre, akkor elég átírni az adott definíciókat, a "main()" függvény törzsében lévő programsorokhoz nem kell nyúlnunk.
Természetesen alkalmazhatunk makrókat is, amelyek segítségével a "main()" függvényben a konkrét értékadások elhagyhatók. Módosítsuk újra az alkalmazásunkat a következő program szerint.
#include <p32xxxx.h>
#define BTN PORTAbits.RA2
#define BTN_Tr TRISAbits.TRISA2
#define LEDs LATD
#define LEDs_Tr TRISD
#define LEDD0 LATDbits.LATD0
#define LEDD0_Tr TRISDbits.TRISD0
#define LEDsA() { LEDs = 0xAAAA; }
#define LEDs5() { LEDs = 0x5555; }
#define BTN_In() { BTN_Tr = 1; }
#define LEDs_Out() { LEDs_Tr = 0x0000; }
main()
{
BTN_In();
LEDs_Out();
while(1)
{
if(BTN)
{
LEDsA();
}
else
LEDs5();
}
}
Látható, hogy itt már nincsenek értékadások (csak a makrókban), a "main()" függvényben csak makróhívások találhatók. A makróhíváskor nem történik stack művelet, tehát gyorsabban kerül végrehajtásra, mint a függvényhívás.
Módosítsuk újra az alkalmazásunkat, írjunk újabb makrókat (és egy függvényt), mert a feladatunk most az, hogy a "D.0" portbiten lévő LED-et villogtassuk. Tekintettel arra, hogy szeretnénk látni ennek a LED-nek a villogását, ezért késleltetést kell alkalmaznunk. A legegyszerűbb késleltetést (amely a legrosszabb megoldás is) egy szoftveres megoldással tudjuk megvalósítani. Egy for ciklus segítségével valósítjuk meg a késleltetést úgy, hogy 0-tól el fogunk számolni egy adott értékig.
Módosítsuk újra a programunkat a következő példa szerint.
#include <p32xxxx.h>
#define BTN PORTAbits.RA2
#define BTN_Tr TRISAbits.TRISA2
#define LEDs LATD
#define LEDs_Tr TRISD
#define LEDD0 LATDbits.LATD0
#define LEDD0_Tr TRISDbits.TRISD0
#define LEDsA() { LEDs = 0xAAAA; }
#define LEDs5() { LEDs = 0x5555; }
#define BTN_In() { BTN_Tr = 1; }
#define LEDs_Out() { LEDs_Tr = 0x0000; }
#define LED0_Tg() { LEDD0 = ~LEDD0; }
void villog(unsigned int hatar);
main()
{
LEDD0_Tr = 0;
while(1)
villog(10000);
}
void villog(unsigned int hatar)
{
int k;
for(k = 0; k < hatar; k++);
//LATDbits.LATD0 = ~LATDbits.LATD0;
//LEDD0 = ~LEDD0;
LED0_Tg();
}
Látrehoztunk egy "villog()" nevű saját függvényt, amely rendelkezik egy "unsigned int" típusú paraméterrel (hatar). Amikor ezt a függvényt tehát meghívjuk a végtelen ciklusban, akkor átadunk egy előjelnélküli egész számot, ez lesz a "hatar" nevű paraméter értéke. A "main()" függvény előtt szerepel ennek a sajátfüggvénynek a szignatúrája.
A "villog()" függvény törzsében kapott helyett a szoftveres késleltetés megvalósítása, illetve itt hívjuk meg a "LED0_Tg()" nevű makrót is, amelynek a feladata annyi, hogy a "D" port 0. bitjének az értékét negálja.
Látható, hogy a makróhívás előtt két programsor is található, amelyek kommentelésre kerültek, azaz nem kerülnek végrehajtásra. Azért szerepelnek a függvény törzsében, mert ha nem alkalmaznánk ezt a makrót, akkor használhatnánk a két programsor egyikét is.
Vajon meg tudjuk oldani ezt a feladatot átláthatóbban is? Noha ennek az alkalmazásnak egyszerű, átlátható a felépítése, de sajnos ez nincs mindig így. Ez a projekt egyszerű, az a feladata, hogy egy LED-et villogtasson, de egy bonyolultabb feladatot nem érdemes egy file-ban megvalósítani.
Nézzük tehát meg azt, hogy hogyan lehet a makrókat, illetve a sajátfüggvényt külön file-okban elhelyezni, mert a célunk most az, hogy a "main()" függvény egy olyan file-ban legyen, amely nem tartalmaz más függvényt, illetve makrót.
Ezért adjunk hozzá a projekt "Header Files" virtuális könyvtárához egy file-t. Ehhez a jobb egérgombbal kell kattintani a könyvtárnévre (10. ábra).
10. ábra Új header file hozzáadása a projekthez
A felbukkanó ablakban adjunk nevet (panel.h) az új header file-nak (11. ábra).
11. ábra A "panel.h" header file hozzáadása a projekthez
A korábbi programunkból másoljuk át a definíciókat, illetve a makrókat a "panel.h" file-ba. Ezután töröljük ki ezeket a forrásfile-ból. Ezt követően a "Source Files" könyvtárhoz adjunk hozzá egy file-t (fv.c), amelyben elhelyezzük a "villog()" nevű sajátfüggvényünket (12. ábra).
12. ábra Új file (fgv.c) hozzáadása a projekthez
A "villog()" függvényt másoljuk be a "fgv.c" file-ba. Tekintettel arra, hogy ebben a függvényben meghvásra kerül egy makró, amely a "panel.h" file-ban van, ezért ezt a header file-t be kell hívnunk a "fgv.c" file-ban.
#include <p32xxxx.h>
#include "panel.h"
void villog(unsigned int hatar)
{
int k;
for(k = 0; k < hatar; k++);
//LATDbits.LATD0 = ~LATDbits.LATD0;
//LEDD0 = ~LEDD0;
LED0_Tg();
}
Noha nem kötelező, de a sajátfüggvény szignatúráját (prototípus) is elhelyezhetjük egy másik header file-ban (fgvproto.h).
void villog(unsigned int hatar);
A projektünk tartalmaz tehát két forrásfile-t (külön vannak a "main()" és a "villog()" függvények), illetve két header file is megtalálható a projektben. Ezt a két header file-t is be kell olvasnunk a file legelején.
Látható a legújabb megoldásnál, hogy a "main() függvényünket tartalmazó forrásfile jelentősen egyszerűbb lett. Megtalálható a két header file beolvasása, illetve a "main()" függvény belsejében a "LEDD0_Tr" kap értéket, azaz, a "D" port 0. bitje digitális kimenet lesz. Ezután már a "while(1)" végtelen ciklus következik, amelynek a magjában egy másik file-ban implementált sajátfüggvény kerül meghívásra.
#include <p32xxxx.h>
#include "panel.h"
#include "fgvproto.h"
main()
{
LEDD0_Tr = 0;
while(1)
villog(10000);
}
A 13. ábrán látható a projektünk végleges felépítése, illetve a "main()" függvény végleges verziója. Fontosnak tartjuk megjegyezni azt, hogy a sajátfüggvény prototípusát tartalmazó header file meghívása kikerült a végleges változatból.
13. ábra A "portkezeles" projekt felépítése és a "portkezel6.c" file tartalma
A 14. ábrán a "panel.h" file tartalma látható.
14. ábra A "panel.h" file-ban látható definíciók és makrók
Végül a 15. ábrán látjuk az "fgv.c" file-ban található "villog()" nevű sajátfüggvényt.
15. ábra A "villog()" függvény az "fgv.c" file-ban
Október közepén elindítjuk az Atmel 8 bites mikrovezérlőkről szóló sorozatunkat. Ehhez használnunk kell természetesen egy fejlesztőkörnyezetet is. Több ilyen is létezik, például a WinAVR, vagy az Atmel Studio. Mi az Atmel Studio-t fogjuk használni, e. . . .
A PIC18F mikrovezérlők ma is népszerű a fejlesztők körében. Noha 8 bites architektúráról beszélünk, számos érdekes és hasznos alkalmazás megvalósítható vele. Elég csak az USB-re, vagy akár az Ethernetre gondolnunk. Ezért a Szerkesztőség egy sorozat k. . . .
A Microchip által javasolt fejlesztőkörnyezet az MPLABX, amely felváltja az MPlab-ot. Használata nehézkesnek tűnhet, ezért megnézzük ennek az IDE környezetnek a használatát, készítünk egy egyszerű projektet, amely egy PIC32 mikrovezérlőre épül.. . . .