2016-10-27
Ezt a kapcsolást fogjuk most programozni. Jócskánt átrendeztem a lábakat, mert a PORTD-nek van az összes lába kivezetve.
Emlékeztetőül az ATmega8 bekötése:
Ebben a programban egy LED-et kapcsolunk be. Figyeljük a két kapcsolót, és attól függően, hogy a BAL, vagy a JOBB hombot nyomjuk le, a fény balra, vagy jobbra lép. A már korábban megismert bit léptető operátort használjuk. Az ott leírtak szerint, a byte-ba 0 bitek lépnek be, ezért a belépő bitet felül kell írnunk, hogy az a LED ne világítson. Majd meg kell vizsgáljuk, ha végigléptettük a 0-t, akkor egy 0-t újra be kell tennünk, hogy a folyamat újra kezdődjön. A ciklus végén a várakozásnak az a jelentősége, hogy különben egy hosszab gombnyomásra ki tudja hány léptetést hajtana végre az áramkör? Így 300 miiisecundumonként legfeljebb egyet.
/*******************************************************************************
*
* Author - Kiraly Tibor
* http://www.tkiraaly.hu
* Date - 2016.10.25.
* Chip - ATmega8
* Compiler - avr-gcc
*
* c_suli_8_1.c
* Vilagito pont leptetese gombnyomasra
*
*******************************************************************************/
#define F_CPU 4 MHZ
#include "tkiraaly_atmega8.h"
#include <util/delay.h>
#define BAL_FELHUZAS PB1_PULLUP
#define BAL_GOMB PB1_RD == 0
#define JOBB_FELHUZAS PB2_PULLUP
#define JOBB_GOMB PB2_RD == 0
int main( void)
{
BAL_FELHUZAS;
JOBB_FELHUZAS;
PORTD= 0B11111110; // csak a jobb szelso LED vilagit
DDRD= 0B11111111; // D port osszes laba kimenet
for(;;)
{
if ( BAL_GOMB)
{
PORTD= ( PORTD << 1)+ 0B00000001; // leptetes, legalso bit feluliras
IF ( PORTD == 0B11111111) PORTD= 0B11111110; // ha vegigfutot, kezdes elolrol
}
if ( JOBB_GOMB)
{
PORTD= ( PORTD >> 1)+ 0B10000000; // leptetes, legfelso feluliras
IF ( PORTD == 0B11111111) PORTD= 0B01111111; // ha vegigfutot, kezdes elolrol
}
_delay_ms( 300);
}
}
Ezt most átalakítjuk KITT-nek. Remélem a legtöbb embernek megva a fekete, beszélő Pontiac Firebird, a Knigh Rider-ből, az elején jobbra balra futó piros fénnyel. A programunkban használunk egy irany változót, és ez fogja vezérelni, hogy éppen balra, vagy jobbra kell léptetni a biteket. Ha 0 bit a byte szélére ért, egyszerűen irányt váltunk, és a következő ciklusban már visszafelé léptetünk.
/*******************************************************************************
*
* Author - Kiraly Tibor
* http://www.tkiraaly.hu
* Date - 2016.10.25.
* Chip - ATmega8
* Compiler - avr-gcc
*
* c_suli_8_2.c
* KITT futofeny
*
*******************************************************************************/
#define F_CPU 4 MHZ
#include "tkiraaly_atmega8.h"
#include <util/delay.h>
#define BAL 0
#define JOBB 1
int main( void)
{
PORTD= 0B11111110; // csak a jobb szelso LED vilagit
DDRD= 0B11111111; // D port osszes laba kimenet
unsigned char irany= BAL;
for(;;)
{
if ( irany == BAL)
{
PORTD= ( PORTD << 1)+ 0B00000001; // leptetes, legalso bit feluliras
IF ( PORTD == 0B01111111) irany= JOBB; // ha vegigfutot, iranyvaltas
}
else
{
PORTD= ( PORTD >> 1)+ 0B10000000; // leptetes, legfelso feluliras
IF ( PORTD == 0B11111110) irany= BAL; // ha vegigfutot, iranyvaltas
}
_delay_ms( 300);
}
}
Számos fény mintát ki tudunk gondolni, olyanokat is, amelyeket elég nehéz fügvénnyel, vagy programmal megvalósítani. Egyszerű megoldhatjuk a problémát, ha a mintákat letároljuk, és a tárból lépésenként vesszük elő a következőt. A tárolást egy egydimenziós adattömbben, másképpen füzérben (idegen szóval string-ben, vagy vektorban) tudjuk megvalósítani. Így néz ki egy 5 elemű tömb (0..4) létrehozása.
unsigned int t[ 5];
Ez követően így tárolhatunk el a tömmben adatokat:.
t[ 1]= 123;
t[ 3]= 0x12;
t[ 0]= 0;
Egyszerübb helyzetben vagyunk, ha már kezdetben tudjuk milyen adatokkal akarjuk a tömböt feltölteni. Ekkor így adhatjuk meg a tömböt, a C fordító ki fogja számolni, hány elemű tömb kell hozzá.
unsigned int t[]= { 123, 48, 21, 98, 120};
Tehát kombinációinkat a minta nevű tömbbe tároljuk el. Az i fogja mutatni, hogy melyik elem következik. Háromtized másodpercenként kiírunk egy mintát PORTD-re, majd a mutatót megnöveljük. Fontos, hogy i ne mutasson a tömbön túlra, mert nem fogunk hibaüzenetet kapni, a C kiszámolja a memóriában hova esne az az elem, és visszadja annak a memória cellának az értékét, ha a tömb egy eleme van benne, ha nem.
/*******************************************************************************
*
* Author - Kiraly Tibor
* http://www.tkiraaly.hu
* Date - 2016.10.25.
* Chip - ATmega8
* Compiler - avr-gcc
*
* c_suli_8_3.c
* Feny minta, tomb kezeles
*
*******************************************************************************/
#define F_CPU 4 MHZ
#include "tkiraaly_atmega8.h"
#include <util/delay.h>
int main( void)
{
unsigned int i= 0; // mutato
unsigned int minta[]=
{
0B10111111,
0B11011111,
0B11101111,
0B11110111,
0B11111011,
0B11111101,
0B10111101,
0B11011101,
0B11101101,
0B11110101,
0B11111001,
0B10111001,
0B11011001,
0B11101001,
0B11110001,
0B10110001,
0B11010001,
0B11100001,
0B10100001,
0B11000001,
0B10000001
};
DDRD= 0B11111111; // D port osszes laba kimenet
for(;;)
{
if ( i > 20) i= 0;
PORTD= minta[ i];
i++;
_delay_ms( 300);
}
}
Fontos megemlíteni, hogy a C-ben nemcsak egy dimenziós, hanem 2, 3... sőt több dimenziós tömbök is kezelhetők. uC környezetben ezek nem jellemzők, mert az ilyen nagy tömbök tárolásához azért jelentős memóriai is kell. A példában szereplő k tömbhöz 2kB memória szükséges. És lehet ezt fokozni, ha nagyobb számú, vagy nagyobb méretű adat elemeket kell eltárolnunk...
unsigned char c[ 3, 10];
int k[ 10, 10, 10, 10],
Szintén fontos megemlíteni, hogy a C-ben nemcsak indexxel tudunk egy tömbre hivatkozni, hanem úgyneveztt mutatóval is. Most csak elvi szinten beszélek a mutatókról, majd megpróbálok valami jó, ideillő példát kitalálni. Mutatókat nagyon gyakran használunk C-ben. Sokan utálják a mutatókat. Egy mutató mutathat a tömb egy elemére, valamilyen adatra, de akár egy függvényre is, értékét eltárolhatjuk, vagy műveleltet végezhetünk vele. Előnye, hogy mutatóval a C gyorsabban tudja kezelni az adatokat, mint index segítségével. Például az objektum orientált programozásnál (C++) fontos szerepe van függvényre mutató mutatónak, mert így az adatokhoz tudjuk kapcsolni az azt kezelő függvényt.