AVR1 - 03 program - soros port echo

2008-02-05

 

A harmadik program ismertetését egy kis technika történeti visszaemlékezéssel kezdem. Réges-régen, egy másik évszázadban, de amikor már az emberek használtak számítógépeket... nem ismerték még a video kártyákat, a directx-et és egyéb csacskaságokat. Különböző megoldásokat használtak a lyukkártyától kezdve, a nyomtatott listákon, a teletype-on keresztül a terminálokig. A terminál tulajdonképpen adatvégállomást jelent. A mi esetünkben egy olyan billentyüzettel ellátott CRT (Chatod Ray Thube) monitort, amit egy soros vonalra lehetett csatlakoztatni. A terminál billentyűzetén beklimpírozott betüket/karaktereket elküldte soros vonalon, és a soros vonalon érkező karaktereket pedig képes volt megjeleníteni a képernyőn. Ebben az időben (198x) piacvezető cég volt a Digital Equipment, amely úgy reklámozta magát, hogy képes bármely számítógépes rendszert összekötni bármely másikkal (internetünk sem volt). Az ő nevükhöz fűződtek a PDP és VAX számítógép családok. És szintén hozzájuk fűzűdtek a teljesség igénye nélkül a VT52, VT100, VT220 terminálok. A máig legelterjedtebb, vagy fennmaradt terminál szabvány a VT100-as. Tehát, az akkori számítógépek kicsit másképpen működtek. Nem volt integrált videó kártyájuk, billentyűzet/egér portjuk. Mindössze egy soros porton keresztül tartották a kapcsolatot a kezelővel, akit operátornak hívtak. Az operátor bepötyögte a parancsait. És ez csak akkor látszott meg a képernyőn, ha a számítógép ugyanezeket karaktereket megjelenítésre visszaküldte a terminál képernyőjére. Ezt hívják echo-nak, vagyis hogy a gép visszhangozza a neki küldött karaktereket. Azután a számítógép a válaszát szintén a képernyőre küldte ki. Nagyon egyszerűnek, sőt talán primitívnek látszik, de ilyen VT52 terminálon már elérhető volt egész képernyős szövegszerkesztő (PDP11/RT11 KEX, kb. mint PC/DOS PE2, vagy NE2), és először ilyen terminálon játszottam TETRIS-t. Kezdetben a terminálok funkciója egegyezett a sornyomtatóéval, azzal a különbséggel, hogy nem használt papírt. Később továbbléptek az interaktivitás felé, és terminálok programjait kiegészítették ESC szekvenciákkal, parancsokkal, amelyek lehetővétették példáúl a kurzor pozícionálását a képernyőn. Ezért hivatkozunk mondjuk a VT100-as terminálra, mert ebben az esetben azokat a parancsokat kell kezellni tudni, amit az egykori VT100-as terminálok is fel tudtak dolgozni. Manapság persze már mindenre PC-ket használunk. Sajnos Linux-kat nem nagyon ismerem, de MS Win rendszerek alatt megtalálható a HiperTerminál, és szabadon letölthető a talán legjobb TeraTerm. Szerintem ez a kis ismertető sok ember hasznára vált, de a kis panelunkkal továbbra is a TeraTerm . Szerintem ez a kis ismertető sok ember hasznára vált, de a kis panelunkkal továbbra is a Bray's Terminal -on kersztül tartsuk a kapcsolatot, mert ilyen célra szerintem ez alkalmasabb.

A harmadik programban új elem, hogy a karakter küldés külön függvénybe került. A függvényeket a program elején deklarálni kell, akár a globális változókat, hogy a fordító program tudja, hogy milyen adatokat vár, illetve, hogy milyen adatokat ad vissza. Ha függvényeket befordítják library-kba, ezek a definíciók kerülnek ki header file-kba, hogyha meghívjuk ezeket a függvényeket a programunkból, a fordító program tudja, hogy az adott függvény mit vár tőlünk, és mit ad vissza. Szintén új elem a megszakítás kezelés (Interrupt, IT). Az IT azt jelenti, hogy meghatározott eseményekre a processor megszakítja a program futását, elmenti a regiszterek értékét az ugynevezett verembe (stack), és egy előre meghatározott másik programrészen folytatja a futását, az adott IT-t lekezelő rutinon. Nézzük át az ATtiny2313 dokumentációját (bekukkanthatun a attiny2313.h-ba is). Körülbelül 20 féle esemény válthat ki IT-t. Ezeket egyenként előzőleg engedélyeznünk kell, továbbá a General IT-t is. A General IT-nek az az értelme, ha kritikus időzítésű programrészt futtatunk, közben letiltjuk az összes IT esemény kezelését. Ebben a programban csupán a soros portra bejövő karaktert figyeljük, és csupán annyit teszünk, ha bejön egy karakter, rögtön visszaküldjük. Tehát ha valamit begépelünk a terminálunk billentyűzetén, az kiíródik a képernyőjén is. Érdekes továbbá, hogy maga a főprogramun tulajdonképpen nem csinál semmit.

Ha valaki megnézegeti az ASM listát is (.lss), akkor érdekes, hogy a fordító program kioptimalizálja a függvény hívást, subrutin hívás helyett beleszerkeszti a karakter küldést a IT kezelő rutinba. Ennek az a magyarázata, hogy egy szubrutin híváshoz gondoskodni kell az átadandó adatról, menten kell a regiszterek tartalmát, át kell ugrani a szubrutinra, le kell futtatni, vissza kell ugrani, vissza kell állítani a regisztereket, vissza kell adni az adatokat (boccs a sorrend nem jó), szóval sokkal több utasításból áll.



/*******************************************************************************
*   Author       -  3 BYTE MI                                                  *
*                   http://haromb.freeweb.hu                                   *
*   Date         -  2008.12.30.                                                *
*   Chip         -  Atmel ATtiny2313                                           *
*   Hardware     -  AVR1 tesztpanel                                            *
*   Compiler     -  avr-gcc (WinAVR 20080610) 4.3.0                            *
*                                                                              *
*   LED2 labat kimenetre allitja, es LED2-t bekapcsolja.                       *
*   USART-ot (soros port) 9600 baud 8 bit no parity 1 stop bit-re allitja.     *
*   USART-ra erkezo karaktereket echo-zza (visszakuldi).                       *
*                                                                              *
********************************************************************************
*   PonyProg Configuration and Security Bits - bepipalva:                      *
*   Belso 4MHz-es osszc.:     SUT0, CKSEL3, CKSEL2, CKSEL0                     *
*   Kulso keramia rezonator:  SUT0                                             *
*                                                                              *
*******************************************************************************/
#include "attiny2313.h"
#include 




#define UC                   unsigned char


// lasd sfr_defs.h 
#define BS(bit)              |= ( 1 << ( bit))             // egy byte adott bitjenek 1-re allitas
#define BC(bit)              &= ~( 1 << ( bit))            // egy byte adott bitjenek 0-ra allitas
#define BTS(sfr,bit)         bit_is_set( sfr, bit)         // egy regiszter egy bitjenek vizsgalata 1-re
#define BTC(sfr,bit)         bit_is_clear( sfr, bit)       // egy regiszter egy bitjenek vizsgalata 0-ra


#define MHz                  000000
#define kHz                  000


#define IT_ENABLE            __asm__ __volatile__ ("sei" ::)    // megszakitas tiltasa
#define IT_DISABLE           __asm__ __volatile__ ("cli" ::)    // megszakitas engedelyezese
#define NOP                  __asm__ __volatile__ ("nop" ::)    // egy ures utasitas beszurasa


// USART inicializalasahoz, kezelesehez

// UCSRA beallitasai
#define DOUBLE_SPEED         0B00000010
#define MULTIPROC            0B00000001

// UCSRA lekerdezese
#define RX_ERROR             UCSRA & 0B00011100  // hiba lekerdezese, 0 - nincs hiba
#define RX_COMPLETE          BTS( UCSRA, 7)
#define TX_COMPLETE          BTS( UCSRA, 6)
#define UDR_EMPTY            BTS( UCSRA, 5)

// UCSRB beallitasai
#define IT_RX_DISABLE        0
#define IT_RX_ENABLE         0B10000000
#define IT_TX_DISABLE        0
#define IT_TX_ENABLE         0B01000000
#define IT_UDR_EMPTY_DISABLE 0
#define IT_UDR_EMPTY_ENABLE  0B00100000
#define RX_DISABLE           0
#define RX_ENABLE            0B00010000
#define TX_DISABLE           0
#define TX_ENABLE            0B00001000

// UCSRC beallitasai
#define ASYNCRON             0
#define SYNCRON              0B01000000
#define PARITY_NO            0
#define PARITY_EVEN          0B00100000
#define PARITY_ODD           0B00110000
#define STOPBIT_1            0
#define STOPBIT_2            0B00001000
#define BIT_5                0
#define BIT_6                0B00000010
#define BIT_7                0B00000100
#define BIT_8                0B00000110


// PORTD bitjei
#define SW1                  5
#define SW2                  6
#define LED1                 3
#define LED2                 4


// LED-ek vezerlese
#define LED1_ON              PORTD BC( LED1)
#define LED1_OFF             PORTD BS( LED1)
#define LED2_ON              PORTD BC( LED2)
#define LED2_OFF             PORTD BS( LED2)


// kapcsolok lekerdezese
#define SW1_ON               BTC( PIND, SW1)     // SW1 lenyomva?
#define SW2_ON               BTC( PIND, SW2)     // SW2 lenyomva?


#ifndef F_CPU
#define F_CPU                4MHz
#endif


#define BAUDRATE             9600




void usart_putc( UC);




ISR( USART_RX_vect)                              // USART veteli megszakitas vektor
{
   usart_putc( UDR);
}




void usart_putc( UC c)                           // USART egy karakter kuldese
{
   while( !UDR_EMPTY);                           // ha tudja fogadni a kovetkezo karaktert
   UDR= c;
}




int main( void)
{
   DDRD BS( LED2);                               // szukseges labak kimenetre allitasa
   LED2_ON;

   UBRRL= ( F_CPU/( BAUDRATE* 16UL))- 1;         // USART inicializalasa
   UBRRH= (( F_CPU/( BAUDRATE* 16UL))- 1)>> 8;
   UCSRC= ASYNCRON+ BIT_8+ PARITY_NO+ STOPBIT_1;
   UCSRB= RX_ENABLE+ TX_ENABLE+ IT_RX_ENABLE;

   IT_ENABLE;

   for( ;;);
   return 0;
}

Itt a vége, fuss el véle, legytek az én vendégeim, innen letölthetitek a hozzávalókat összecsomagolva.