A Microchip különböző PIC mikrokontrollereket gyárt, amelyek képesek az USB kommunikációra, akár HID (Human Interface Device) használatával, akár CDC-ben (Communication Device Class). A PIC18-as családban (pl.: PIC18F67J50, PIC18F85J50, PIC18F14K50, stb), de akár a PIC32MX-eseknél (pl.: PIC32MX440F128L, PIC32MX795F512L, stb) is bőven találunk olyan eszközöket, amelyek képesek az USB protokoll használatára.
Készítsünk el közösen egy USB-s projektet, amelynek segítségével LED-eket tudunk ki-/bekapcsolni. Karaktereket fogunk küldeni, a kiküldött karakterektől függ, hogy melyik LED-et kapcsoljuk be/ki. Tehát az USB CDC-t fogjuk alkalmazni. A PC-n futó program virtuális soros porton keresztül csatlakozik a mikrovezérlős panelhez. Ennek a kommunikációs megoldásnak a maximális sebessége kb 64KB/s.
Ezt akár egy általunk megvalósított tesztpanelon, vagy a Microchip által gyártott rengeteg fejlesztői board egyikén is kipróbálhatjuk.
Az általunk választott PIC18F család fejlesztői kártyájának a leírása, illetve a kapcsolási rajza innen tölthető le.
A Microchip által kínált USB Stack (és egyéb stack, illetve alkalmazások) innen tölthető le. Bármelyik USB módot is használnánk (pl.: CDC, HID, stb), a Microchip úgy oldotta meg az adott példaalkalmazását, hogy a main() függvény felépítése mindig ugyanaz. Itt tudunk választani, hogy interrupt megoldást, vagy a polling-olást alkalmazzuk a projektünk elkészítésekor.
Polling-olásnál az USBDeviceTasks() függvény mindig meghívásra kerül a végtelen ciklusban, ha megszakítást használunk, akkor csak a megszakításnál kerül ez a függvény futtatásra.
#if defined(__18CXX)
void main(void)
#else
int main(void)
#endif
{
InitializeSystem();
#if defined(USB_INTERRUPT)
USBDeviceAttach();
#endif
while(1)
{
#if defined(USB_POLLING)
USBDeviceTasks();
#endif
ProcessIO();
}
}
Látható a main() függvénynél, hogy feltételes fordítás van, tehát csak az IT használatánál kerül sor az USBDeviceAttach() függvény használatára.
A while(1) végtelen ciklusban állandóan meghívjuk a ProcessIO() függvényt, ebben fogjuk megvalósítani azt a programrészletet, amely a LED-ek állapotáért fog felelni.
Telepítsük a Microchip Application Library-t, majd azután indítsuk el az MpLab-ot. Hozzunk létre egy projektet az MpLab-on belül, és a projekt felépítése a következő legyen (1. ábra).
1. ábra Az USB-CDC projekt felépítése
Az USB CDC projektben található *.C és *.H file-ok megtalálhatók a telepített Microchip Application Library-ban.
A telepített Microchip Application Library-ban konkrét projekt is található, az. "..\..\USB\Device-CDC-Basic Demo\Firmware" elérési útvonalon. Kattintsunk a "USB Device - CDC - Basic Demo - C18 - Low Pin Count USB Development Kit.mcp" projektfile-ra, ekkor az MpLab elindul és betöltődik az USB CDC projekt. A "main.c" file-ban találjuk meg a main() és a ProcessIO() függvényeket.
Ahhoz, hogy virtuális soros kommunikációt tudjunk kialakítani az USB porton keresztül, a következő függvényeket használhatjuk (1. táblázat).
Fordítsuk le a projektünket (CTRL + F10). Ha sikerült, akkor egészítsük ki a ProcessIO() függvényt az USB Stack-ben található függvényekkel. Ezeket a függvényeket a "usb_function_cdc.c" file-ban találjuk meg.
Függvény neve | Iránya | Leírás |
getsUSBUSART() | PC -> PIC | string olvasása a PC-ről |
putrsUSBUSART() | PIC -> PC | adatküldés a programmemóriából, \n-nel |
putsUSBUSART()
|
PIC -> PC | adatküldés az adatmemóriából \n-nel |
mUSBUSARTTxRom() | PIC -> PC | adatküldés programmemóriából, a hossz ismert |
mUSBUSARTTxRAM() | PIC -> PC | adatküldés az adatmemóriából, a hossz ismert |
mUSBUSARTIsTxTrfReady() | készen áll az újabb adatküldésre a PIC? | |
mCDCGetRxLength() | az olvasott string hossza |
1. táblázat Főbb USB-CDC kommunikációt megvalósító függvények
A "getUSBUSART" függvény meghívásakor a paraméterlistájában átadunk egy max. 64 elemű karaktertömböt (pl.: USB_Out_Buffer) és egy egész számot. Az "USB_Out_Buffer" tömbben tároljuk el azokat a karaktereket, amelyeket a számítógépről küldünk a PIC felé.
Ezt a getUSBUSART() függvényt írjuk be a ProcessIO() függvény törzsébe.
Az eredeti ProcessIO() látható itt, majd a módosított megoldást mutatja a következő rész.
void ProcessIO(void)
{
if((USBDeviceState < CONFIGURED_STATE) || (USBSuspendControl==1)) return;
if(mDataRdyUSART())
{
USB_Out_Buffer[NextUSBOut] = getcUSART();
++NextUSBOut;
USB_Out_Buffer[NextUSBOut] = 0;
}
CDCTxService();
}
A módosított ProcessIO() (kiemelve a feltételvizsgálat) :
void ProcessIO(void)
{
if((USBDeviceState < CONFIGURED_STATE) || (USBSuspendControl==1)) return;
if(mDataRdyUSART())
{
USB_Out_Buffer[NextUSBOut] = getcUSART();
++NextUSBOut;
USB_Out_Buffer[NextUSBOut] = 0;
}
if (getsUSBUSART(USB_Out_Buffer,1))
{
if (USB_Out_Buffer[0] == 'x')
LATC = 0B00000110;
else
LATC = 0B00000000;
}
CDCTxService();
}
A végtelen ciklusban állandóan meghívott ProcessIO() törzsében található getsUSBUSART() függvény belsejében feltételvizsgálat történik. Ha az USB_Out_Buffer karaktertömb 0. eleme "x", akkor a mikrovezérlő C portjának az 1. és 2. bitje logikai 1-be kerül. Egyéb esetben az összes C portbit logikai nulla értéket kap.
Természetesen egyszerre nem csak egy karakter vihető át, és figyelhető egy feltételes szerkezettel, hanem maximum 64 karakter.
Ha nem fogjuk tudni, hogy mennyi karaktert küldünk át a vezérlés során (pl.: ez a szám változik vagy nem rögzítjük), akkor a mCDCGetRxLength() függvény visszatérési értékét figyelhetjük, mert ez a függvényérték adja vissza az átküldött karaktersorozat hosszát.
Ha nem csak LED-eket szeretnénk be-/kikapcsolni, hanem mikrovezérlőből beolvasni adatot az USB-n keresztül, akkor ismét módosítani kell az eredeti ProcessIO() függvényt. Az első táblázatban lévő függvények egyikét alkalmazhatjuk, attól függően, hogy ismert hosszúságú karaktersorozatot kívánunk átküldeni, illetve el kell dönteni azt is, hogy honnan küldjük az adatot.
void ProcessIO(void)
{
if((USBDeviceState < CONFIGURED_STATE) || (USBSuspendControl==1)) return;
if(mDataRdyUSART())
{
USB_Out_Buffer[NextUSBOut] = getcUSART();
++NextUSBOut;
USB_Out_Buffer[NextUSBOut] = 0;
}
if (getsUSBUSART(USB_Out_Buffer,1))
{
if (USB_Out_Buffer[0] == 'x')
LATC = 0B00000110;
else
LATC = 0B00000000;
}
if(mUSBUSARTIsTxTrfReady())
putrsUSBUSART("WebElektronika");
CDCTxService();
}
Először beállítjuk a LED-ek (mikrovezérlő C port-ja) állapotát, majd a putrsUSBUSART függvény használatával a "WebElektronika" karaktersorozatot küldük a PIC18F-ből a számítógép felé.
Ha nem karaktersorozatot szeretnénk átküldeni, hanem egész számot (pl.: AD átalakító értéke), akkor átalakítást kell végeznünk. Erről részletesebben itt olvashat.
Megismerjük most a PIC18F mikrovezérlők megszakításkezelését, és készítünk két egyszerű példaprogramot is. Ezek az egy- és a kétszintű megszakításkezelést mutatják be, de sablonként is jól használhatók saját fejlesztéseknél is.. . . .
Ebben a cikkben egy kétsoros LCD felprogramozását és a hozzátartozó sajátfüggvényeket, makrókat mutatjuk be. Nem térünk ki viszont az LCD-k felépítésére, vezérlésére.. . . .
Ebben a cikkben egy kétsoros LCD felprogramozását és a hozzátartozó sajátfüggvényeket, makrókat mutatjuk be. Nem térünk ki viszont az LCD-k felépítésére, vezérlésére.. . . .