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.