Dál budeme potřebovat nějaký vhodný software do PC pro příjem a vysílání znaků. Osobně používám nejraději stařičký TELIX, ale je možné použít například Hyperterminál přímo ve Windows - není to nic světoborného, ale je to použitelné. Mimo jiné uvádím na konci stránky další program pro komunikaci pomocí sériové linky ke stažení. Nastavení programu pro zde uváděné příklady je vidět na obrázku vlevo.
Je třeba nastavit použitou Baudovou rychlost (Baud - zkratka Bd je počet bitů za sekundu - zde 19200), nastavit použitý port (já zde mám COM4), no a parametry přenosu - tedy 8 datových bitů, bez parity a jeden STOP bit. Pak ještě musíme nastavit "handshaking" na NONE (přesný překlad je "potřásání rukou" - jedná se o druh komunikace, kdy nadřízený systém vyšle dotaz a čeká na odpověď - u jednoduché komunikace to nepoužíváme. Jde o pojem řízení toku, což je možno najít i ve správci zařízení ve Windows - toto řízení toku je třeba vypnout - tedy zde to vypneme v nabídce a program to zabezpečí za nás, pokud pouzžijeme jiný software je třeba na to pamatovat. Pokud totiž necháme povolenou volbu např. řízení toku hardwarem, může dojít k tomu, že PC čeká na nahození linky DTR, RTS - tyto linky se používají právě k řízení "plnokrevné" komunikace na sériovém portu - je to použito například u modemu. No a pokud toto zůstane nastaveno, a my to nepoužijeme, nemusí nám komunikace fungovat vůbec, prostě proto, že PC čeká na změnu na těchto signálech, které ale my nevyužíváme. Jako poslední věc je třeba ručně zapnout právě signály DTR a RTS trvale - jsou totiž použity pro napájení kompaktního převodníku -je napájen díky nízké spotřebě z těchto signálů a pokud zůstanou vypnuté, nebude převodník napájen. |
Nyní se již můžeme "po hlavě" vrhnout do prvního pokusu. Nejprve je vhodné si např. na nepájivé pole zapojit klasické zapojení procesoru (krystal - POZOR ZMĚNA 11,059200 MHz, reset - kondenzátor, napájení atd.) například 89C2051 (když jsme již začli s těmi ATMELy). Dál propojíme přijímací a vysílací linky. Je vhodné si nejprve vyzkoušet komunikaci směrem od / do PC. To
se nejlépe vyzkouší tak, že spustíme terminál v PC, a na straně TTL (kterou posléze připojíme do mikroprocesoru) spojíme přijímací a vysílací vodič. Po stisku klávesy (resp. odeslání znaku) se musí ten samý znak objevit v přijímacím okně terminálu. Pokud tomu tak není, je třeba zkontrolovat převodník, popřípadě je možné opět zkusit propojení TxD (vysílací - transmitt) a RxD (přijímaci - receive) linky
přímo v PC.
Jestliže je vše v pořádku, připojíme si linky k procesoru. Nezapomeňte, že se vždy připojuje vysílací linka na přijímací a obráceně přijímací na vysílací. Leckomu to přijde logické , nespojovat proti sobě dvě vysílací linky, ale již jsem "opravoval" na dálku několik zaručeně zkontrolovaných konstrukcí, které měli jen prohozené vysílací a přijímací linky. Tak....hotovo ? Budeme pokračovat trochu obráceně. Nejprve si program vyzkoušíme a pak si k tomu něco řekneme. |
$MOD51 ORG 0000H JMP Init ORG 0030H ;============================================================ ; hlavní program ;============================================================ Init: mov sp,#35H mov scon,#01010000B ;nastavení ser.linky+časovače1 mov tmod,#00100000B ;19200 bps,8 databit,1 stopbit,bez parity mov 87H,#10000000B ;zdvojnásobení rychlosti (nastaví bit SMOD) mov th1,#253 ;časovač mód 2,ser.linka mód 1 setb TR1 mov R0,#'T' call vysilani mov R0,#'e' call vysilani mov R0,#'s' call vysilani mov R0,#'t' call vysilani mov R0,#' ' call vysilani mov R0,#'R' call vysilani mov R0,#'S' call vysilani mov R0,#'2' call vysilani mov R0,#'3' call vysilani mov R0,#'2' call vysilani jmp $ vysilani: clr ti ;nulování příznaku dokončeného odvysílání mov sbuf,r0 ;vysílání obsahu R0 jnb ti,$ ;čekání na odvysílání clr ti ;nulování příznaku dokončeného odvysílání ret END |
Po naprogramování čipu zkontrolujte zapojení a propojte sériovou linku (stačí RxD převodníku resp. PC a TxD pin procesoru). V PC spusťte terminál a nastavte parametry programu - komunikační rychlost 19200 bitů za sekundu (19200 kBd), 8 datových bitů, bez parity, 1 stop bit.
Nyní připojte napájení procesoru. Pokud máte vše správně zapojeno, musíte na obrazovce PC číst text: Test RS232. Pro opakované vypsání je třeba resetovat procesor. Nyní se vrátím k popisu programu. Vlastní vysílání je velmi jednoduché. Nejprve se nastaví parametry linky - je třeba nastavit mód linky - zde mód 1 (více o módech na jiné stránce tohoto webu) - v registru SCON. Pro časování sériové linky je použit TIMER1. Dále povolíme příjem (nastavení bitu REN v SCON) - zde není příjem sice použit, ale to nám nevadí. Následně nastavíme časovač 1. V byte TMOD je nakonfigurován jako 8 bitový čítač s automatickou předvolbou - MÓD2 (více o této volbě se dočtete na jiné stránce tohoto webu). To znamená, že časovač běží, maximalní dosažitelná hodnota je 8-mi bitová (256) - pro čítání je použit dolní byte timeru - TL1. Po přetečení a vyvolání přerušení je v tomto módu automaticky do časovače uložena předvolba z vyššího byte časovače - TH1. Byte TH1 je tedy využit jen a pouze pro uchovávání předvolby časovače (pevně doufám, že víte co to znamená, pokud se řekne předvolba časovače - ne ? ajajaj, pak si to tedy nastudujte třeba zde). Ještě jedna věc ohledně časovače - při tomto použití časovače se nepovoluje generování přerušení od tohoto časovače ! Časování UARTu je interně ovládáno. Vždy se tedy jen nastaví parametry časovače, a časovač se spustí. Jako předposlední věc nastavíme bit SMOD v registru PCON (na adrese 87H) pro zdvojnásobení komunikační rychlosti. Jako poslední věc nastavíme předvolbu časovače 1 na 253 decimálně (0FDH) - proč zrovna tuto hodnotu se dozvíte na stránce popisu UARTu. No a spustíme časovač nastavením bitu TR1. To je vše, a více se o časovač starat nebudeme. |
0041 7854 28 mov R0,#'T' 0046 7865 30 mov R0,#'e'T má ASCII reprezetaci 54 - což je v prvním řádku za kódem instrukce 78, no a znak malé e má ASCII reprezentaci 65, což opět vidíme v druhé řádce zase za kódem instrukce.
$MOD51 ORG 0000H JMP Init ORG 0030H ;============================================================ ; hlavní program ;============================================================ Init: mov sp,#35H mov scon,#01010000B ;nastavení ser.linky+časovače1 mov tmod,#00100000B ;19200 bps,8 databit,1 stopbit,bez parity mov 87H,#10000000B ;zdvojnásobení rychlosti (nastaví bit SMOD) mov th1,#253 ;časovač mód 2,ser.linka mód 1 setb TR1 main: jnb ri,$ ;cekej na znak z linky mov a,sbuf ;nacti hodnotu z UARTU do akumulatoru clr ri ;nuluj flag ;----------------------------------------------------------- mov R0,#'(' call vysilani mov R0,ACC ;prijatou hodnotu uloz do R0 call vysilani ;a odesli mov R0,#')' call vysilani jmp main vysilani: clr ti ;nulování příznaku dokončeného odvysílání mov sbuf,r0 ;vysílání obsahu R0 jnb ti,$ ;čekání na odvysílání clr ti ;nulování příznaku dokončeného odvysílání ret END |
Takže nastavení je totožné jako z minulého příkladu. Ohledně hardware musíme nyní již propojit obě komunikační linky (RxD čipu TxD PC a TxD čipu na RxD PC - samozřejmě přes převodník úrovni). Na začátku se neustále testuje příznak RI, který svým nastavení signalizuje dokončení příjmu znaku přes sériovou linku. Po nastavení RI je možno přečíst znak z bufferu SBUF. Takže jakmile je příznak nastaven, víme, že přišel znak. Znak z bufferu SBUF přesuneme do akumulátoru a následně vynulujeme příznak RI (příznaky RI a TI se musí nulovat softwarově na rozdíl od ostatních příznaků). Následně vyšleme zpět do terminálu v PC závorku, dále odešleme přijatý znak, který máme v akumulátoru a nakonec odešleme uzavírací závorku. Po jejím odeslání se vrátíme zpět na začátek (jmp main) a čekáme na další příchozí znak. Výsledkem tohoto krátkého prográmku je to, že vrátí do terminálu v PC znak, který jsme odeslali uzavřený v závorkách např. odešleme písmeno A, vrátí se (A). Na tomto asi není dále co vysvětlovat, zkuste si prográmkem pohrát, zkusit například odeslat přijatý znak mezi hvězdičkami a podobně. Případně si můžete zkusit napsat rutinu tak, aby přijímala dva znaky a po příjmu druhého odeslal zpět oba znaky do PC. |
$MOD51 ORG 0000H JMP Init ;-------------------------------------------------- ORG 23H jmp prerus_uart ;-------------------------------------------------- ;-------------------------------------------------- LED equ P1.2 ;vystup LED ;-------------------------------------------------- ORG 0030H ;============================================================ ; hlavní program ;============================================================ Init: mov sp,#35H mov scon,#01010000B ;nastavení ser.linky+časovače1 mov tmod,#00100000B ;19200 bps,8 databit,1 stopbit,bez parity mov 87H,#10000000B ;zdvojnásobení rychlosti (nastaví bit SMOD) mov th1,#253 ;časovač mód 2,ser.linka mód 1 setb TR1 setb ES ;povol int od uartu ale ne globalne setb EA ;povol preruseni globalne ;---------------------------------------------------------------- ;=============================Hlavni smycka================================= main: setb LED zacatek:cpl LED mov R3,#167 cas_1: mov R2,#171 cas_2: mov R1,#16 cas_3: djnz R1,cas_3 djnz R2,cas_2 djnz R3,cas_1 sjmp zacatek ;============================================================================ vysilani: clr ti ;nulování příznaku dokončeného odvysílání mov sbuf,r0 ;vysílání obsahu R0 jnb ti,$ ;čekání na odvysílání clr ti ;nulování příznaku dokončeného odvysílání ret ;------------------------------------------------------------ ;*************************Obsluha preruseni************************************* prerus_uart: push ACC ;uloz hodnotu v akumulatoru push PSW ;uloz stavove slovo jnb ri,navrat ;preruseni od prijmu ? (muze byt vyvolano i vysilanim) mov a,sbuf ;nacti hodnotu z UARTU do akumulatoru clr ri ;nuluj flag ;------------------------------------------------------------ mov R0,#'(' call vysilani mov R0,ACC ;prijatou hodnotu uloz do R0 call vysilani ;a odesli mov R0,#')' call vysilani navrat: pop PSW pop ACC reti ;------------------------------------------------------------ END |
Příjem znaku v přerušení je poněkud složitější, ale v podstatě použijeme znalosti z minulého příkladu. Příklad bude opět vracet znaky uzavřené v závorce. Navíc, aby bylo dostatečně ilustrované to,
že procesor stále "dělá" něco jiného v hlavní smyčce, a při příjmu znaku "si odskočí" udělat obsluhu přerušení je v hlavní smyčce rutinka blikání LED diodou na portu P1.2 (vývod 14 procesoru).
Funkce programu je následující. Na začátku je povoleno přerušení od sériové linky a globální přerušení (tím se povolují/zakazují všechna přerušení). V hlavní smyčce programu je tedy rutinka blikání LED diodou pomocí časové smyčky. Nyní, jestliže přijde po sériové lince znak (data) je nastaven příznak RI a vyvoláno přerušení. Program odskočí z vykonávání blikání na adresu 23H. To je tzv. vektor přerušení sériové linky. Na tuto adresu program vždy skočí, pokud je vyvoláno přerušení od sériové linky. Tato adresa je pevně definovaná výrobcem (více na jiné stránce tohoto webu), tak jako adresy (vektory) od jiných zdrojů přerušení (časovačů, externích vstupů přerušení atd.). Protože vektory jsou relativně blízko u sebe (mám na mysli adresy) vzhledem k programu se na tyto adresy umisťují skoky na obslužné rutiny toho kterého přerušení. My si tedy na adresu vektoru od sériové linky umístíme instrukci skoku na rutinu prerus_uart. Program po příjmu znaku tedy skočí na adresu 23H, následuje skok na rutinu prerus_uart. Na počátku této rutiny se nejprve uschová obsah akumulátoru a stavové slovo (tohle již známe z kapitoly o přerušení). Dále je nutno zjistit, odkud přerušení vzešlo. Jde o to, že přerušení od sériové linky může být vyvoláno jak odesláním, tak příjmem znaku a tyto dvě věci si musí programátor ošetřit sám. Takže otestujeme příznak příjmu RI. Pokud není nastaven, přišlo přerušení od jiné vnitřní periferie, a následuje návrat z obsluhy přerušení bez činnosti. Jestliže je příznak RI nastaven, signalizuje nám to příjem znaku - resp. to že přijatý znak je v přijímacím bufferu. My nejprve přesuneme hodnotu z registru SBUF do akumulátoru a následně smažeme programově příznak RI (clr RI). Tento příznak jako jediný (kromě TI) se musí nulovat programově (nenuluje jej hardware procesoru při obsluze přerušení tak při obsluze ostatních periferií jádra). |
;-------------------------------------------------- LED equ P1.2 ;vystup LED zap BIT 0 ;-------------------------------------------------- zacatek:jnb zap,zacatek cpl LED mov R3,#167 cas_1: mov R2,#171 cas_2: mov R1,#16 cas_3: djnz R1,cas_3 djnz R2,cas_2 djnz R3,cas_1 sjmp zacatek ;-------------------------------------------------- ;--v preruseni----- mov R0,#'(' call vysilani mov R0,ACC ;prijatou hodnotu uloz do R0 call vysilani ;a odesli mov R0,#')' call vysilani cjne A,#'z',druhy_test setb zap jmp navrat druhy_test: cjne A,#'v',navrat clr zap |
V hlavičce si nadefinujeme příznak - jeden bit v bitově adresovatelné části paměti RAM. Tento bit můžeme nahodit do H, shodit do L, popřípadě jeho stav otestovat. V hlavní smyčce programu tento příznak testujeme a pokud není nastaven, blikání se nekoná (jnb zap,zacatek = jump not bit = pokud není nastaven bit zap, skoc na návěští zacatek) -prostě pokud je bit vynulován, smyčka stojí na jednom místě. Jestliže v přerušení bit nastavíme do log. H, pak po návratu smyčka normálně pokračuje dál. Nastavování a nulování příznaku je v rutině přerušení provedeno po odeslání odpovědi v závorkách do PC. Přijatý znak máme uložený v akumulátoru, provedeme tedy test CJNE - nejprve pokud se přijatý znak nerovná z skoč na návěští druhy_test. Pokud se znak rovná z, instrukcí setb zap se příznak nastaví a následuje návrat z přerušení. Jestliže přijatý znak nebyl z, pak se testem za návěštím druhy_test otestuje, zda je přijatý znak v. Pokud ano, pak se instrukcí clr zap příznak vynuluje, a následuje návrat z přerušení. Pokud znak nebyl ani z, ani v, je proveden návrat z přerušení beze změny příznaku. Kompletní kód rutiny naleznete v archivu se zdrojovými kódy na konci stránky ke stažení. |
| Příklady - ASM i HEX soubor a schémata | |
| Terminal - program pro komunikaci přes sériovou linku |
© DH servis 2002 - |