Aszinkron soros kommunikáció (UART)
A fejezet tartalma:- Univerzális aszinkron soros kommunikáció
- UART modulok kivezetései
- A soros perifériák engedélyezése
- Az UARTx modulok regiszterkészlete
- Az UART0 modul konfigurálása
-
Mintaprogramok
- Program4_1: Egyszerű kiíratás az UART0 soros porton
- Program4_2: Egyszerű karakter bevitel az UART0 soros porton
- Az UART2 port használata USB-UART átalakítóval
- Program4_3: Egyszerű kiíratás az UART2 soros porton
- Program4_4: Karakter visszatükrözés az UART2 soros porton
- Uart_retarget: A stdio átirányítása az UART0 soros portra
- Felhasznált anyagok és ajánlott olvasmányok
Amikor egy mikrovezérlő a külvilággal kommunikál, az adatforgalom többnyire bájtok, vagy több bájból álló üzenetcsomagok formájában történik.
Párhuzamos kommunikáció esetén minden adatbitet külön adatvonalon küldünk ki, s a kommunikáció szinkronizálásához még néhány vezérlő jel továbbítása is kellhet. Ilyen kommunikáció zajlott hajdanában a személyi számítógépek és a Centronics kábel túlsó végén lógó nyomtató, vagy lapszkenner között.
Soros kommunikáció esetén viszont az adatbitek egymás után, szekvenciálisan kerülnek kiküldésre ugyanazon az egy adatvezetéken. Ez nem csupán gazdaságosabbá teszi a kommunikáció hardveres megvalósítást, hanem olyan típusú kommunikációt is lehetővé tesz, amelynek ellenoldali partnere nagyobb távolságban van (az ipari telephely túlsó szegletében, esetleg egy másik városban...
Az MKL25Z128VLK4 mikrovezérlő számos kommunikációs perifériával rendelkezik:
- USB OTG periféria, amely Full speed (12 Mbit/s) és Low speed (1.5 Mbit/s) kommunikációra alkalmas
- 2 db SPI (Serial Peripheral Interface) modul
- 3 db UART (Universal Asynchron Transmitter Receiver) melyek közül az egyik kis fogyasztású
- 2 db I2C (Inter Integrated Circuits) modul
Univerzális aszinkron soros kommunikáció
Az univerzális aszinkron soros adatküldés és fogadás története a géptávírók koráig nyúlik vissza. Fő feladata az volt, hogy a párhuzamos adatokat (egy-egy karakter 5, 7, vagy 8 bites kódja) egyetlen vonalon, adatbitenként időben egymás után küldje el egy előre megszabott ütemben (pl. 110 bit/s), a vevő oldalon pedig a soros adatokat vissza kell állítani karakterkódokká. A kapcsolat jellegétől függően a kommunikáció lehet egyirányú (simplex), felváltva kétirányú (half duplex), vagy egyidejűleg kétirányú (full duplex). A teletype az első miniszámítógépek általános perifériájaként is kitűnő eszköz volt. Az első UART áramkörök a DEC PDP miniszámítógépeihez készültek, amelyekben a bejövő jel mintavételezésével jobb időzítést sikerült megvalósítani, mint a korábbi eszközökkel.Az aszinkron soros kapcsolat egyik fontos jellemzője, hogy nincs külön szinkronjel, ezért az adónak és a vevőnek előre rögzített ütemben (bitrátával) kell küldeni/fogadni az adatokat. A másik fontos jellemző pedig az, hogy az adatbájtok (vagy karakterek) "keretbe foglalva" kerülnek kiküldésre. Erre egyrészt azért van szükség, hogy a végtelen bitfolyamban meg lehessen találni az egyes adategységeket, másrészt minden újabb adatbájt kezdete lehetőséget ad az újraszinkronizálásra.
A keretezés azt jelenti, hogy minden adatbájt előtt van egy start bit, az adatbájt után pedig egy (vagy két) stop bit. A start és stop bit között adatküldési formátumtól függően lehet 5, 7, 8 vagy 9 adatbit és opcionálisan egy paritásbit. Mi a legelterjedtebb 8, N, 1 formátumot fogjuk használni, azaz 8 adatbitet küldünk, nem használunk paritásbitet, s a stop bitek száma 1 lesz. Egy tipikus jelalak (a TX kimenet jelszintjének időbeli lefutása) az alábbi ábrán látható. Az ábrán látható jelsorozat a bináris 0b01001101 adatbájt (ne feledjük: visszafelé kell olvasni!), ami a hexadecimális 0x4D-nek, vagy a decimális 77-nek felel meg, s az ASCII kódtábla szerint az „M” karakter kódját jelenti.
1. ábra: Egy tipikus UART jelalak
Az UART kommunikáció eredetileg bipoláris, NRZ (Non Return to Zero) jelszintekkel történik. Egy példa erre az RS-232 ahol a a logikai '1' jelszintje -15 V és -3 V közötti, a logikai '0' jelszintje pedig +15 V és +3 V közötti lehet. A mikrovezérlők és a logikai IC-k világában azonban természetesebb megoldás az unipoláris jelszint alkalmazása: '1' a digitális rendszer logikai magas jelszintje (régebben +5 V, az újabb eszközöknél, és így esetünkben is +3,3 V), a '0' pedig az alacsony logikai szint (0 V). Tétlen állapotban, amikor nincs adatküldés, az adás vonalat (TX) magas szinten kell tartani. Minden elküldött karakter egy start jellel kezdődik, azaz a TX vonal egy bitidő tartamára alacsony szintre vált. Ezt követően kerülnek kiküldésre egymás után az adatbitek, a legkisebb helyiértékű bittel kezdve. A legmagasabb helyiértékű bit után egy stop bit következik, amikor egy bitidő tartamára a kimenet magas szintre vált.
Ha a vevő azt tapasztalja, hogy a stop bit helyén (ami esetünkben a 10. bitet jelenti, ami a start bit lefutó élét 9 bitidőnyi késéssel követi) alacsony szintet észlel, akkor „keretezési hibát” (Framing Error) jelez és eldobja a feltehetően hibásan vett adatot.
Egy bit időtartama az adatküldés sebességétől függ. A szabványos adatsebességek (300, 1200, 2400, 4800, 9600, 19200, 38400, 57600, 115200 bit/s stb) közül alapértelmezetten a 9600 bit/s-ot használjuk. A 9600 bit/s azt jelenti, hogy egy bitre 1 s/9600 = 0,00010416667 s, azaz 104,1667 µs idő jut. Vegyük észre, hogy a karakterek "keretezése" miatt a hasznos adatok továbbítási sebessége kisebb, mint az aktuális adatküldési sebesség, mivel a 8 bites adaton kívül legalább egy START és egy STOP bitet is ki kell küldenünk.
UART modulok kivezetései
Az MKL25Z128VLK4 mikrovezérlő kivezetés kiválasztás (pin multiplexing) funkciója lehetővé teszi, hogy a három UART periféria lábkivezetéseinek kiosztását több lehetőség közül kiválasszuk. Az, hogy az egyes UART modulok adó (TX) és vevő (RX) vezetéke egyáltalán mely lábakon vezethető ki, a FRDM-KL25Z Pin usage and pinout chart dokumentumban található. Ezen lehetőségek közül némelyik a FRDM-KL25Z kártya esetében hardver ütközés miatt nem használható. A ténylegesen használható kivezetéseket az mbed forráskódjának PeripheralPins.c állománya alapján az alábbi táblázatban foglaltuk össze. A táblázatban vastagon szedett nevű kivezetések az elsődlegesen ajánlottak, amennyiben a kártya csatlakozó pontjainak Arduino kompatibilis kiosztását nem akarjuk megzavarni. A táblázatban a kivezetések megnevezés mellett zárójelben feltüntettük Zárójelben megadtuk a kivezetés üzemmódjának beállításához szükséges számot is, amit az adott kivezetéshez tartozó megfelelő PORTx_PCRn portvezérlő regiszter MUX bitcsoportjába kell beírni az UART mód kiválasztásához. Például az UART0 modulhoz tartozó PTA1 és PTA2 kivezetések engedélyezése így néz ki: SIM->SCGC5 |= 0x0200; // PORTA engedélyezése
PORTA->PCR[1] = 0x0200; // PTA1 UART RX módba állítása
PORTA->PCR[2] = 0x0200; // PTA2 UART TX módba állítása
Megjegyzés: Természetesen a
táblázatban szereplő számot 8 bináris helyiértékkel balra kell tolni
(két hexadecimális nullát utána kell írni...), a MUX bitcsoport helyiértékének megfelelően.1. táblázat: Az UART portok választható kivezetései
Modul |
TX |
RX |
Megjegyzés |
---|---|---|---|
UART0 |
PTA2 (2) |
PTA1 (2) |
Az OpenSDA USB-UART protokol
konverterhez csatlakozik |
PTD7 (3) |
PTD6 (3) |
Alternatív kivezetési lehetőség |
|
PTE20 (4) |
PTE21 (4) |
Alternatív kivezetési lehetőség | |
UART1 |
PTE0 (3) |
PTE1 (3) |
A Pin diagram szerinti
támogatott
kivezetés |
PTC4 (3) |
PTC3 (3) |
Alternatív kivezetési lehetőség | |
UART2 |
PTE22 (4) |
PTE23 (4) |
A Pin diagram szerinti támogatott kivezetés |
PTD3 (3) |
PTD2 (3) |
Alternatív kivezetési lehetőség | |
PTD5 (3) |
PTD4 (3) |
Alternatív kivezetési lehetőség |
A soros perifériák engedélyezése
Minden használni kívánt perifériát engedélyezni kell. Az MKL25Z128VLK4 mikrovezérlő soros perifériáit a SIM_SCGC4 regiszter megfelelő bitjének '1'-be állításával lehet engedélyezni.2. ábra: A SIM_SCGC4 regiszter bitjeinek kiosztása
Az UARTx modulok regiszterkészlete
A Freescale MKL25Z128VLK4 mikrovezérlő három UART modulja hasonló regiszterkészlettel rendelkezik (az UART0 modul felépítése valamivel bonyolultabb, ezért ennek hárommal több regisztere van). A regiszterkészletek báziscímei:- UART0 báziscíme: 0x4006 A000
- UART1 báziscíme: 0x4006 B000
- UART2 báziscíme: 0x4006 C000
Regiszternév |
A regiszter funkciója | Cím |
---|---|---|
UART0_BDH | Baud Rate Register High (adatsebesség - magas helyiérték) |
4006_A000 |
UART0_BDH | Baud Rate Register Low (adatsebesség - alacsony helyiérték) | 4006_A001 |
UART0_C1 |
Control Register 1 (1. vezérlő regiszter) |
4006_A002 |
UART0_C2 | Control Register 2 (2. vezérlő regiszter) | 4006_A003 |
UART0_S1 | Status Register 1 (1. állapotjelző regiszter) |
4006_A004 |
UART0_S2 | Status Register 2 (2. állapotjelző regiszter) |
4006_A005 |
UART0_C3 | Control Register 3 (3. vezérlő regiszter) | 4006_A006 |
UART0_D | Data Register (Adat regiszter) |
4006_A007 |
UART0_MA1 | Match Address Register 1 (1. címegyezés regiszter) |
4006_A008 |
UART0_MA2 | Match Address Register 2 (2. címegyezés regiszter) |
4006_A009 |
UART0_C4 | Control Register 4 (4. vezérlő regiszter) | 4006_A00A |
UART0_C5 | Control Register 5 (5. vezérlő regiszter) | 4006_A00B |
- Konfigurációs regiszterek: Mielőtt használnánk valamelyik UART modult, konfigurálni kell azt. Be kell állítani az adatsebességet, a szóhosszt, a stop bitek számát, a megszakítást (ha kell) stb. A beállításhoz szükséges legfontosabb regiszterek: UARTx_BDH, UARTx_BDL, UARTx_C1, és UARTx_C2.
-
Adatküldő és vételi regiszter: az adatküldés vagy –fogadás esetünkben
egyszerűen az UART_D
regiszter írásával/olvasásával történik. Ugyanaz a név íráskor illetve
olvasáskor fizikailag másik regisztert jelent: íráskor a küldő egység
adatregiszterébe kerül az adat, olvasáskor pedig a vevő egység
adatregiszterét olvassuk ki.
- Státusz regiszter: a státusz regiszter bitjei az UART modul állapotát, különféle események bekövetkeztét jelzik, például új adat beérkezését, a beérkezett adat érvénytelenségét, az adatküldés végét stb. A számunkra legfontosabb állapotjelző biteket az UARTx_S1 regiszter tartalmazza.
3. ábra: Egy UART modul felépítésének blokkvázlata
Az UART0 modul konfigurálása
Ebben a szakaszban az UART0 modul konfigurálását mutatjuk be, amely egyrészt az OpenSDA programozó és USB-UART átalakító áramkörön keresztül kitűnő lehetőséget kínál a PC-vel történő kommunikációra.Az adatátviteli sebesség beállítása
Az adatküldő egység az adatátviteli sebességnek (Baud rate) megfelelő frekvenciájú órajelet igényel. Minden órajel impulzusra egy bit kerül kiküldésre. Mivel az UART porton az adatátvitel aszinkron módon zajlik, a vevőegységnek minél pontosabban kell tudni meghatározni a beérkező adat Start bitjének a homlokélét. Ennek érdekében a bemenet mintavételezése nem a bitrátának megfelelő frekvenciával, hanem nagyobb frekvenciájú gyakorisággal történik. Ezt túlmintavételezésnek (oversampling) nevezzük. Az UART0 modul esetén a túlmintavételezési arány tág határok között (4x - 32x) változtatható, míg az UART1 és UART2 modulok esetében a túlmintavételezés rögzített arányú: a Baud rate frekvencia 16-szorosával történik a bemenet mintavételezése.Az adatátviteli sebesség beállítása egy frekvenciaosztó áramkör segítségével történik, melynek osztási arányát az összefogott UARTx_BDH : UARTx_BDL regiszterpárba írt 13-bites szám adja meg (az UARTx_BDH regiszter SBR bitcsoportjába az öt legmagasabb helyiértékű bitet, az UARTx_BDL regiszterbe pedig az alsó 8 bitet kell írni). Osztási arányként 1 - 8191 közötti számot adhatunk meg. Nulla beírása esetén az UART modul adatforgalma leáll, nem érvényes osztási arány.
D7 |
D6 |
D5 |
D4 |
D3 |
D2 |
D1 |
D0 |
|
---|---|---|---|---|---|---|---|---|
UART0_BDH |
LBKDIE |
RXEDGIE |
SBNS |
SBR |
||||
UART0_BDL |
SBR |
4. ábra: UART0 órajelének előállítása
5. ábra: A SIM_SOPT2 regiszter bitkiosztása
A SIM_SOPT2 regiszter bitcsoportjai közül UART0SRC[1:0] csak az UART0 modul órajelének kiválasztására szolgál (00: órajel letiltva, 01: MCGFLLCLK vagy MCGPLLCLK/2, 10: OSCERCLK, 11: MCGIRCLK), a PLLFLLSEL bit azonban, ami az FLL vagy PLL áramkör kimenő órajelének kiválasztására szolgál (0: MCGFLLCLK, 1: MCGPLLCLK/2), más perifériák működésére is hatással lehet!
Megjegyzés: A Freescale MKL25Z128VLK4 mikrovezérlő órajelenek előállításáról és elnevezéseiről a KL25 Sub-Family Reference Manual 5. fejezetében, a SIM rendszerintegrációs modul regisztereinek szerepéről és bitkiosztásairól pedig a 12. fejezetében találunk részletes információt.
Az adatátviteli sebesség (Baud rate) az UART modul bemenő órajelének frekvenciájából, a UARTx_BDH : UARTx_BDL regiszterpárba írt SBR értékből és az OSR túlmintavételezési arányból számítható ki az alábbi képlet szerint:
Baud rate = UART modul órajel / (SBR * OSR)
Példa: 24 MHz buszfrekvencia -> 4800 baud, 16-szoros túlmintavételezéssel
SBR = 24 000 000/(4800*16) = 312.5. Ezt az értéket kerekíteni kell a legközelebbi egészre (312 vagy 313), végeredményben lesz egy kis eltérés a névleges értéktől, de az bőven belefér a tűréshatárba.
A túlmintavételezési arány megadása
Ahogy korábban említettük, az UART1 és UART2modulok esetében a túlmintavételezés mindig 16x arányú. Az UART0 modul esetében azonban 4x és 32x között változtatható. A túlmintavételezési arány eggyel csökkentett értékét az UART0_CR4 vezérlő regiszter alsó 5 bitjébe kell beírni. A regiszter többi bitjének szerepével itt nem foglalkozunk, azokat állítsuk mindig 0 értékre! Végeredményben tehát a beállítás: UART0_CR4 = OSR - 1;Megjegyzések:
- Ha az UART0_CR5 vezérlő regiszter BOTHEDGE bitjét (bit 1) '1'-be állítjuk, akkor minden órajel fel- és lefutó élénél is mintavételezzük a bemenőjelet. Alacsony túlmintavételezési arány esetén (4x - 7x) ez kötelező beállítás, a magasabb túlmintavételezési arányoknál pedig opcionális lehetőség.
- Érvénytelen túlmintavétélezési beállítás esetén az alapértelmezett 16x-os túlmintavételezés lép életbe.
A vezérlő regiszterek beállítása
Az UART modul adatformátumát, működési módját, a programmegszakítások esetleges engedélyezését a vezérlő regiszterek segítségével adhatjuk meg.D7 |
D6 |
D5 |
D4 |
D3 |
D2 |
D1 |
D0 |
|
---|---|---|---|---|---|---|---|---|
UART0_CR1 |
LOOPS |
DOZEEN |
RSRC |
M |
WAKE |
ILT |
PE |
PT |
UART0_CR2 | TIE |
TCIE |
RIE |
ILIE |
TE |
RE |
RWU |
SBK |
UART0_CR3 | R8T9 | R9T8 | TXDIR | TXINV |
ORIE | NEIE | FEIE | PEIE |
UART0_CR5 |
TDMAE |
0 |
RDMAE |
0 |
0 |
0 |
BOTHEDGE |
RESYNCDIS |
UART0_CR4 | MAEN1 | MAEN2 | M10 | OSR |
- LOOPS: Visszahurkolás/egyvezetékes (TX/RX) mód
- DOZEEN: Energiatakarékos mód engedélyezés – UART tiltása alvás módban
- RSRC: Visszahurkolás vagy egyvezetékes mód közötti választás
- M: 9-bites adatmód (8-bites mód helyett)
- WAKE: Felébresztési mód
- ILT: Tétlen vonal típusa
- PE: Paritás engedélyezés (ha 1)
- PT: Paritás (0: páros, 1: páratlan)
Megszakítás engedélyezés
- TIE: Megszakítás ha a küldő adatregiszter üres
- TCIE: Megszakítás az átvitel végén
- RIE: Megszakítás ha van beérkezett adat
- ILIE: Megszakítás, ha tétlen a vevő vonal
- TE: Adó (transmitter) engedélyezés
- RE: Vevő (receiver) engedélyezés
- RWU: a vevőt standby módba teszi, felébresztés az előírt feltételek esetén
- SBK: Break karakter (csupa nulla) küldése
- R8T9: Receive Bit 8 / Transmit Bit 9
- R9T8: Receive Bit 9 / Transmit Bit 8
- TXDIR: UART TX kivezetés adatirányának beállítása egyvezetékes módban
- TXINV: Küldött adat polaritásának invertálása
- ORIE: Megszakítás engedélyezése túlfutási hiba esetén
- NEIE: Megszakítás engedélyezése zajos jel vétele esetén
- FEIE: Megszakítás engedélyezése keretezési hiba esetén
- PEIE: Megszakítás engedélyezése paritáshiba esetén
- MAE1: Match Address 1 mód engedélyezése
- MAE2: Match Address 2 mód engedélyezése
- M10: 10-bites adatformátum választása
- OSR: Túlmintavételezési arány eggyel csökkentett értéke, 4x (00011) és 32x (11111) közötti érték lehet.
- TDMAE: Adó oldali DMA átvitel engedélyezése
- RDMAE: Vevő oldali DMA átvitel engedélyezése
- BOTHEDGE: Mintavételezés az órajel mundkét élénél
- RESYNCDIS: újraszinkronizálás tiltása
- UART0_CR1 esetében egyszerűen írjunk nullát a regiszterbe! Ez megfelel a leggyakrabban használt 8 adatbites, paritásvizsgálat nélküli, 1 stop bit formátumú átvitelnek.
- UART0_CR2 bitjei közül ebben a fejezetben csak a modul engedélyező biteket fogjuk használni:
- Konfigurálás (pl. adatátviteli arány, vagy túlmintavételezési arány megváltoztatása) előtt mind az adó, mind a vevő modult le kell tiltani a TE és RE bitek törlésével.
- Konfigurálás végeztével, használattól függően az adó vagy a vevő (vagy mindkét) modult újra kell engedélyezni a megfelelő bit (RE és/vagy TE) '1'-be állításával.
- Ebben a fejezetben az UART0_CR3 regiszter alapértelmezett (nulla) értékét fogjuk használni!
- Az UART0_CR4 regiszterbe írjuk be a választott túlmintavételezési arány eggyel csökkentett értékét, a többi bitet hagyjuk 0-nak!
- Az UART0_CR5 regiszterben szükség esetén állítsuk '1'-be a BOTHEDGE bitet, a többi bitet hagyjuk 0-nak!
A státuszregiszterek szerepe
A státuszregiszterek elsősorban az a szerepe, hogy jelezzék számunkra az UART port pillanatnyi állapotát, illetve bizonyos események bekövetkeztét. Néhány bit azonban az UART port beállítására szolgál, ezek a konfigurálásnál is szerepet játszanak.D7 |
D6 |
D5 |
D4 |
D3 |
D2 |
D1 |
D0 |
|
---|---|---|---|---|---|---|---|---|
UART0_S1 |
TTDRE |
TC |
RDRF |
IDLE |
OR |
NF |
FE |
PF |
UART0_S2 | LBKDIF |
RXEDGIF |
MSBF |
RXINV |
RWUID |
BRK13 |
LBKDE |
RAF |
- TTDRE: A küldő regiszter felszabadult, újabb adatot írhatunk bele
- TC: Adatátvitel kész.
- RDRF: Adat érkezett a vételi adatregiszterbe
- IDLE: az UART vevő bemenete tétlen már egy karakternyi ideje
- OR: Ráfutási hiba. A beérkezett adat felülírta a korábbi, még nem kiolvasottat.
- NF: Zaj jelző. A vett bitminták ellentmondásosak (túl gyors változás)
- FE: Keretezési hiba. A stop bit helyén 0-t érzékeltünk 1 helyett.
- PF: Paritáshiba a vett adatban.
Az UART0_S2 regiszter bitjeinek jelentése:
- LBKDIF: LIN (Local Interconnect Network) Break detektálás jelzőbit
- RXEDGIF: A vevő vonalon aktív él detektálás jelzőbit
- MSBF: "MSB first" mód (a legmagasabb helyiértékű adatbit áll elől) kiválasztása
- RXINV: Vételi bemenet jelének invertálása
- RWUID: A bemenet tétlen állapota figyelésének engedélyezése standby módban
- BRK13: A break karaktere hosszának beállítása, üzemmódtól függően (0: 10-13 bit), 1: 13-16 bit)
- LBKDE: LIN Break detektálás engedélyezése
- RAF: Vevő aktív (Start bit detektálás) jelzőbit
Az adatküldés és -fogadás folyamata
Mikor küldhetünk adatot?- A küldő buffer üres legyen!
- Vizsgáljuk meg az UARTx_S1 regiszter TDRE jelzőbitjét!
- Vagy használjunk megszakítást a küldéshez, ehhez azonban várakozási sorba kell pakolni az adatokat!
- Írjuk az adatot az UARTx_D regiszterbe!
- A vevő adatbuffere ne legyen üres!
- Vizsgáljuk meg az UARTx_S1 regiszter RDRF jelzőbitjét!
- Vagy használjunk megszakítást a fogadáshoz, ehhez azonban várakozási sorba kell pakolni az adatokat!
- A vett adatot az UARTx_D regiszterből olvashatjuk ki.
Mintaprogramok
Az alábbiakban elsősorban a Muhammad Ali Mazidi, Shujen Chen, Sarmad Naimi és Sepehr Naimi: "Freescale ARM Cortex-M Embedded Programming" c. könyc 4. fejezetének mintapéldáit ismertetjük, amelyek az Univerzális Soros Port egyszerű, lekérdezéses módban történő használatát mutatja be.A programokon az alábbi apró változtatásokat eszközöltük:
- A megjegyzéseket magyarra fordítottuk.
- A KEIL MDK v5.20 Real-time környezete más alapértelmezett rendszerórajel-frekvenciát (20.97152 MHz) állít be, mint amit a könyv mintapéldái feltételeznek. Ezért a késleltetéshez használt konstansokat, valamint az UART adatsebességet meghatározó, a BDH:BDL regiszterekbe írandó értéket ennek megfelelően módosítanunk kellett.
- Az UART2 esetében mi más mikrovezérlő lábakon vezetjük ki az adó és vevő (Tx/Rx) kivezetéseket.
Program4_1: Egyszerű kiíratás az UART0 soros porton
A "Yes" szöveget küldjük ki 2 másodpercenként a FRDM-KL25Z kártya UART0 Tx kimenetén keresztül a számítógép felé, az OpenSDA által biztosított virtuális soros portra. Használjunk valamilyen terminál emulátor programot (PUTTy.exe, Termite, TeraTerm stb.) az üzenetek megjelenítéséhez, az alábbi beállítással: 9600 bps, 8N1, adatfolyam vezérlés nélkül. Az UART0 vevő modulját nem használjuk, így konfiguráláskor nem is engedélyezzük.Alapértelmezetten a SystemInit() függvény 20.97 MHz FLL órajelet állít be. A programban használt BDH=0, BDL=0x88, és OSR=0x0F beállításokkal körülbelül 9600 Baud lesz a sebesség.
Az UART0 soros port az MKL25Z128VLK4 mikrovezérlő PTA1 (Rx) és PTA2 (Tx) lábain keresztül kapcsolódik az OpenSDA áramkörön keresztül a PC-re, ezért az adatküldéshez az UART0 port beállítása mellett a PTA2 kivezetést is konfigurálnunk kell.
A konfigurálás lépései:
- Engedélyezzük az UART0 modult a SIM_SCGC4 regiszter 10. bitjének 1-be állításával.
- Legyen FLL az UART0 órajel forrása: SIM_SOPT2 bit27-26 = 01 és bit16 = 0.
- Az UART0 Tx/Rx letiltása konfigurálás előtt: UART0_C2 regiszter TE=0, RE = 0.
- Az UART0 bitsebesség konfigurálása UART0_BDH és UART0_BDL beírásával.
- Túlmintavételezés konfigurálása: OSR = 16x-hoz UART0_C4-ba írjunk 0x0F-et!
- Adatformátum konfigurálása: a szokásos adatformátum (1 stop bit, nincs paritás vizsgálat, 8-bites adat) konfigurálásához egyszerűen írjunk 0x00-t az UART0_C1 vezérlő regiszterbe!
- Engedélyezzük UART0 adóját: írjunk 0x08-at az UART0_C2 regiszterbe (TE bit = 1)!
- Engedélyezzük az A portot: a SIM_SCGC5 regiszter 9. bitje legyen 1!
- Válasszuk ki a PTA2 kivezetés Alt2 funkcióját (UART0_Tx) PORTA_PCR2 MUX=2.
- Vizsgáljuk a Status Register 1 (UART0_S1) TDRE bitjét és várjunk addig, amíg a küldő buffer üressé válik (TDRE = 1)!
- Írjuk bele a kiküldendő bájtot az UART0_D adatregiszterbe!
- Újabb karakter kiküldéséhez menjünk a 10. ponthoz!
1. lista: Program4_1/main.c listája
/* Program4_1
*
* "Yes" szöveget küldünk ki 2 másodpercenként a FRDM-KL25Z
* kártya UART0 Tx kimenetén keresztül a számítógép felé
* az OpenSDA által biztosított virtuális soros portra.
*
* A program forrása: Mazidi et al., Freescale ARM Cortex-M Embedded Programming
* http://www.microdigitaled.com/ARM/Freescale_ARM/Code/Ver1/Chapter4/Program4_1.txt
*/
#include <MKL25Z4.h>
void UART0_init(void);
void delayMs(int n);
int main (void) {
UART0_init(); // UART0 kimenet inicializálása
while (1) {
while(!(UART0->S1 & 0x80)); // Várunk, míg üres lesz a kimeneti buffer!
UART0->D = 'Y'; // karakter küldés
while(!(UART0->S1 & 0x80)); // Várunk, míg üres lesz a kimeneti buffer!
UART0->D = 'e'; // karakter küldés
while(!(UART0->S1 & 0x80)); // Várunk, míg üres lesz a kimeneti buffer!
UART0->D = 's'; // karakter küldés
delayMs(2000); // Várunk egy kicsit...
}
}
/* UART0 Tx inicializálása 9600 Baud átviteli sebességre
* Baudrate = UART0 clock freq / [OSR+1] / BDH:BDL
* Esetünkben 20.97 MHz / [15 + 1] / 0x00:0x88 = 9637 bps,
* ami elfogadható eltérés a névlegestol.
*/
void UART0_init(void) {
SIM->SCGC4 |= 0x0400; // UART0 periféria engedélyezése
SIM->SOPT2 |= 0x04000000; // MCGFLLCLK választása UART0 baudrate órajelnek
UART0->C2 = 0; // UART0 letiltása a konfigurálás idotartamára
UART0->BDH = 0x00; // Baudrate = 9600 bps (bit8 - bit12)
UART0->BDL = 0x88; // Baudrate = 9600 bps (bit0 - bit7)
UART0->C4 = 0x0F; // Túlmintavételezési arány = 16
UART0->C1 = 0x00; // 8-bites adatformátum
UART0->C2 = 0x08; // Adatküldés engedélyezése
SIM->SCGC5 |= 0x0200; // PORTA engedélyezése
PORTA->PCR[2] = 0x0200; // PTA2 legyen UART0_Tx üzemmódban
}
/* Késleltető függvény: Várakozás n milliszekundumig
* A CPU rendszerórajel alapértelmezett értéke 20.97152 MHz
*/
void delayMs(int n) {
int i;
int j;
for(i = 0 ; i < n; i++)
for (j = 0; j < 3500; j++) {}
}
A program futási eredménye az alábbi ábrán látható. Mivel a kiíratás
során nem küldünk sorvége jelet, a végtelen ciklusban ismételt kiírások
szövege tagolás nélkül, "ömlesztve" jelenik meg.6. ábra: Program4_1 futási eredménye
Program4_2: Egyszerű karakter bevitel az UART0 soros porton
Karakterek fogadása a FRDM-KL25Z kártya UART0 Rx bemenetén. A vett karakter legalsó három bitjével az RGB LED színkomponenseinek ki- illetve bekapcsolt állapotát vezéreljük. A LED kezelése a Digitális ki- és bemenetek használata c. fejezet Program2_7 mintapéldájában leírtakhoz hasonlóan történik. Használjunk valamilyen terminál emulátor programot (PUTTy.exe, Termite, TeraTerm stb.) a karakterek küldéséhez, az alábbi beállítással: 9600 bps, 8N1, adatfolyam vezérlés nélkül. A kártya nem tükrözi vissza a fogadott karaktert. Ügyeljünk rá, hogy a terminál emulátor a küldött karakterekhez ne fűzzön hozzá semmilyen sorvége jelet! Például a Termite program Settings menüjében "Append nothing" beállítás kell. Az UART0 adó modulját most nem használjuk, így konfiguráláskor nem is engedélyezzük.Alapértelmezetten a SystemInit() függvény 20.97 MHz FLL órajelet állít be. A programban használt BDH=0, BDL=0x88, és OSR=0x0F beállításokkal körülbelül 9600 Baud lesz a sebesség.
Az UART0 soros port az MKL25Z128VLK4 mikrovezérlő PTA1 (Rx) és PTA2 (Tx) lábain keresztül kapcsolódik az OpenSDA áramkörön keresztül a PC-re, ezért az adatfogadáshoz az UART0 port beállítása mellett a PTA1 kivezetést kell konfigurálnunk. A konfigurálás lépései szinte szóról szóra megegyeznek az előző programná leírtakkal, változás csak a piros színnel megjelölt sorokban van.
A konfigurálás lépései:
- Engedélyezzük az UART0 modult a SIM_SCGC4 regiszter 10. bitjének 1-be állításával.
- Legyen FLL az UART0 órajel forrása: SIM_SOPT2 bit27-26 = 01 és bit16 = 0.
- Az UART0 Tx/Rx letiltása konfigurálás előtt: UART0_C2 regiszter TE=0, RE = 0.
- Az UART0 bitsebesség konfigurálása UART0_BDH és UART0_BDL beírásával.
- Túlmintavételezés konfigurálása: OSR = 16x-hoz UART0_C4-ba írjunk 0x0F-et!
- Adatformátum konfigurálása: a szokásos adatformátum (1 stop bit, nincs paritás vizsgálat, 8-bites adat) konfigurálásához egyszerűen írjunk 0x00-t az UART0_C1 vezérlő regiszterbe!
- Engedélyezzük UART0 vevőjét: írjunk 0x04-et az UART0_C2 regiszterbe (RE bit = 1)!
- Engedélyezzük az A portot: a SIM_SCGC5 regiszter 9. bitje legyen 1!
- Válasszuk ki a PTA1 kivezetés Alt2 funkcióját (UART0_Rx) PORTA_PCR1 MUX=2.
- Vizsgáljuk a Status Register 1 (UART0_S1) RDRF bitjét és várjunk addig, amíg a karakter érkezik a bufferbe (amíg RDRF = 1 nem lesz)!
- Olvasuk ki a vett karaktert az UART0_D adatregiszterből!
- Újabb karakter fogadásához menjünk a 10. ponthoz!
2. lista: Program4_2/main.c listája
/* Program4_2
*
* Karakter fogadása terminál emulátorból (PUTTy.exe,
* Termite, TeraTerm stb.) OpenSDA által biztosított virtuális
* soros porton kereeztül, a FRDM-KL25Z kártya UART0 Rx
* bemenetén. A vett karakter legalsó bitjeivel az RGB LED
* állapotát vezéreljük.
*
* A program forrása: Mazidi et al., Freescale ARM Cortex-M Embedded Programming
* http://www.microdigitaled.com/ARM/Freescale_ARM/Code/Ver1/Chapter4/Program4_2.txt
*/
#include <MKL25Z4.h>
void UART0_init(void); // UART0 Rx bemenet inicializálása
void LED_init(void); // RGB LED inicializálása
int main (void) {
char c;
UART0_init(); // UART0 Rx bemenet inicializálása
LED_init(); // RGB LED inicializálása
while (1) {
while(!(UART0->S1 & 0x20)); // Adatbeérkezésre várunk
c = UART0->D; // Kiolvassuk a vett karaktert
if (c & 1) PTB->PCOR = 0x40000; // Piros LED: BE (bit18 = 0)
else PTB->PSOR = 0x40000; // Piros LED: KI (bit18 = 1)
if (c & 2) PTB->PCOR = 0x80000; // Zöld LED: BE (bit19 = 0)
else PTB->PSOR = 0x80000; // Zöld LED: KI (bit19 = 1)
if (c & 4) PTD->PCOR = 0x02; // Kék LED: BE (bit1 = 0)
else PTD->PSOR = 0x02; // Kék LED: KI (bit1 = 0)
}
}
/* UART0 Rx inicializálása 9600 Baud átviteli sebességre
* Baudrate = UART0 clock freq / [OSR+1] / BDH:BDL
* Esetünkben 20.97 MHz / [15 + 1] / 0x00:0x88 = 9637 bps,
* ami elfogadható eltérés a névlegestol.
*/
void UART0_init(void) {
SIM->SCGC4 |= 0x0400; // UART0 periféria engedélyezése
SIM->SOPT2 |= 0x04000000; // MCGFLLCLK választása UART0 baudrate órajelnek
UART0->C2 = 0; // UART0 letiltása a konfigurálás idotartamára
UART0->BDH = 0x00; // Baudrate = 9600 bps (bit8 - bit12)
UART0->BDL = 0x88; // Baudrate = 9600 bps (bit0 - bit7)
UART0->C4 = 0x0F; // Túlmintavételezési arány = 16
UART0->C1 = 0x00; // 8-bites adatformátum
UART0->C2 = 0x04; // Adatfogadás engedélyezése
SIM->SCGC5 |= 0x0200; // PORTA engedélyezése
PORTA->PCR[1] = 0x0200; // PTA1 legyen UART0_Rx üzemmódban
}
/* RGB LED inicializálása Program2_7 alapján */
void LED_init(void) {
SIM->SCGC5 |= 0x400; // Port B engedélyezése
SIM->SCGC5 |= 0x1000; // Port D engedélyezése
PORTB->PCR[18] = 0x100; // PTB18 legyen GPIO (MUX = 1)
PTB->PDDR |= 0x40000; // PTB18 legyen kimenet (bit18)
PTB->PSOR = 0x40000; // Piros LED lekapcsolása (negatív logika!)
PORTB->PCR[19] = 0x100; // PTB19 legyen GPIO (MUX = 1)
PTB->PDDR |= 0x80000; // PTB19 legyen kimenet (bit19=1)
PTB->PSOR = 0x80000; // Zöld LED lekapcsolása (negatív logika!)
PORTD->PCR[1] = 0x100; // PTD1 legyen GPIO (MUX = 1)
PTD->PDDR |= 0x02; // PTD1 legyen GPIO (MUX = 1)
PTD->PSOR = 0x02; // Kék LED lekapcsolása (negatív logika!)
}
Sikeres programletöltés után kapcsolódjunk a kártyához a választott
terminál emulátor programmal, majd a kártya RESET gombjának
megnyomásával indítsuk el a programot! Az ABC betűin, vagy a
számjegyeken végigzongorázva váltogathatjuk a z RGB színek kombinációit
a LED-en. Az UART2 port használata USB-UART átalakítóval
A következő két példaprogramban az UART2 portot fogjuk használni, s a PTE22 (Tx), PTE23 (Rx) kivezetéseken keresztül csatlakozunk hozzá. Az MKL25Z128VLK4 mikrovezérlőt azért látták el több UART porttal, hogy olyan eszközökkel tudjon egyidejűleg kommunikálni, amelyek ilyen csatoló felülettel vannak ellátva (pl. GPS vevő, WiFi modul, másik mikrovezérlő, vagy vonalmeghajtóban illesztett LIN, esetleg MODBUS eszköz). Ebben a bevezető tananyagban természtesen nem akarunk belebonyolódni ilyen komplex projektekben, csupán arra vállalkozunk, hogy az UART2 port kezelését bemutassuk. Ezért a kommunikáció megvalósításához egy USB-UART átalakítót használunk, melyet a számítógéphez csatlakoztatunk, s az előzőekhez hasonlóan, egy terminál emulátor programmal ellenőrizzük a működést.7. ábra: FT232 USB-UART átalakító
8. ábra: Az FT232 modul bekötése UART2 használatához
Program4_3: Egyszerű kiíratás az UART2 soros porton
"Hello" szöveget küldünk folyamatosan a FRDM-KL25Z kártya UART2 Tx (PTE22) kimenetén keresztül. Használjunk egy 3,3 V jelszintű USB-soros átalakítót az üzenetek PC-re küldéséhez és valamilyen terminál emulátor programot (PUTTy.exe, Termite, TeraTerm stb.) az üzenetek megjelenítéséhez, az alábbi beállítással: 9600 bps, 8N1, adatfolyam vezérlés nélkül. Az UART2 vevő modulját most nem használjuk, így konfiguráláskor nem is engedélyezzük.Az UART1 és UART2 modul mindig a rendszerbusz órajelét használja, amelyet a SystemInit() függvény alapértelmezetten a 20.97 MHz FLL CPU órajel frekvenciájának felére, azaz 10.49 MHz-re állít be. Ennek megfelelően az előző programokban használt SBR értéket is felezni kell! A túlmintavételezési arány nem állítható (mindig 16-szoros). A programban használt BDH=0, BDL=0x44 beállításokkal tehát ugyanúgy 9600 Baud körüli lesz a sebesség, mint az előző programoknál.
Megjegyzés: Ha az RTE futtatói környezet system_MKL25Z4.h állományában nulla értékkel definiáljuk a CLOCK_SETUP makrót, akkor mind a CPU, mins a rendszerbusz frekvenciája 20.97152 MHz lesz, tehát az explicit módon megadott MCG 0 mód és az alapértelmezett beállítás különböznek! A CLOCK_SETUP makró definiálásához a system_MKL25Z4.h állományba szúrjuk be az alábbi sort:
#define CLOCK_SETUP 0 // Előre definiált beállítás: CPU és busz órajel = 20.97152 MHz
A fenti sor beszúrása után a buszfrekvencia az alapértelmezett érték duplája lesz, tehát BDH=0, BDL=0x88 beállításokkal kapunk 9600 bps adatátviteli sebességet. Mi az alábbi programnál nem definiáltuk a CLOCK_SETUP makrót, ezért az alapértelmezett (kisebb) buszfrekvenciához való BDH=0, BDL=0x44 beállítást használjuk.
Az UART2 soros portot az MKL25Z128VLK4 mikrovezérlő a PTE22 (Tx) és PTE23 (Rx) lábain keresztül kötjük az USB-UART átalaítóhoz, ezért az adatküldéshez az UART0 port beállítása mellett a PTE22 kivezetést kell konfigurálnunk.
A konfigurálás lépései nagyon hasonlóak az előzőekhez, de az UART1 és UART2 modulok esetén két lépést "megspórolunk", mivel nem kell beállítani az UART órajel forrását (az mindig a rendszerbusz órajele lesz) és nem kell megadni a túlmintavételezési arányt sem (az mindig 16-szoros lesz)
A konfigurálás lépései:
- Engedélyezzük az UART2 modult a SIM_SCGC4 regiszter 12. bitjének 1-be állításával.
- Az UART2 Tx/Rx letiltása konfigurálás előtt: UART2_C2 regiszter TE=0, RE = 0.
- Az UART2 bitsebesség konfigurálása UART2_BDH és UART2_BDL beírásával.
- Adatformátum konfigurálása: 1 stop bit, nincs paritás vizsgálat, 8-bites adat megadásához írjunk 0x00-t az UART2_C1 vezérlő regiszterbe!
- Engedélyezzük UART2 adóját: írjunk 0x08-at az UART2_C2 regiszterbe (TE bit = 1)!
- Engedélyezzük az E portot: a SIM_SCGC5 regiszter 13. bitje legyen 1!
- Válasszuk ki a PTE22 kivezetés Alt4 funkcióját (UART2_Tx) PORTE_PCR22 MUX=4.
- Vizsgáljuk a Status Register 1 (UART2_S1) TDRE bitjét és várjunk addig, amíg a küldő buffer üressé válik (TDRE = 1)!
- Írjuk bele a kiküldendő bájtot az UART2_D adatregiszterbe!
- Újabb karakter kiküldéséhez menjünk a 8. ponthoz!
3. lista: Program4_3/main.c listája
/* Program4_3
*
* "Hello" szöveget küldünk folyamatosan a FRDM-KL25Z
* kártya UART2 Tx kimenetén keresztül. Használjunk egy
* USB-soros átalakítót és valamilyen terminál emulátor
* programot az üzenetek megjelenítéséhez!
* Beállítások: 9600 bps, 8N1, adatfolyam vezérlés nélkül.
*
* A program forrása: Mazidi et al., Freescale ARM Cortex-M Embedded Programming
* http://www.microdigitaled.com/ARM/Freescale_ARM/Code/Ver1/Chapter4/Program4_3.txt
*/
#include <MKL25Z4.h>
void UART2_init(void); // UART2 kimenet inicializálása
void delayMs(int n); // Késlelteto függvény
int main (void) {
char message[] = "Hello\r\n"; // Ez lesz a kiírandó szöveg
int i; // Ciklusváltozó
UART2_init();
while (1) {
for (i = 0; i < 7; i++) {
while(!(UART2->S1 & 0x80)); // Várunk, míg üres lesz a kimeneti buffer!
UART2->D = message[i]; // Következo karakter küldése
}
delayMs(2000); // Várunk egy kicsit...
}
}
/* UART2 Tx (PTE22) inicializálása 9600 Baud átviteli sebességre
* Baudrate = bus freq / 16 / BDH:BDL
* Esetünkben 10.49 MHz / 16 / 0x00:0x44 = 9637 bps
* Megjegyzés: UART2 órajele a buszfrekvencia, túlmintavételezés aránya mindig 16
*/
void UART2_init(void) {
SIM->SCGC4 |= 0x1000; // UART2 periféria engedélyezése
UART2->C2 = 0; // UART2 letiltása a konfigurálás idotartamára
UART2->BDH = 0x00; // Baudrate = 9600 bps (bit8 - bit12)
UART2->BDL = 0x44; // Baudrate = 9600 bps (bit0 - bit7)
UART2->C1 = 0x00; // 8-bites adatformátum
UART2->C3 = 0x00; // Nincs hibainterrupt
UART2->C2 = 0x08; // Adatküldés engedélyezése
SIM->SCGC5 |= 0x2000; // PORTE engedélyezése (bit 13)
PORTE->PCR[22] = 0x0400; // PTE22 legyen UART2_Tx üzemmódban (Alt4)
}
/* Késleltető függvény: Várakozás n milliszekundumig
* A CPU rendszerórajel alapértelmezett értéke 20.97152 MHz
*/
void delayMs(int n) {
int i;
int j;
for(i = 0 ; i < n; i++)
for (j = 0; j < 3500; j++) {}
}
Apró és lényegtelen különbség, hogy itt a kiíratást egy tömbből, for
programciklus segítségével végezzük. Több karakter kiírása esetén
nyilván ez a célszerűbb megoldás. A kiírt szöveg végén egy CR+LF
(kocsi-vissza és soremelés) sorvége jelzést is küldünk , így minden
kiratás új sorba kerül. A C nyelvű programokban az \r jelenti a kocsi-vissza (0x0D), az \n pedig a soremelés (0x0A) karaktert.Program4_4: Karakter visszatükrözés az UART2 soros porton
Ez a program egy karaktert fogad az UART2 port bemenetén majd a karakter kódját eggyel megnövelve visszaírja az UART2 port kimenetére. Használjunk egy 3,3 V jelszintű USB-soros átalakítót az üzenetek PC-re küldéséhez és valamilyen terminál emulátor programot (PUTTy.exe, Termite, TeraTerm stb.) az üzenetek megjelenítéséhez, az alábbi beállítással: 9600 bps, 8N1, adatfolyam vezérlés nélkül.Az UART2 soros portot az MKL25Z128VLK4 mikrovezérlő a PTE22 (Tx) és PTE23 (Rx) lábain keresztül kötjük az USB-UART átalaítóhoz, ezért az adatküldéshez az UART0 port beállítása mellett ezeket a kivezetéseket is konfigurálnunk kell.
A konfigurálás lépései:
- Engedélyezzük az UART2 modult a SIM_SCGC4 regiszter 12. bitjének 1-be állításával.
- Az UART2 Tx/Rx letiltása konfigurálás előtt: UART2_C2 regiszter TE=0, RE = 0.
- Az UART2 bitsebesség konfigurálása UART2_BDH és UART2_BDL beírásával.
- Adatformátum konfigurálása: 1 stop bit, nincs paritás vizsgálat, 8-bites adat megadásához írjunk 0x00-t az UART2_C1 vezérlő regiszterbe!
- Engedélyezzük UART2 adóját és vevőjét: írjunk 0x0C-t az UART2_C2 regiszterbe (TE bit = 1, RE bit =1)!
- Engedélyezzük az E portot: a SIM_SCGC5 regiszter 13. bitje legyen 1!
- Válasszuk ki a PTE22 kivezetés Alt4 funkcióját (UART2_Tx) PORTE_PCR22 MUX=4.
- Válasszuk ki a PTE23 kivezetés Alt4 funkcióját (UART2_Rx) PORTE_PCR23 MUX=4.
- Vizsgáljuk a Status Register 1 (UART2_S1) RDRF bitjét és várjunk addig, amíg egy karakter érkezik a bufferbe (amíg RDRF = 1 nem lesz)!
- Olvasuk ki a vett karaktert az UART0_D adatregiszterből!
- Vizsgáljuk a Status Register 1 (UART2_S1) TDRE bitjét és várjunk addig, amíg a küldő buffer üressé válik (TDRE = 1)!
- Írjuk bele a beolvasott karakter eggyel megnövelt kódját az UART2_D adatregiszterbe!
- Újabb karakter kiküldéséhez menjünk a 9. ponthoz!
Megjegyzés: Mi az alábbi programnál nem definiáltuk a CLOCK_SETUP makrót, ezért az alapértelmezett (10,49 MHz) buszfrekvenciához való BDH=0, BDL=0x44 beállítást használjuk. Ha az RTE futtatói környezet system_MKL25Z4.h állományában nulla értékkel definiáljuk a CLOCK_SETUP makrót, akkor viszont a BDL=0x44 értéket meg kell duplázni: BDL = 0x88 kell helyette, az azonos adatsebesség beállításához!
4. lista: Program4_4/main.c listája
/* Program4_4 Uart echo
*
* Ez a program egy karaktert fogad az UART2 port bemenetén
* majd eggyel megnövelve visszaírja az UART2 port kimenetére.
* Használjunk egy USB-soros átalakítót a kapcsolódáshoz
* és valamilyen terminál emulátor programot az üzenetek megjelenítéséhez!
* Beállítás: 9600 bps, 8N1, adatfolyam vezérlés nélkül.
*
* A program forrása: Mazidi et al., Freescale ARM Cortex-M Embedded Programming
* http://www.microdigitaled.com/ARM/Freescale_ARM/Code/Ver1/Chapter4/Program4_1.txt
* Változtatások (Cserny I.):
* - Baudrate újraszámolása az eltéro busz orajel frekvencia miatt
* - Kivezetések átkonfigurálása PTE22, PTE23-ra
* - A visszatükrözött karakter kódját eggyel megnöveljuk
*/
#include <MKL25Z4.h>
void UART2_init(void); // UART2 kimenet inicializálása
int main (void) {
char c;
UART2_init();
while (1) {
while(!(UART2->S1 & 0x20)); // Karakter beérkezésre várunk
c = UART2->D ; // Beolvassuk a vett karaktert
while(!(UART2->S1 & 0x80)); // Várunk míg kiürül a küldo buffer
UART2->D = c+1; // Kiküldjük az eggyel megnövelt kódot
}
}
/* UART2 Tx (PTE22) inicializálása 9600 Baud átviteli sebességre
* Baudrate = bus freq / 16 / BDH:BDL
* Esetünkben 10.49 MHz / 16 / 0x00:0x44 = 9637 bps
*/
void UART2_init(void) {
SIM->SCGC4 |= 0x1000; // UART2 periféria engedélyezése
UART2->C2 = 0; // UART2 letiltása a konfigurálás idotartamára
UART2->BDH = 0x00; // Baudrate = 9600 bps (bit8 - bit12)
UART2->BDL = 0x44; // Baudrate = 9600 bps (bit0 - bit7)
UART2->C1 = 0x00; // 8-bites adatformátum
UART2->C3 = 0x00; // Nincs hibainterrupt
UART2->C2 = 0x0C; // Adatküldés és fogadás engedélyezése
SIM->SCGC5 |= 0x2000; // PORTE engedélyezése (bit 13)
PORTE->PCR[22] = 0x0400; // PTE22 legyen UART2_Tx üzemmódban (Alt4)
PORTE->PCR[23] = 0x0400; // PTE23 legyen UART2_Rx üzemmódban (Alt4)
}
Uart_retarget: A stdio átirányítása az UART0 soros portra
Joseph Yiu: „The Definitive Guide to ARM® Cortex®-M0 and
Cortex-M0+ Processors” c. könyvének egyik mintapéldája
(18_2_uart_retarget) alapján bemutatjuk, hogy a printf() és a scanf() függvények számára hogyan irányíthatjuk át az UART0 portra a stdio
ki- és bemenetet. Az eredeti programot némileg leegyszerűsítettük
(kiszedve belőle a LED vezérlést) és a kimenetet is átalakítottuk:
egyszerű visszatükrözés helyett kiíratjuk a vett karakter betűképét és
ANSI kódját is.A stdio átirányítására általában két lehetőség kínálkozik:
- Retargeting: néhány alacsony szintű I/O függvény felüldefiniálásával a kívánt kimenetre (UART vagy LCD) irányithatjuk a ki/bemenetet. Mi most ezt próbáljuk ki.
- Semihosting: Némelyik fejlesztői eszköz és környezet lehetővé teszi, hogy a stdio kimenet a hardveres nyomkövető egység legyen, s azon keresztül történhet adat ki- és bevitel. Ez a lehetőség azonban nem minden fejlesztőeszköznél áll rendelkezésre, viszonylag lassú, és csak debug módban használható.
Az UART0 kezeléséhez szükséges függvényeket (UART_config(), UART_putc(), UART_getc(), UART_echo(), UART_puts()) az uart_funcs.c állomány tartalmazza. Ezek ismertetésére itt nem térünk ki részletesen, hiszen ezek a függvények is lekérdezéssel, a fentebb bemutatott programokhasonlóan működik. Amire ki kell térnünk, az a konfigurálás, amit ebben a programban egy kicsit másképp csinálunk, mint korábban:
1. A mikrovezérlő órajelét most a külső kvarcot használó oszcillátor és a PLL áramkör segítségével állítjuk elő. Ez system_MKL25Z4.h állományban előre definiált rendszerórajel konfigurációk közül az 1. sorszámú beállítást jelenti. Ekkor a CPU órajele 48 MHz lesz (külső kvarccal), a buszfrekvencia pedig 24 MHz lesz. Ennek kiválasztásához új projekt létrehozásakor, a projekt lefordítása előtt a system_MKL25Z4.h állományba be kell szúrnunk az alábbi sort:
#define CLOCK_SETUP 1
2. Ahhoz, hogy az UART0 órajel forrása az így beállított 48 MHz CPU frekvencia legyen, a SIM_SOPT2 regsizter bit27-26 = 01 és bit 16 = 1 legyen!3. Lényegtelen különbség, hogy ebben a programban nem 16x-os túlmintevételezés van beállítva, hanem 4x-es túlmintavételezési arány, mindkét élen történő mintavételezéssel.
A projekthez csatolt retarget.c állománynak köszönhetően felüldefiniálásra kerülnek a fputc(), fgetc() és ferror() függvények. Ez azt jelenti, hogy a főprogramban az UART_config() meghívása után a kiíratásokhoz használhatjuk a printf(), a beolvasásokhoz pedig a scanf() függvényt.
A program induláskor kiír egy üdvözlő üzenetet, majd egy név beírására vár. A beírást szóköz karakter begépelésével lehet lezárni. Ezután a program visszatükrözi a beírt nevet, majd elkezdődik a végtelen ciklus. A ciklusban minden karakterre visszaírjuk a karaktert, majd a karakter ANSI kódját is.
Megjegyzések:
- Ha egyszerre 2-3 karakternél többet küldünk, a vevő lefullad (valószínűleg ráfutási hiba miatt). Mivel a programunkban a soros porti kommunkációbal kapcsolatos hibák nincsenek lekezelve, az UART modul újraindulásig nem fogad újabb karaktert.
- Ebben a programban kivételesen az alapértelmezettől elérő adatküldési sebességet használunk, ezért a terminál emulátor programot 38400 Baud sebességre kell állítani!
#include <MKL25Z4.H>
#include "stdio.h"
// System runs at 48MHz
// Baud rate 38400, 8 bit data, no parity, 1 stop bit
// UART functions
extern void UART_config(void);
extern char UART_putc(char ch);
extern char UART_getc(void);
extern void UART_echo(void);
extern void UART_puts(char * mytext);
int main(void) {
char txt_buf[100];
char c;
SystemCoreClockUpdate();
UART_config();
printf("\r\nWelcome to FRDM-KL25Z board!\r\n");
printf("Please enter your name:");
scanf("%99s", txt_buf);
printf("\nName entered :[%s]\n", txt_buf);
while(1){
c = UART_getc(); //Read one character
printf("received char: %c = %d\r\n",c,c);
}
}
9. ábra: Az Uart_retarget program futási eredménye
Felhasznált anyagok és ajánlott olvasmányok:
- Joseph Yiu: The Definitive Guide to ARM® Cortex®-M0 and Cortex-M0+ Processors (2nd Ed.)
- Muhammad Ali Mazidi, Shujen Chen, Sarmad Naimi, Sepehr Naimi: Freescale ARM Cortex-M Embedded Programming
- ARM University Program: Course/Lab Material for Teaching Embedded Systems/MCUs (for the FRDM-KL25Z board)
- Trevor Martin: The Designer’s Guide to the Cortex-M Processor Family
- Freescale: MKL25Z128VLK4 MCU datasheet
- Freescale: KL25 Sub-Family Reference Manual
- Freescale: FRDM-KL25Z User Manual