Nigel pocinje svoju seriju tutorijala sa tipicnim “hello world” programom za mikrokontrolere – tj “blinkanjem ledara”.

Za prvi deo ovog tutorijala bice nam potrebna GLAVNA1 plocica sa ledarom. sa J1 postavljenim, ili mozemo koristiti LED plocicu na portu B.

Primer 1.1

Jednostavan program koji sve io portove setuje na na 1 a onda na 0 (pisan u MikroC-u):

void main(){
   CMCON = 0x07;    // TURN COMPARATORS OFF (make it like a 16F84)
   TRISA = 0;       // Set port A all output
   TRISB = 0;       // Set port B all output
   
Loop:
     PORTA = 0xFF;  // Set all port A bits high
     PORTB = 0xFF;  // Set all port B bits high
     asm nop        // The nop's make up the time taken by the goto
     asm nop        // giving square wave output
     PORTA = 0;     // Set all port A bits low
     PORTB = 0;     // Set all port B bits low
     goto Loop;     // go back and do it again
}

Prva linija definise pocetak “glavne” funkcije, druga iskljucuje komparatore, naredne dve setuju “pravac” portova A i B. Na PIC mikrokontrolerima, digitalni IO port moze biti “ulaz” ili “izlaz”, da li je port ulazni ili izlazni podesava se registrom TRISx gde za je svaki bit tog registra vezan za bit porta i 0 predstavlja “output” a 1 “input”.

U petlji dizemo sve bitove oba porta na 1, pravimo pauzu od 2 takta (sa nop sto znaci no operation) spustamo vrednost na 0 i skacemo na pocetak petlje (ovaj skok takodje traje 2 takta tako da nam je izlaz simetrican).

Primer 1.2
Ako ste probali primer 1.1 primetili ste da ne primecujete kako LED trepce. Ne mozete primetiti treptanje posto ledare trepcu velikom brzinom (upaljene su 2-3 mikro sekunde i onda su ugasene 2-3 mikro sekunde ako uzmemo u obzir da mikrokontroler radi na 4MHz) sto je prebrzo da bi bilo detektovane golim okom. Kako bi mogli da “vidimo” promene, ubacicemo pauzu izmedju paljenja i gasenje le dioda.

void main(){
   CMCON = 0x07;    // TURN COMPARATORS OFF (make it like a 16F84)
   TRISA = 0;       // Set port A all output
   TRISB = 0;       // Set port B all output
   
Loop:
     PORTA = 0xFF;  // Set all port A bits high
     PORTB = 0xFF;  // Set all port B bits high
     asm nop        // The nop's make up the time taken by the goto
     asm nop        // giving square wave output
     Delay_ms(500); // Half a second pause
     PORTA = 0;     // Set all port A bits low
     PORTB = 0;     // Set all port B bits low
     Delay_ms(500); // Half a second pause
     goto Loop;     // go back and do it again
}

MikroC compiler koristen u ovom primeru koristi funkciju Delay_ms(x) koja sluzi da pauzira program na X milisekundi. Mi smo dodali Delay_ms(500) sto pravi pauzu od 500ms iliti pola sekunde. MikroC takodje ima funkcije Delay_us() (pauza u mikro sekundama), VDelay_ms() (pauza u mili sekundama koja nije “apsolutno tacna” ali zauzima manje prostora od Delay_us()) kao i Delay_Cyc(x) funkciju koja pravi pauzu u “taktovima”. 1 takt na PIC mikro kontroleru je na svake 4 oscilacije glavnog instrukcijskog oscilatora tako da ako nam je oscilator na 4MHz 1 takt je na svake 4 oscilacije, dakle na 1 mikro sekundu. Neki C kompajleri nude delay funkciju samo na nivou “taktova” tako da sami morate u odnosu na to kolika je brzina procesora da racunate koliko taktova vam je potrebno za vremesku pauzu od X milisekundi.

Primer 1.3
Prethodni primeri menjaju vrednost “svih” pinova jednog porta. Cesto zelimo da menjamo vrednost samo jednog pina. Razliciti C kompajleri nam dozvoljavaju da pristupimo pinovima porta na razlicite nacine. MikroC sintaksa ja PORTx.Fn gde je x – ime porta a n bit dakle, PORTA.F0 je najnizi bit porta A, PORTC.F7 je najvisi bit porta C; neke ceste sintakse su: PORTAbits.RA0, PORTA.A0, PORTA.0 i slicno. Neki kompajleri van daju mogucnost da sami kreirate strukturu i imenujete svaki pin, neki daju mogucnost da setujete pojedinacne pinove kroz funkciju (na primer – output_high(porta, 0); ) i slicno.

Ovaj primer pali i gasi RB7 (PORTB MSB – tj. najvisi bit porta B):

void main(){
   CMCON = 0x07;    // TURN COMPARATORS OFF (make it like a 16F84)
   TRISA = 0;       // Set port A all output
   TRISB = 0;       // Set port B all output
   PORTA = 0;       // Set port A all bits low
   PORTB = 0;       // Set port B all bits low

   
Loop:
     PORTB.F7 = 1;  // Set RB7 high
     asm nop        // The nop's make up the time taken by the goto
     asm nop        // giving square wave output
     Delay_ms(500); // Half a second pause
     PORTB.F7 = 0;  // Set RB7 low
     Delay_ms(500); // Half a second pause
     goto Loop;     // go back and do it again
}

Primer 1.4
Ako zelimo da umesto RB7 iz prethodnog posta palimo i gasimo LED na RB4 moramo da nadjemo svuda gde se spominje PORTB.F7 i promenimo u PORTB.F4 .. C jezik nam daje mogucnost definisanja makro-a tako da na pocetku programa mozemo da definisemo makro LED koji ce kompajler sam zameniti sa PORTB.F7 a mi ako zelimo da promenimo port/pin to cinimo samo na jednom mestu te nam je kasnije mnogo lakse da razumemo i administriramo program:

#define LED PORTB.F7
void main(){
   CMCON = 0x07;    // TURN COMPARATORS OFF (make it like a 16F84)
   TRISA = 0;       // Set port A all output
   TRISB = 0;       // Set port B all output
   PORTA = 0;       // Set port A all bits low
   PORTB = 0;       // Set port B all bits low

   
Loop:
     LED      = 1;  // Set RB7 high
     asm nop        // The nop's make up the time taken by the goto
     asm nop        // giving square wave output
     Delay_ms(500); // Half a second pause
     LED      = 0;  // Set RB7 low
     Delay_ms(500); // Half a second pause
     goto Loop;     // go back and do it again
}

Dakle ako sada u prvoj liniji umesto #define LED PORTB.F7 stavimo #define LED PORTB.F4 LED na RB4 ce se paliti i gasiti.

Primer 1.5
Sada cemo “prosetati” svetlo po redu od 8 ledara na portu B

#define LEDPORT PORTB
#define LEDTRIS TRISB

void main(){
   CMCON = 0x07;    // TURN COMPARATORS OFF (make it like a 16F84)
   LEDTRIS = 0;     // Macro points to right TRIS register, set them to output
   LEDPORT = 0;     // Macro points to right PORT, set it all low
Loop:
     LEDPORT = 0x80;// 10000000
     Delay_ms(500); // Half a second pause
     LEDPORT = 0x40;// 01000000
     Delay_ms(500); // Half a second pause
     LEDPORT = 0x20;// 00100000
     Delay_ms(500); // Half a second pause
     LEDPORT = 0x10;// 00010000
     Delay_ms(500); // Half a second pause
     LEDPORT = 0x08;// 00001000
     Delay_ms(500); // Half a second pause
     LEDPORT = 0x04;// 00000100
     Delay_ms(500); // Half a second pause
     LEDPORT = 0x02;// 00000010
     Delay_ms(500); // Half a second pause
     LEDPORT = 0x01;// 00000001
     Delay_ms(500); // Half a second pause
     goto Loop;     // go back and do it again
}

Primer 1.6
Vrlo lako mozemo da napravimo da se svetlo “odbija” od krajeve:

#define LEDPORT PORTB
#define LEDTRIS TRISB

void main(){
   CMCON = 0x07;    // TURN COMPARATORS OFF (make it like a 16F84)
   LEDTRIS = 0;     // Macro points to right TRIS register, set them to output
   LEDPORT = 0;     // Macro points to right PORT, set it all low
Loop:
     LEDPORT = 0x80;// 10000000
     Delay_ms(500); // Half a second pause
     LEDPORT = 0x40;// 01000000
     Delay_ms(500); // Half a second pause
     LEDPORT = 0x20;// 00100000
     Delay_ms(500); // Half a second pause
     LEDPORT = 0x10;// 00010000
     Delay_ms(500); // Half a second pause
     LEDPORT = 0x08;// 00001000
     Delay_ms(500); // Half a second pause
     LEDPORT = 0x04;// 00000100
     Delay_ms(500); // Half a second pause
     LEDPORT = 0x02;// 00000010
     Delay_ms(500); // Half a second pause
     LEDPORT = 0x01;// 00000001
     Delay_ms(500); // Half a second pause


     LEDPORT = 0x02;// 00000010
     Delay_ms(500); // Half a second pause
     LEDPORT = 0x04;// 00000100
     Delay_ms(500); // Half a second pause
     LEDPORT = 0x08;// 00001000
     Delay_ms(500); // Half a second pause
     LEDPORT = 0x10;// 00010000
     Delay_ms(500); // Half a second pause
     LEDPORT = 0x20;// 00100000
     Delay_ms(500); // Half a second pause
     LEDPORT = 0x40;// 01000000
     Delay_ms(500); // Half a second pause

     goto Loop;     // go back and do it again
}