2016-10-27
Készítsünk egy egyszerű kapcsolást és programot, ami végtelen ciklusban fél másodpercre bekapcsol egy LED-et, majd fél másodpercre kikapcsolja. Minnél egyszerűbb valami, annál kevesebb hibát tudunk beleépíteni. Egyszerűsége ellenére kiinduló pontja lehet a legtöbb munkánknak, mert lehetővé teszi, hogy szemrevételezéssel meggyőződjünk az áramkörünk működőképességéről. Megszámolhatjuk, hogy a LED hányat villan egy perc alatt, így ellenőrizhetjük, hogy helyesen állítottuk-e be a sebességet? Íme az áramkör:
A bal oldalon vannak azok a lábak, amelyeket a programozó fejhez kell csatlakoztatni. Alul és felül vannak a táp lábak. Jobbra látható a LED, amit majd be/ki fogunk kapcsolgatni. A LED akkor fog világítani, ha a PB0 lábon 0 lesz.
Emlékeztetőül az ATmega8 bekötése:
Ez pedig a programunk:
/*
c_suli_3_1.c
C suli - Elso program - LED villogtatasa 1Hz-cel
*/
#define F_CPU 4 MHZ
#include "tkiraaly_atmega8.h"
#include <util/delay.h>
int main( void)
{
PB0_OUTPUT; // LED lab legyen kimenet
for(;;) // vegtelen ciklus
{
PB0_0; // LED lab legyen 0, vilagit
_delay_ms( 500); // fel masodperc varakozas
PB0_1; // LED lab legyen 1, nem vilagit
_delay_ms( 500);
}
}
Azt látjuk, hogy az C suli 1-ből megszerzett tudásunkkal ezt a programot nemigen értjük. Ne vessétek a szememre, hogy azt írtam, a C nyelvet 10-20 kulcsszóval le lehet fedni, mert azt is írtam, hogy a C nagyon rugalmasan bővíthető. Szép sorban nézzük meg, minek mi az értelme?
A programba írhatunk magyarázatokat, hogy mások is megértsék mit csináltunk,
de néhány hónap múlva már saját magunknak is jól jön. Egyik lehetőség,
a "/*
Magyarázat */", így több soros szöveget is beírhatunk. A másik lehetőség "//
Magyarázat", amit a sor végére biggyeszthetünk.
#define F_CPU 4 MHZ
Ez arról szól, hogy megadjuk a uC órajelének a frekvenciáját, ezt az értéket sok előre elkészített progam modul használja.
#include "tkiraaly_atmega8.h"
Ez egy általam előre megírt modul, ami megkönnyíti a munkát, majd később érdemes lesz belenézni. Egész pontosan azt mondja, hogy ide be kell szúrni a "tkiraaly_atmega8.h" file szövegét.
#include <util/delay.h>
Ez megint egy előre megírt modul beszúrása, de látjuk, hogy különbözik az előző utasítástól. Ez azért van, mert az előző file-t a programunk mappájában kell keresni, ez a modul meg a C fordító programunk tartozéka és az ott rendszeresített helyen lehet megtalálni.
int main( void) {}
C-ben a programunkat kisebb önállóan is működöképes mini programokra bontjuk, úgynevezett függvényekre. Egy C függvény hasonlít a matematikai függvényekre, átadhatunk neki változó(ka)t, majd a függvény az által kiszámolt értéket adja vissza. Magát a programunkat a kötelezően "main()" nevü függvény valósítja meg ( magyarul fő). A main() kötelezően "int" típusú, ami azt jelenti, hogy a függvény egy int (16 bites) számot ad vissza. A "( void)" (magyarul üres) részből látszik, hogy a main()-nek nem adunk át paramétert. Később lesz olyan függvényünk is, aminek átadunk paramétert. A "{ }" kapcsos zárójelek között soroljuk fel azokat az utasításokat, amikből a main() áll.
PB0_OUTPUT;
Ez egy általam előre megírt program részlet, ami PB0 lábat kimenetre állítja. Később még részletesen meg fogjuk ezt nézni.
for(;;) { }
Végre valami ismerős! Ezt láttuk a C suli 1-ben. Ez egy olyan ciklus, aminek a törzsét, vagyis a "{ }" közé zárt utasításokat a vég nélkül fogja a uC ismételgetni.
PB0_0;
Ez megint én követtem el, ez a program részlet a PB0 lábat 0-ba állítja. Ilyenkor a LED világítani fog.
_delay_ms( 500);
Ez a "delay.h"-ban van leprogramozva. Ez egy 500 milisecundum, azaz fél másodpercig tartó mini program. Az utasításaink feldolgozása a mini program lefutását követően folytatódnak. Fontos, hogy a uC orajele helyesen legyen megadva, mert ez a modul az F_CPU figyelembe vételével fut.
PB0_1;
Mint fent, csak értelemszerűen a PB0 lábat 1-ba állítja. Ilyenkor a LED nem fog világítani
A programozási nyelvek két csoportba sorolhatók, az interpreterekre, és a compilerekre. Az interpreter értelmezőt jelent, úgy működik, hogy a program sorainkat egyenként értelmezi és végrehajta. Tehát futtatás közben az interpreter programnak, és a forrásprogramnak is bent kell lennie a gépben. A compiler az egész programunkat egyszerre lefordítja, és csak a lefordított gépi kódú programot töltjük be a gépbe. A C compiler. A valóságban a C programunk több lépésben kerül lefordításra, ami nagyfokú rugalmasságot és modularitást biztosít. Ezt talán majd akkor lehet megismerni/belátni, amikor az ember már nem ilyen egyszerű kis példaprogramokat ír, hanem talán egy csoport feladatának egy modulját dolgozza ki. Nekünk most fontos, hogy első lépésben a preprocesszor (előfeldolgozó) próbálja megemészteni a kódunkat. A "#" - heshmark-kal kezdődő sorok szólnak a preprocesszornak, itt csak kétféle található. A "#define" utasítással egy kifejezés párt adunk meg a preprocesszornak, úgy működik, mint egy keress/cserél utasítás a szövegszerkesztőben. A "#include" azt jelenti, hogy a programunk szövegébe szúrja be a megadott file-t. A preprocesszor által előkészített kód több lépésben kerül fordításra, ez látszik a munka közben generált file-okból is. Nekünk a végeredmény a fontos, aminek .hex lesz a neve (Intel HEX formátumú állomány), ezt az égető programmal tudjuk a uC-be betölteni. Most, amikor mindenkinek elment a kedve az egésztől, elmondom, hogy a C programunkat kvázi egy utasítással fogjuk lefordítani, a "fordit.bat"-tal (batch - parancs köteg). Itt látható a tartalma:
avr-gcc -g -Wall -O2 -mmcu=atmega8 -c -o prg.o prg.c
avr-gcc -g -O2 -mmcu=atmega8 -Wl,-Map,prg.map -o prg.elf prg.o
avr-objdump -h -S prg.elf > prg.lst
avr-objcopy -j .text -j .data -O ihex prg.elf prg.hex
avr-size --format=avr --mcu=atmega8 prg.elf
A a GNU C fordító AVR-re (Atmel uC-k) adaptált változatát használjuk. Azért választottam ezt, mert ingyenes, korlátozások nélkül használható. Inkább ne kérdezzétek ez a sok parancssori kapcsoló, kutyafüle mit jelent. Egyszer beleástam magam, de azóta sokat felejtettem. Akit érdekel, vagy szüksége van rá, a doksik a neten elérhetők. A lefordítani kívánt programot át szoktam nevezni "prg.c"-re, így nem kell a batch file-t piszkálnom.