ATmega8 - Jelzőlámpa - C++ demo

2016-03-20

2016-03-21 - Kiegészítve az inline deklarációval.

 

Mostanában mindig csak kódokat írtam, ez a kép talán egy kicsit feldobja a lapot.

Előző lapokon szó volt a C++ programozásról, meg a "tkiraaly_kpin.c"-ben lévő port/pin kezelő függvényekről. Most szeretném bemutatni, hogy a nagyobb, lassabb kód ellenére mi a módszer előnye, mennyivel egyszerűbb így a programozás. Fenntartva, hogy ez egy lehetőség, lehet C-ben, vagy méginkább Assembly-ben kisebb, gyorsabb programot írni, ahol arra szükség van. Én most úgy látom mindegy, hogy a uC 2 vagy 8% memóriáját foglalja le a program. A pogram a standard piros/sárga/zöld jelzőlámpa működését modellezi. Vegyük észre, hogy csak minimális változó deklarálásra volt szükség, a kiválasztott port lábak könnyen megváltoztathatók. A program elég áttekinthető, csak a működési logikát tartalmazza. Ha csak magamnak írtam volna, azt hiszem nem is tettem volna bele megjegyzéseket.


/*******************************************************************************
*   Author       -  Kiraly Tibor
*                   www.tkiraaly.hu
*   Date         -  2016.03.20.
*   Chip         -  ATmega8
*   Compiler     -  avr-gcc (WinAVR)
*
*   Jelzo lampa - cpp demo
*
*******************************************************************************/
#define F_CPU                4 MHZ


#include "tkiraaly_atmega8.h"
#include "tkiraaly_kbutton.cpp"
#include "tkiraaly_kled.cpp"


int main( void)
{
   U8 phase= 0;                        // jelzolampa fazis
   kled lamp_red( D_PORT_5);           // piros lampa
   kled lamp_yellow( D_PORT_6);        // sarga lampa
   kled lamp_green( D_PORT_7);         // zold lampa
   lamp_red.on();
   kbutton button_step( D_PORT_2);     // lepteto gomb
   for(;;)
   {
      if( button_step.check())
      {
         phase++;
         if( phase > 3) phase= 0; 
         switch( phase)
         {
            case 0:                    // piros
                    lamp_red.on();
                    lamp_yellow.off();
                    break;
            
            case 1:                    // piros + sarga
                    lamp_yellow.on();
                    break;
            case 2:                    // zold
                    lamp_red.off();
                    lamp_yellow.off();
                    lamp_green.on();
                    break;
            case 3:                    // sarga
                    lamp_yellow.on();
                    lamp_green.off();
                    break;
         }
      }
   }
}

A programban látható, hogy a C++-ban lehetőség van az objektum létrehozásakor (valójában a változók létrehozásakor) zárójelek között megadni a kezdő értéke(ke)t, amit a constructor kap meg. Ha a constructor olyan, aminek nem kell kezdő érték, akkor hagyományosan ki kell írni az obektum létrehozásakor a construktor-t. Nézzük például egy led nevű objektum esetén:


led green= led();

A "kbutton" objektummal szeretném demonstrálni a C++-t, meg a "kpin"-t . Úgy tűnik, nem kell külön ".h"-ba tenni a class deklarációt, egy ".cpp"-be bele lehet írni az egészet. Ezen meglátás alapján vontam össze a "tkiraaly_kpin.c"-t és a "tkiraaly_kpin.h"-t is. Láthattuk, hogy a programban az objektum könnyen felhasználható, az objektumok, a ".cpp" file-k megírása igénylik a nagyobb körültekintést. Ezért nem a fő programba, hanem a ".cpp"-be írjuk bele az összes hivatkozást. Lehet több olyan ".cpp" file-unk, amelyikben "#include"-dal hivatkozunk ugyanarra a kódra (pl. "tkiraaly_kpin.c"), és ilyenkor a fordító ellenkezésére számíthatnánk, ha nem használnánk az "#ifndef-#endif" deklarációt.


/*******************************************************************************
*   Author       -  Kiraly Tibor
*                   www.tkiraaly.hu
*   Date         -  2016.03.20.
*   Chip         -  AVR
*
*   kbutton - nyomogomb kezelo objektum 
*
*   Az objektum a nyomogombok kezelesere szolgal.
*   A gombot a fold es a kivalasztott lab koze kell kotni.     
*   A construktor-nak meg kell adni a labat, lasd "tkiraaly_kpin.h".
*   A lab  fel lesz huzva a belso ellenallassal.
*   Az objektum pergesmentesen kezeli a gombot.
*   Az objektum a gomb lenyomaskor csak egyszer ad ki 1-et.
*   
*******************************************************************************/
#ifndef tkiraaly_kbutton
#define tkiraaly_kbutton


#include <util/delay.h>
#include "tkiraaly_kpin.c"


class kbutton
{
   public:
      kbutton( U8);                    // constructor
      U8 check();                      // lekerdezes
   private: 
      U8 _pin;                         // melyik lab
      U8 _state;                       // gomb allapota
};


kbutton::kbutton( U8 pin)              // constructor
{
   _pin= pin;
   kpin_pullup( pin);                  // bemenet/felhuzas
   _state= 1;                          // gomb alapallapota
}


U8 kbutton::check( void)                // lekerdezes
{
   U8 a= 0;
   if ( kpin_rd( _pin) != _state )
   {
      _delay_ms( 30);                  // esetleges perges miatt varakozas
      if ( kpin_rd( _pin) != _state )
      {
         if ( _state)                  // allapot valtas
         {
            _state= 0;
            a= 1;                      // 1-0 valtas eseten
         }
         else _state= 1;
      }
   }
   return a;
}


#endif

Mikor megírtam a "kbutton"-t, és elkezdtem faragni a mintaprogramot, és láttam, hogy az jó, gyorsan összekalapáltam az alábbi "kled"-t is, mert ezzel egyszerűbb, áttekinthetőbb és kényelmesebb lett a kód. Ez a mintapéldája, hogy a fejlődés mozgatórugója a lustaság :). Csak, hogy néhány sorral rövidebb és egyszerűbb legyen a főprogram, képes voltam egy külön objektumot készíteni.


/*******************************************************************************
*   Author       -  Kiraly Tibor
*                   www.tkiraaly.hu
*   Date         -  2016.03.20.
*   Chip         -  AVR
*
*   kled - LED kezelo objektum 
*
*   Az objektum LED-ek kezelesere szolgal.
*   A LED katodjat egy ellenallason keresztüla a labra kell kotni, az anodjat a tapra.     
*   A construktor-nak meg kell adni a labat, lasd "tkiraaly_kpin.h".
*   Alaphelyzetben a LED ki lesz kapcsolva.
*   
*******************************************************************************/


#ifndef tkiraaly_kled
#define tkiraaly_kled


#include "tkiraaly_kpin.c"


class kled
{
   public:
      kled( U8);                       // constructor
      void on();                       // bekapcsolas
      void off();                      // kikapcsolas
   private: 
      U8 _pin;                         // melyik lab
};


kled::kled( U8 pin)                    // constructor
{
   _pin= pin;
   kpin_1( pin);
   kpin_output( pin);
}


void kled::on()                        // bekapcsolas
{
   kpin_0( _pin);
}


void kled::off()                       // kikapcsolas
{
   kpin_1( _pin);
}


#endif

A C++-ban lehet inline függvényeket is használni, vagyis ha jól értem egy függvényen belül is lehet függvényt deklarálni. Ez biztos mindenfélére jó, én csak egy értelmét látom, mint itt, hogy a kevéssé terjedelmes függvényeket közvetlenül bele lehet írni a class-ba. Hivatalosan ez az implicit inline deklaráció, mivel nem kell kiírni az "inline" kulcsszót. Kevesebbet kell írni, talán az összetatozó részek is egymáshoz közel lesznek, de szerintem a kód kevésbé lesz olvasható. Nekem annyira zavarta a szemem, hogy egy-egy üres sorral választottam el a tagfüggvényeket. Mindkét alak egyező méretűre fordul le.


/*******************************************************************************
*   Author       -  Kiraly Tibor
*                   www.tkiraaly.hu
*   Date         -  2016.03.21.
*   Chip         -  AVR
*
*   kled2 - LED kezelo objektum inline fuggvenyekkel
*
*   Az objektum LED-ek kezelesere szolgal.
*   A LED katodjat egy ellenallason keresztüla a labra kell kotni, az anodjat a tapra.     
*   A construktor-nak meg kell adni a labat, lasd "tkiraaly_kpin.h".
*   Alaphelyzetben a LED ki lesz kapcsolva.
*   
*******************************************************************************/


#ifndef tkiraaly_kled
#define tkiraaly_kled


#include "tkiraaly_kpin.c"


class kled
{
   public:

      kled( U8)  { _pin= pin;
                   kpin_1( pin);
                   kpin_output( pin);}

      void on()  { kpin_0( _pin);}     // bekapcsolas

      void off() { kpin_1( _pin);}     // kikapcsolas

   private: 
      U8 _pin;                         // melyik lab
};


#endif

Itt a vége, fuss el véle, legyetek az én vendégeim, innen letölthetitek a programokat, miegymást összecsomagolva.