marți, 14 februarie 2012

Microntrollere PIC Microchip pentru incepatori - scrierea codului

In episodul precedent (vezi aici) am explicat cate ceva despre microcontrolere. Asadar suntem in punctul in care avem un PC cu Windows, cu port USB, am instalat mikroC (de la Mikroelektronika) si Microchip MPLAB IDE (de la Microhip), avem un programator pe USB si o placa de dezvoltare. Ne mai lipseste prima aplicatie - sa scriem primul program, sa scriem cod pentru microcontroler.

In cele ce urmeaza nu vei gasi un ghid detaliat care sa te invete sa faci aplicatii sau care sa iti bage in cap tot ceea ce nu sti (mai ales despre hardware), scopul rindurilor ce urmeaza este doar sa iti ofere un punct de pornire pentru a invata programarea microcontrolerelor Microchip folosind limbajul de programare C din mediul oferit de Mikroelektronika - adica in mikroC. Restul este invatare proprie, studiu, efort personal. Oricum, nimic in viata nu vine de-a gata, insa ne bucuram cand suntem ajutati sa incepem ceva nou, ceva care ne usureaza startul.

Cum traditia in programare cere ca primul program sa fie clasicul "Hello World!", aici vom face un Hello World in care microcontrolerul ne va saluta aprinzand si stingand un LED legat la unul dintre pinii sai.

Detalii despre LEDuri, conectarea acestora la microcontroler si alte lucruri care sunt de baza gasiti la Mikroelektronika pe site aici

Pe placa mea am un LED legat la portul D, bitul 0. Fizic este legat la pinul 19 al microcontrolerului. Aceste porturi sunt de fapt pinii microcontrolerului. Ei pot accepta semnale electrice din exterior, adica pot fi intrari sau pot ei sa genereze semnale electrice in exterior, adica pot fi iesiri. Deci trebuie sa fie setat bitul 0 al portului D (pinul 19) ca iesire si sa ne aprinda si sa ne stinga LEDul. Cum anodul LEDului este in exterior la +5Vcc si catodul este la microntroler, va trebui sa punem pinul sa dea un 0 logic astfel incat LEDul sa se aprinda.

Aici intervine documentatia microcontrolerului PIC18F4550 (aici gasiti documentatia: PIC18F4550): la pagina 4 a documentului gasim diagrama pinilor, acolo vedem ca RD0 corespunde pinului 19 (bitul 0 al portului D se numeste si RD0). Urmatorul pas in documentatie este sa citim despre portul D - pagina 122 - "10.4 PORTD, TRISD and LATD Registers".

Acolo scrie ca:
PORTD is an 8-bit wide, bidirectional port. The corresponding data direction register is TRISD. Setting a TRISD bit (= 1) will make the corresponding PORTD pin an input (i.e., put the corresponding output driver in a high-impedance mode). Clearing a TRISD bit (= 0) will make the corresponding PORTD pin an output (i.e., put the contents of the output latch on the selected pin).


Deci cum noi vrem sa aprindem un LED, trebuie sa setam pinul ca iesire, adica sa punem bitul corespunzator din registrul TRISD pe 0, deci TRISD0 = 0 pt ca RD0 sa fie iesire.

Cateva cuvinte despre registri: registrul se refera la o locatie din memoria microcontrolerului, unde biti pot fi pusi pe 1 sau pe 0 (adica setati sau resetati). In functie de valoarea unui registru, un microcontroler se comporta intr-un anumit fel. Spre exemplu daca se efectueaza o instructiune de adunare si exista depasire (spre exemplu 9+1=10, adica scriu 0, iar 1 e depasirea), atunci bitul 3 din registrul STATUS (bitul OV = overflow) va fi setat si devine 1.

Programarea unui microcontroler (si programarea in general) necesita o schema logica astfel incat sa stim ce avem de facut, in acest fel vom rezolva pas cu pas cerintele aplicatiei. Schema logica in acest caz este urmatoarea:


Schema logica pentru aprinderea unui LED conectat la pinul RD0

Bazat pe schema logica, se va scrie codul de programat microcontrolerul. Acum mai multi ani, aici era p>asul unde cautam instructiunile in documentatia microcontrolerului - pagina 309 "26.0 INSTRUCTION SET SUMMARY" (aici e documentatia: PIC18F4550). Aici gasim cum sa ii vorbim microcontrolerului pe limba lui. Cum spuneam, nu e simplu. Dar suntem salvati de mikroC: scriem cod in C pentru microcontroler si putem sa citim acest cod si chiar sa intelegem ce se petrece.

Acum vine partea cu mikroC: aici lucrurile sunt organizate pe proiecte, asadar facem un proiect nou (meniul Project -> New Project), apoi intram intr-un "wizard" care ne ajuta sa facem setarile necesare i.f.d. microcontroler, frecventa de ceas, numele proiectului, locatia pe harddisk etc. Eu am folosit un PIC18F4550 cu un cuart de 20MHz si un LED legat pe RD0, schema e mai jos:



Urmeaza imaginile de mai jos pentru a realiza un nou proiect:


Odata facuti acesti pasi, ajungem la locul unde se poate incepe scrierea programului urmand schema logica. O paranteza: aplicatiile de inceput in mod nu vor revolutiona lumea, fiind aplicatii clasice, iar cum la inceput e nevoie de ajutor, vom cauta proiecte date de exemplu; in mod cert e bine sa tragem cu ochiul la ceea ce au facut altii.

Sursa arata ca mai jos. Comparatia intre sursa si schema logica face clar ceea ce se petrece in codul scris. Toate elementele scrise sunt explicate pe larg in sectiunea "Help" a mikroC (apasa tasta F1).

void main() {

TRISD0_bit = 0; // set direction to be output for pin RD0 - page 122

/*
PORTD is an 8-bit wide, bidirectional port.
The corresponding data direction register is TRISD.
Setting a TRISD bit (= 1) will make the corresponding PORTD
pin an input (i.e., put the corresponding output driver in
a high-impedance mode).
Clearing a TRISD bit (= 0) will make the corresponding PORTD
pin an output (i.e., put the contents of the output latch on
the selected pin).
*/


do {
RD0_bit = 0; // Turn OFF LED on PORTD, pin RD0 - page 124
Delay_ms(1000); // 1 second delay
RD0_bit = 1; // Turn ON LEDs on PORTD
Delay_ms(1000); // 1 second delay
} while(1); // Endless loop
}


Pentru a introduce comentarii plasam "//" la inceput de rind, iar daca avem un bloc de comentarii, plasam comentariile intre "/*" si "*/".

Dupa ce am scris codul, urmeaza sa il compilam. Adica se verifica sintaxa si daca este corecta, atunci se genereaza un fisier, anume HelloWorld.hex. Un lucru important trebuie remarcat: un cod compilat cu succes nu este un cod care face neaparat ceea ce dorim noi in aplicatie. Am vazut multe confuzii de tipul: nu inteleg de ce nu merge ca doar a fost compilat fara erori! Erorile de fapt sunt in logica cu care am facut codul, nu in sintaxa, e ca si cum ai vorbi corect, dar fara sens (ca in parlament spre exemplu). Compilatorul ne spune doar ca avem cod corect dpdv sintactic, dar nicidecum ca aplicatia noastra e corecta!

Astfel meniul "Build" -> Build va verifica codul si va produce fiserul HelloWorld.hex, jos pe ecran se vede ca a fost compilat cu succes. Asadar am creat primul program pt microcontroler.


Compilare folsind meniul Build


Compilare folsind scurtatura la meniul Build


Rezultatul compilarii - un succes total :) (de obicei la primul program se mai uita o virgul, o paranteza si nu iese, e frustrant, dar ce nu te omoara te face mai puternic :) )


Cateva cuvinte despre fisierele pe care le genereaza moikroC:

HelloWorld.c - contine codul in C pe care l-am scris

HelloWorld.mcppi - este fisierul care contine setarile proiectului, daca vrem sa deschidem intreg proiectul, acesta este fisierul corect.

HelloWorld.hex - fisierul binar care contine codul cu care trebuie programat microcontrolerul.

Dupa ce am vazut ca sintactic programul este corect, urmeaza sa simulam functionarea lui in simulatorul software (in debugger).

Pasul urmator: simularea codului in debuggerul mikroC

7 comentarii:

  1. Folosesc si programez de ceva vreme MCU dar a scrie programe i-mi parea ceva SF.In mod cert
    este o munca laborioasa,deloc la indemana oricui,
    insa acest articol a fost o revelatie.I-ti arata clar 'de unde sa-l apuci'.Inarmat cu putin entuziasm si vointa voi incerca primul proiect.

    RăspundețiȘtergere
  2. Multumesc mult! Foarte bine explicat!

    RăspundețiȘtergere
  3. Am un cod sursa si vreau sa fac ceva modificari dar nu stiu cum ,ma puteti ajuta?

    RăspundețiȘtergere
    Răspunsuri
    1. Depinde de ce modificari sunt, trebuie vazut si apoi pot spune da ori nu. Lasa un e-mail sa vorbim mai in detaliu (nu public adresa).

      Ștergere
  4. Va salut
    Am un cod care vrea sa il trimit de pe un pic prin emisie.....
    De pe arduino il pot folosi sa il trimit prin cabluri si anume transmisie dar vrea sa il fac pe emisie
    S anume imi trebuie un cod care sa bag codul meu si codul masina sa imi trimita codul meu prin emisie pentru ca la iesire ăic vreau sa ii pun un emitator rf ...

    Se poate ?
    Va multumesc daca e cinev sa ma ajute ....

    RăspundețiȘtergere
    Răspunsuri
    1. O schema si inca niste explicatii mi-ar fi de ajutor sa inteleg exact si va spun daca se poate ori nu. Lasati-mi un email (nu il public) si mai vorbim.

      Ștergere
  5. Va salut
    Am un cod care vrea sa il trimit de pe un pic prin emisie.....
    De pe arduino il pot folosi sa il trimit prin cabluri si anume transmisie dar vrea sa il fac pe emisie
    S anume imi trebuie un cod care sa bag codul meu si codul masina sa imi trimita codul meu prin emisie pentru ca la iesire ăic vreau sa ii pun un emitator rf ...

    Se poate ?
    Va multumesc daca e cinev sa ma ajute ....

    RăspundețiȘtergere