AVR1 - 02 program - kapcsolók visszajelzése soros porton

2008-02-03

 

A második programban felélesztjük a kommunikációt a PC és AVR1 tesztpanelünk között. Igaz még csak egy irányba, a paneltől a PC felé. Ehez szükségünk lesz a soros kábelre és egy terminál programra. Számomra legcélszerűbb eszköz a már korábban is említett Bray's Terminal. Elég egyszerű a használata. Előszőr állítsuk be ugyanazokat a paramétereket, amelyeket a panelunkba is beállítunk (9800 bit, no parity, 1 stop bit). Majd kattintsunk a CONNECT gombra. Ha minden ok, a két gomb nyomogatására 1-eseket és 2-eseket kell megjelenni a képernyőnkön. Hiba esetén most jó segítség lehet a panelra helyezet két LED, amelyek mutatják a kimenő illetve a bemenő vezetékek állapotát. Ha a mikrovezérlőnk ad, akkor L4 felvillan. Ha bejövő jel van, akkor L3 villog. Most talán feleslegesnek tűnik ez a két plusz LED, de majd akkor fogjuk igazán megbecsülni, ha egy műhely koszos, hozzáférhetetlen sarkában kell életet lehelnünk a berendezésünkbe (többi lehetetlen helyszin felsorolása fakultatív feladat :).

Néhány definícióval bővült a programunk, amelyeket a későbbiekben átrakok a header file-ba. A feladat egyszerű, előszőr inicializálni (kezdő beállítás) kell a mikrovezérlőnkben található UART egységet, ami azután hardware-ből megcsinálja nekünk a kommunikációt. Anélkül, hogy fényezni akarnám magamat, szerintem egy egészen áttekinthető beállítási módot sikerült készítenem. A baudrate (átviteli sebesség, bit/sec) beállító macro-t azt ollóztam, de egy kicsit azt is pofozgattam. Érdemes a doksiban megnézegetni, hogy milyen órajel mellett (F_CPU), milyen baudrate értékek, milyen pontosan állíthatók be. 1%-nál pontosabb értékpárok esetén jó eséjünk van, hogy nem fog hibázni az összeköttetés. Alapesetben nagyon könnyű az UART-on egy karaktert elküldeni, meg kell vizsgálni, hogy az UDR regiszter üres-e? Ha az előző karakter már kiment, akkor üres, és betölthető a következő. A main()-ban egyszerűen a c-ben követjük, hogy melyik gomb volt utoljára lenyomva. Ez azért kell, hogy egy gomb nyomásra csak egy üzenetet küldjön a program. Ezután eltároljuk c-be a lenyomott gombot, módosítjuk LED1 állapotát, addig várunk amíg UDR üres nem lesz, majd elküldjük a jelző karaktert. Ez ciklikusan ismétlődik a végtelenséig. Ez egy abszolút favágó módszer, hogy nem csináltam külön egy függvényt a karakter elküldéséhez, hanem mindent kétszer leprogramoztam. Későbbiek során majd visszatérünk erre, megvizsgáljuk, hogy lehet-e olyan eset, amikor ez a megoldás célszerű? Érdekes, hogy a main()-t nem sikerült void main( void);-formában deklarálni, ragaszkodik a fordító a default int main(); -hoz, azért kellet egy return 0;-t írni a végére, hogy ne panaszkodjon.



/*******************************************************************************
*   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                            *
*                                                                              *
*   IT-t nem hasznal.                                                          *
*   LED1 es LED2 labakat kimenetre allitja.                                    *
*   LED1-t kikapcsolja, LED2-t bekapcsolja alaphelyzetben.                     *
*   USART-ot (soros port) 9600 baud 8 bit no parity 1 stop bit-re allitja.     *
*   SW1 lenyomasara LED1-et bekapcsolja, es a soros porton elkuld egy '1'-t.   *
*   SW2 lenyomasara LED1-et kikapcsolja, es a soros porton elkuld egy '2'-t.   *
*                                                                              *
********************************************************************************
*   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" ::)
#define IT_DISABLE           __asm__ __volatile__ ("cli" ::)
#define NOP                  __asm__ __volatile__ ("nop" ::)




// 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




int main( void)
{
   UC c= 0;                                      // pergesmentesites helyett

   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;

   DDRD BS( LED1);                               // szukseges labak kimenetre allitasa
   DDRD BS( LED2);
   LED1_OFF;
   LED2_ON;

   for( ;;)
   {
      if( SW1_ON)
      {
         if( !c)
         {
            c= 1;  
      	    LED1_ON;
            if( UDR_EMPTY) UDR= '1';
         }
      }
      if( SW2_ON)
      {
         if( c)
         {
            c= 0;  
      	    LED1_OFF;
            if( UDR_EMPTY) UDR= '2';
         }
      }
   }
   return 0;
}

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