This is an old revision of the document!
As a principle, program written in C-language can be in any form, even in one line, because the compiler assumes only the following of syntax rules. However, it is advisable to take care of program coding style for clearness and simplicity. Typical structure of a C-language program:
/* Include header files */ #include <avr/io.h> #include <stdio.h> /* Makro declarations */ #define PI 3.141 /* Data type definitions */ typedef struct { int a, b; } element; /* Global variables */ element e; /* Functions */ int main(void) { // Local variables int x; // Program code printf("Tere maailm!\n"); }
Programmer can write random text into program code for notes and explanations that is no compiled. Comments can also be used for temporally excluding some parts of code from compiling. Examples of two commenting methods:
// Üherealine kommentaar. // Kommentaariks loetakse kahe kaldkriipsu järel olevat teksti /* Mitmerealine kommentaar Kommentaari algus ja lõpp määratakse kaldkriipsude ja tärnidega */
C-keele baasandmetüübid:
Tüüp | Miinimum | Maksimum | Bitte | Baite |
---|---|---|---|---|
(signed) char | -128 | 127 | 8 | 1 |
unsigned char | 0 | 255 | 8 | 1 |
(signed) short | -32768 | 32767 | 16 | 2 |
unsigned short | 0 | 65535 | 16 | 2 |
(signed) long | -2147483648 | 2147483647 | 32 | 4 |
unsigned long | 0 | 4294967295 | 32 | 4 |
float | -3.438 | 3.438 | 32 | 4 |
double | -1.7308 | 1.7308 | 64 | 8 |
Sulgudes olevat sõna “signed” ei pea kasutama, kuna vaikimisi ongi andmetüübid bipolaarsed.
AVR mikrokontrolleril int = short
PC arvutil int = long
C-keeles puudub spetsiaalne teksti-andmetüüp. Selle asemel kasutatakse char tüüpi massiive (nendest edaspidi) ja ASCII “tähestikku”, kus igal tähel ja märgil on oma järjekorranumber.
Programmis saab kasutada kindlat andmetüüpi mälupesasid - muutujaid. Muutujate nimed võivad sisaldada ladina tähestiku tähti, numbreid ja alakriipsu. Nimi ei tohi alata numbriga. Muutuja deklareerimisel kirjutatakse selle ette andmetüüp. Väärtuse omistamiseks muutujale kasutatakse võrdusmärki (. Näide muutujate kasutamisest:
// char tüüpi muutuja c deklareerimine char c; // Muutujale c väärtuse omistamine. c = 65; c = 'A'; // A on ASCII märgisüsteemis samuti väärtusega 65 // int tüüpi muutuja i20 deklareerimine ja algväärtustamine int i20 = 55; // Mitme unsigned short tüüpi muutuja deklareerimine unsigned short x, y, test_variable;
Konstante deklareeritakse samamoodi nagu muutujaid, kuid ette lisatakse const võtmesõna. Konstantide väärtust ei saa programmi käigus muuta. Näide kasutamisest:
// int tüüpi konstandi määramine const int x_factor = 100;
Baasandmetüüpidest saab struct võtmesõnaga struktuure koostada. Struktuur on justkui kombineeritud andmetüüp. Tüüpi deklareeritakse typedef võtmesõnaga. Näide struktuurist andmetüübi loomise ja kasutamise kohta:
// Uue punkti andmetüübi deklareerimine typedef struct { // x ja y koordinaat ning värvikood int x, y; char color; } point; // Punkti muutuja deklareerimine point p; // Punkti koordinaatide määramine p.x = 3; p.y = 14;
Andmetüüpidest võib koostada massiive (jadasid). Massiiv võib olla ka mitmemõõtmeline (tabel, kuup, jne). Näide ühe- ja kahemõõtmelise massiivi kasutamisest:
// Ühe- ja kahemõõtmelise massiivi deklareerimine char text[3]; int table[10][10]; // Teksti moodustamine tähemassiivist text[0] = 'H'; // Täht text[1] = 'i'; // Täht text[2] = 0; // Teksti lõpetamise tunnus (null-bait) // Tabeli ühe elemendi muutmine table[4][3] = 1;
Muutujate, konstantide ja väärtust tagastavate funktsioonidega saab koostada avaldisi (tehteid). Avaldise väärtusi saab omistada muutujatele, neid saab kasutada funktsiooni parameetritena ja erinevates tingimuslausetes.
C-keeles toetatud aritmeetilised tehted on liitmine (+), lahutamine (-), korrutamine (*), jagamine (/) ja mooduli võtmine (%). Näited aritmeetiliste tehete kasutamisest:
int x, y; // Mooduli võtmine, korrutamine ja väärtuse omistamine // x saab väärtuse 9 x = (13 % 5) * 3; // Liitev-omistav operaator // x väärtuseks saab 14 x += 5; // Ühe lahutamise kiirmeetod // x väärtuseks saab 13 x--;
Loogilised tehted on eitus (!), loogiline korrutamine (&&) ja loogiline liitmine (||). Näide tehete kasutamisest:
bool a, b, c; // Algväärtustamine a = true; b = false; // Eitus // c väärtus tuleb väär sest tõest eitati c = !a; // Loogiline korrutamine // c väärtuseks tuleb väär, sest üks operandidest on väär c = a && b; // Loogiline liitmine // c väärtus tuleb tõene, sest üks operandidest on tõene c = a || b;
NB! bool andmetüüp C-keeles tegelikult puudub, selle asemel on kasutusel täisarvud, kus 0 tähistab väära ja iga muu arv tõest väärtust. Näiteks Kodulabori teegis on defineeritud bool kui unsigned char. Konstant true tähistab seal väärtust 1 ja false väärtust 0.
Arvude väärtuste võrdlemisel saadakse loogilised väärtused. Võrdlustehted on samaväärsus (=, erinevus (!
, suurem (>), suurem-võrdne (>
, väiksem (<) ja väiksem-võrdne (⇐). Näide kasutamisest:
int x = 10, y = 1; // Suurem-kui võrdlustehe, mis on tõene // Tehte ümber on sulud vaid selguse pärast bool b = (5 > 4); // Erinevuse tehe // Tehte tulemus on väär b = (4 != 4); // Aritmeetiline, võrdlus ja loogiline tehe üheskoos // b tuleb väär, sest esimene loogilise korrutise operand on väär b = (x + 4 > 15) && (y < 4);
Bititehted on andmetega binaarses arvusüsteemis tegelemiseks. Neid saab rakendada kõigi täisarv-tüüpi andmetega. Bititehted sarnanevad loogiliste tehetega, kuid erinevad selle poolest, et tehe teostatakse iga bitiga eraldi, mitte kogu arvuga. C keeles on bititeheteks inversioon (~), konjunktsioon (&), disjunktsioon (|), antivalentsus (^), nihe vasakule («) ja nihe paremale (»).
// Märgita 8-bitise char-tüüpi muutuja deklareerimine // Muutuja väärtus on kümnendsüsteemis 5, kahendsüsteemis 101 unsigned char c = 5; // Muutuja c disjunktsioon arvuga 2 (kahendsüsteemis 010) // c väätuseks saab 7 (kahendsüsteemis 111) c = c | 2; // Bitinihe vasakule 2 võrra // c väärtuseks saab 28 (kahendsüsteemis 11100) c = c << 2;
Bititehted on hädavajalikud mikrokontrollerite registrite kasutamisel. Täpsemalt tutvustab neid AVR registrite peatükk.
Funktsioon on programmilõik, mida saab selle nime järgi täitmiseks välja kutsuda. Funktsioonil võivad olla parameetrid ja funktsioon võib tagastada ühe väärtuse. Kui funktsioon ei tagasta väärtust, on selle tüüp void. Kui funktsioonil pole parameetreid, tuleb vanemat C-keele kompilaatorit kasutades void kirjutada ka parameetrite deklaratsiooni asemele. Näide liitmisfunktsioonist ja tagastamisväärtuseta funktsioonist:
// Kahe int tüüpi parameetriga funktsiooni deklareerimine // Funktsioon tagastab int-tüüpi väärtuse int sum(int a, int b) { // Kahe arvu liitmine ja summa tagastamine return a + b; } // Ilma parameetrite ja tagastatava väärtuseta funktsioon void power_off(void) { }
Funktsiooni kasutamiseks tuleb see välja kutsuda. Funktsioon peab programmikoodis olema deklareeritud enne välja kutsumise kohta. Näide liitmisfunktsiooni väljakutsumisest.
int x; int y = 3; // Liitmisfunktsiooni väljakutsumine // Parameetriteks on muutuja ja konstandi väärtus x = sum(y, 5); // Väljalülitamise funktsiooni väljakutsumine // Parameetrid puuduvad power_off();
C-keele programmi täitmist alustatakse main nimelisest funktsioonist, mis teeb selle kohustuslikuks funktsiooniks.
Tingimuslause võimaldab vastavalt sulgudes oleva avaldise tõesusele täita või mitte täita tingimusele järgnevat lauset või programmilõiku. Tingimuslause võtmesõna on if. Näide kasutamisest:
// Avaldis on tõene ja lause x = 5 täidetakse, // sest 2 + 1 on suurem kui 2 if ((2 + 1) > 2) x = 5; // Kui x on 5 ja y on 3, siis täidetakse järgnev programmilõik if ((x == 5) && (y == 3)) { // Suvaline tegevus y = 4; my_function(); }
Tingimuslause võib olla pikem ja sisaldada ka lauset või programmilõiku, mis täidetakse avaldise mittetõesuse korral. Selleks tuleb if tingimuslause järel kasutada else võtmesõna.
// Kas x on 5 ? if (x == 5) { // Suvaline tegevus z = 3; } // Kui x ei olnud 5, kas siis x on 6 ? else if (x == 6) { // Suvaline tegevus q = 3; } // Kui x ei olnud 5 ega 6... else { // Suvaline tegevus y = 0; }
Kui on vaja võrrelda avaldist mitme erineva väärtusega, on mõistlik kasutada valikulauset switch võtmesõnaga. Näide kasutamisest:
int y; // Tingimuslause y võrdlemiseks switch (y) { // y on 1 ? case 1: // Suvaline tegevus function1(); break; // y on 2 ? case 2: // Suvaline tegevus function2(); break; // Kõik muud juhtumid default: // Suvaline tegevus functionX(); // break lauset pole vaja, // kuna võrdlemine lõppeb nagunii }
Tsüklitega saab programmilõiku täita mitmeid kordi.
while võtmesõnaga tähistatud programmilõiku täidetakse seni, kuni sulgudes olev avaldis on tõene.
int x = 0; // Tsükkel kestab seni, kuni x on väiksem kui 5 while (x < 5) { // x suurendamine ühe võrra x++; }
for võtmesõnaga tsükkel sarnaneb while tsüklile, kuid lisaks on sulgudes ära määratud enne tsüklit täidetav lause ja iga tsükli ajal täidetav lause.
Näide:
int i, x = 0; // Algul määratakse i nulliks. Tsüklit täidetaks seni, kuni // i on vähem kui 5. Iga tsükli lõpus suurendatakse i ühe võrra for (i = 0; i < 5; i++) { // x suurendamine 2 võrra x += 2; } // Siinkohal tuleb x väärtuseks 10
while ja for tsüklitest saab erandkorras väljuda break võtmesõnaga. continue võtmesõnaga saab alustada järgmist tsüklit ilma järgnevat koodi täitmata.
int x = 0, y = 0; // Lõputu tsükkel, kuna 1 on loogiline tõesus while (1) { // Tsüklist väljutakse, kui x on saavutanud väärtuse 100 if (x >= 100) break; // x suurendamine, et tsükkel kunagi lõppeks ka x++; // Kui x on 10 või vähem, siis alustatakse järgmist tsüklit if (x <= 10) continue; // y suurendamine y++; } // Siinkohal on y väärtus 90
Tekstitöötlusfunktsioone on mikrokontrolleri puhul vaja eelkõige teksti kuvamiseks LCD ekraanile.
sprintf funktsioon toimib sarnaselt C-keeles üldlevinud printf funktsiooniga. Erinevuseks on funktsiooni tulemuse väljastamine puhvrisse (muutujasse), mitte standard väljundisse.
tagastus = sprintf(muutuja, parameetritega_tekst, parameetrid);
Näide:
int r = sprintf(buffer, "%d pluss %d on %d", a, b, a+b);
Väärtustab muutuja vormindatud tekstiga, mis on antud funktsiooni teisest kuni n parameetrini. Sprintf funktsioon lihtsustab keerulisemate fraaside või lausete koostamist. Mugavam on kasutada tekstis muutujaid, mis asendatakse väärtustega. Funktsioon tagastab muutujasse salvestatud teksti pikkuse. Vea korral tagastatakse negatiivne arv.
Näide:
sprintf(x, "%d. on esimene", 1); // sama tulemuse saaksime ka nii: x = "1. on esimene"; sprintf(x, "%s on %d aastat vana", "Juku", 10); // sama tulemuse saaksime ka nii: x = "Juku on 10 aastat vana";
%s ja %d on antud juhul parameetrid, mis asendatakse vastavalt muutjate väärtustega, mis on funktsiooni viimasteks parameetriteks. Niipalju, kui on parameetreid, peab olema ka muutujaid. Esimese näite puhul oli meil parameetriks %d, mis asendati muutuja väärtusega 1. Teise näite puhul olid parameetriteks %s ja %d, mis asendati vastavalt muutuja väärtustega “Juku” ja 10. Just nimelt sellises järjekorras, sest %s ootab väärtust teksti kujul ja %d numbrilist väärtust. Erinevate andmetüüpide jaoks on olemas vastavad muutujate kirjeldused:
Parameeter | Kirjeldus | Näide |
---|---|---|
%c | Tähemärk | a |
%i või %d | Täisarv | 123 |
%f | Murdarv | 3,14 |
%s | Tekst | näide |
%X | Heksadetsimaalarv | 3F |
#include <stdio.h> int main () { char buffer [50]; int n, a=5, b=3; n=sprintf (buffer, "%d pluss %d on %d", a, b, a+b); printf ("\"%s\" on %d markki pikk\n",buffer,n); return 0; }
Teegi standard library (stdlib.h) funktsioonide erinevate operatsioonide ja konverteerimiste lihtsustamiseks
Juhuarvude genereerimine ei olegi AVR kontrolleril väga lihtne.
Esmalt tuleb juhunumbrigeneraator seemendada arvuga, mille järgi genereeritakse suvaliste numbrite jada. Sama numbri järgi genereeritakse alati sama jada. Suvalisema tulemuse saamiseks võib seemendamiseks kasutada näiteks tühjast ADC-st loetud ujuvaid väärtusi.
Näide:
srand(100); rand();
Näide, juhuarvu genereerimiseks vahemikus 16
#include <stdlib.h> int x; x=rand() % 16;
Põhjalikuma inglisekeelse kirjelduse C keele funktsioonide kohta leiad aadressilt:
http://www.cplusplus.com/reference/clibrary/
~~DISCUSSION~~