softwarový sér. port u AT89C51ED2

Zdravim,

nechcem moc cerit tiche vody typu “delay_us”, ale prave taketo riesenia
dehonestuju vybavu hw periferii jednocipakov.

Myslim, ze vacsinou sa od procesora ocakava, ze ak komunikuje, to automaticky neznamena, ze nema robit nic ineho (AD prevody, filtracia signalu, zobrazovanie na LCD, interakcia s tlacitkami, vypocty regulacnych sluciek, atd, atd). Obzvlast, ak caka na prijem nejakej spravy.

SW uart moze byt napisany tak ako bolo uvedene vyssie, ale ak je to mozne, za systemovejsie riesenie povazujem vyuzit HW vybavu procesora.
Konkretne na x51 (ale aj na ine typy) je dobre pouzit interupt od casovaca.
Predpokladam, ze MCU najprv caka na nejaku spravu od PC a potom na nu odpoveda, komunikacia typu 8N1.

Prijem:
Vstupny pin casovaca T vyuzijem na RX. 8b casovac nastavim do modu pocitania vstupnych impulzov a do pocitadla mu vlozim hodnotu 0xff. Prichodom dobeznej hrany na pine casovac pretecie a vyhodi prerusenie. Nie je teda potrebne obetovat na RX nejaky iny pin s funkciou INT.
V tomto preruseni zmenim mod citaca/casovaca na casovac a prednastavim cas na 1/2 Bd rychlosti. Samozrejme s prerusenim.
Po druhom preruseni otestujem, ci je vstupny signal v log.0. Ak ano, udalost prehlasim za platny start bit. Do predvolby nastavim cas 1 Bd rychlosti.
Postupne pride 8 preruseni. V kazdom z nich otestujem hodnotu pinu procesora (vstup pre T) a ulozim do nejakeho bajtu ako platne bity.
Pockam na deviate prerusenie. Ak je hodnota pinu 1, jedna sa o platny stop bit, prijaty bajt mozem ulozit do komunikacneho bufera - akoby mi prislo prerusenie od UARTu a celu cinnost opakujem.

Vysielanie:
Ten isty citac / casovac, ktory som pouzival pri prijme vyuzijem na odpocet vyslania bajtu. Predpokladam komunikaciu typu poloduplex.
Ak komunikujem cez budic RS485, prepnem smer na vysielanie (iny pin ako RX a TX.)
Pin procesora (iny ako som pouzil na RX, ale v zasade lubovolny) nastavim na log.0 (start bit), do predvolby vlozim cas 1 Bd rychlosti. Postupne pride 8 preruseni. V kazdom z nich nastavim na vystup prislusny bit z vysielaneho bajtu. Po deviatom preruseni nastavim pin na log.1 - stop bit. Ak komunikujem cez RS 232, cinnost ukoncim/pokracujem v odvysielani dalsieho bajtu, ak cez RS485, pockam na desiate prerusenie a otocim smer budica RS485 na prijem, ak uz nie je potrebne odvysielat dalsi bajt.

Ak komunikujem rychlostou 38400/9600Bd, potom cas medzi jednotlivymi bitmy je cca 26/104us.Osobne robim s ATmega (14.7456MHz) a tie za tu dobu urobia 383/1533 instrukcii. A to je naozaj dost dlha doba, aby sa procesor len tak flakal v nejakej zapraskanej casovej slucke. Okrem toho C prekladac program optimalizuje a bezduche casove slucky (ak nie su asm volatile) optimalizuje, pripadne cele vyhadzuje. s tym maju hlavne zaciatocnici psychicke problemy typu - ved som to tam napisal, tak preco to ten “blby” prekladac vyhadzuje a upravuje. No preto, lebo to nie je ASM a od prekladaca primarne chceme, aby nase programatorske “blaboly” optimalizoval do hustejsieho a rychlejsieho kodu. A pri rozne zapnutych optimalizaciach budu prirodzene casove/velkostne vysledky rozne.
Preto celkovo v C doporucujem sa funkciam typu delay_ms/us vyhybat (aj ked principialne sa pouzit daju, akurat brzdia cely procesor) a naucit sa vyuzivat ine prostriedky, ktore su na casove funkcie v jednocipoch urcene.

Horeuvedeny postup je uplne nezavisly, ci programujem v ASM, alebo v C.