Sari la conținut
ELFORUM - Forumul electronistilor

Invatat programare de la zero


Postări Recomandate

Ordinea fireasca pentru a invata programarea unui microcontroler ar fi, in ordine, invatarea arhitecturii acestuia, a instructiunilor si a programarii in limbaj de asamblare. Acesta este indispensabil cand se urmareste obtinerea unui cod compact, rapid si foarte precis. Deoarece exista foarte multa documentatie despre stramosescul 16F84, este bine sa se porneasca cu echivalentul mai ieftin si mai performant 16F628A. Pentru comoditate se poate trece ulterior si la limbaje de nivel mai inalt.

Link spre comentariu

@puriu, este si acesta un punct de vedere.

Crezi ca printre picaturi poti face ceva in directia aceasta? Poate un topic nou unde sa "arunci un bolovan" sperand sa "pornesti avalansa"? Adica sa inceapa sa posteze si ceilalti care cunosc bine limbajul de asamblare ...

 

Ar fi util sa avem mai multe optiuni, mai multe viziuni si modalitati de a aborda ceea ce numim "programare embedded". Este important insa sa facem totul cat mai intuitiv pentru ca daca vrem abstractizari nu avem decat sa citim un manual gros si greu de programare.

Editat de mars01
Link spre comentariu

Mai departe.

 

Scriam mai devreme:

 

Registrii asociati pentru portul A sunt:

PORTA, TRISA, CMCON, CVRCON, ADCON1.

Citesti despre fiecare registru in parte si ce face fiecare "intrerupator" mai corect spus, bit, din fiecare din registrii de mai sus.

 

Mai pe scurt, dupa ce citesti o sa te lamuresti ca din:

- PORTA, bit 0, vei schimba starea pinului 2 (pe care l-am ales noi sa il folosim)

- TRISA, bit 0, vei configura pinul 2 ca si iesire digitala.

- CMCON - in acest registru trebuie dezactivezi comparatorul (periferic care este conectat se pare si el la acest pin cu ceva)

- ADCON1 - in acest registru trebuie sa dezactivam perifericul de intrare analogica pentru pinul 2

 

In etapa anterioara am dezactivat comparatorul.

 

2. Dezactivam convertorul analog digital (ADC) adica anulam perifericul de intrare analogica sau cu alte cuvinte scapam de AN0 din eticheta de pe pinul 2 (eticheta este RA0/AN0).

 

In datasheet, la pagina 127 avem sectiunea 11. Analog to Digital converter

 

Posted Image

 

Registrul ADCON1 (il gasim la pagina 128) permite coexistenta atat de pini configurati ca intrari (sau iesiri) digitale cat si pini configurati ca intrari analogice (adica intrari de convertor ADC - analog to digital converter).

 

Dar cum in aplicatia noastra de "licurici" nu ne intereseaza sa folosim NICI-O intrare in configuratie analogica, putem pur si simplu sa dezactivam tot convertorul ADC din chip. Cu alte cuvinte nu vom mai putea folosi nici-o intrare analogica pe nici-un pin. Aceasta se face din registrul ADCON0 gasit chiar pe pagina 127 a datasheet-ului.

 

Vedem ca bitul 0 (zero) al acestui registru este ADEN care:

 

Posted Image

 

Asadar tot ce trebuie facut este sa scriem un 0 logic (zero logic sau LOW) pe bitul 0 al registrului ADCON0 pentru a dezactiva convertorul ADC. Restul de biti nu ne mai intereseaza pentru ca dezactivam total ADC-ul.

 

So,

scriem in binar pentru lizibilitate:

ADCON0 = 0b00000000;

[Nota: sunt o gramada de zero pe primele 7 pozitii pentru ca nu ne intereseaza ce este acolo. Important este ultimul bit, adica bitul 0. Acela trebuie sa fie 0 logic (zero) pentru a dezactiva ADC-ul. Puteam sa scriu si ADCON0 = 0b11111110; rezultatul era acelasi pentru ca pe ultimul bit avem valoarea zero. Evident, in acest caz mai jos, in format zecimal sau in format hexazecimal apareau valorile echivalente]

 

sau pentru usurinta putem scrie in zecimal:

ADCON0 = 0;

sau in hexa:

ADCON0 = 0x00;

Tadaaa, am terminat si cu configurarea (de fapt dezactivarea) peifericului ADC care era prezent pe pinul 2 al controlerului, unde vrem sa conectam LED-ul.

 

Pentru ca am facut toate aceste configurari, pinul devine DIGITAL I/O (adica se poate seta ca intrare sau iesire digitala). Nu trebuie sa facem nimic altceva pentru a il desemna ca pin I/O (pin input/output) sau pin digital. Prin toate configurarile facute, fiindca i-am luat toate celelalte posibilitati a ramas una singura adica aceea de a fi pin I/O.

 

Mai ramane sa il configuram ca IESIRE (tineti cont ca el poate fi configurat si ca INTRARE, asadar trebuie sa ii spunem controller-ului ce sa fie). In mod default, la pornirea controlerului, in datasheet scrie ca pinul 2 (ca si ceilalti) sunt setati ca intrari (intrarile sunt atunci cand bitii corespunzatori pinilor sunt 1 logic - 1 seamana cu I de la intrare - si acei pini sunt Output, iesiri cand bitii sunt 0 logic - 0 seamana cu O de la output).

 

Setarile aceastea de INTRARE sau IESIRE se fac din registrul TRISx (unde x este portul in cauza: A, B, C sau E) in cazul nostru TRISA. Dupa care ne putem folosi de registrul PORTA ca sa il facem LOW sau HIGH, dupa caz.

 

Posted Image

 

Va urma.

 

LE:

Spuneam mai sus ca nu conteaza ce scrii in restul de biti ai unui registru atata timp cat perifericul corespunzator (pe care il controleaza acel registru) este dezactivat. Cand se doreste dezactivarea perifericului, este important bitul (sau btii in anumite cazuri, vezi cazul comparatorului unde avem 3 biti care trebuie sa fie 1 pentru ca sa dezactivam comparatorul) de ENABLE/DISABLE. 

Daca acel bit il initializam incat sa dezactivam perifericul (cel mai adesea dezactivarea se face cand se face "clear" la bitul in cauza, adica se pune un 0 logic in acel bit iar activarea apare cand se face "set" la bitul in cauza adica atunci cand se pune 1 logic in acel bit) atunci restul de biti din registru numai conteaza. Este similar cu situatia cand avem un televizor care l-am oprit din buton. Dupa aceea numai conteaza ce butoane apasam de pe panelul de control ca nu se intampla nimic.

 

Tineti cont insa ca exista registri in controler unde fiecare bit conteaza. Acolo numai poti face cum am facut mai sus. Acolo trebuie sa folosesti o tehnica speciala care sa lase ceilalti biti in starea lor, fara sa-i atingem si sa modificam doar bitul (sau de ce nu, bitii) carora vrem sa le modificam valoarea.

Un exemplu este registrul INTCON dar aceasta este o alta poveste pentru mai tarziu.

 

Sa nu va fie teama sa faceti search in pdf-ul cu datasheet-ul controlerului (adica pe romaneste, foaia tehnica a controlerului) dupa numele unui registru anume. In felul acesta vedeti cam ce influenteaza.

 

Datasheet-ul are si un loc unde sunt listati toti registrii controlerului. Si adesea prin fiecare sectiune a datasheet-ului, cand se trateaza un periferic, se listeaza ce registri sunt pertinenti pentru acel periferic (modul).

Editat de mars01
Link spre comentariu

Excelenta initiativa ; o asteptam de mult !

 

Am 1000 de intrebari dar nu vreau sa ramificam prea mult topicul asa ca o sa astept expunerea dumneavoastra . O intrebare am totusi : nu puteti posta programul pe care il analizam ? ca sa putem merge si noi pe linii si sa urmarim mai usor desfasurarea programului ? 

Link spre comentariu

Pai tot ce am scris pana acum in posturile anterioare descriu doar 3 ... 4 linii de program.

Am considerat ca mai intai este necesar sa intelegem ce se intampla "sub capota", vorba vine.

 

Dupa ce intelegem toata chestia asta cu registrii controlerului, am acoperit practic 50% din ce inseamna programarea embedded.

Tine cont ca cca 90% din programarea embedded este accesibila tuturora. Restul de 10% este ceea ce face diferenta dintre noi ca hobby-sti si cei din tagma profesionistilor (tot felul de tehnici si algoritmi, pointeri, pointeri la functii, pointeri la pointeri, acestea sunt o parte din cei 10%).

Eu zic ca daca facem ordine in cei 90% este suficient ca sa incepem, restul de cei 10% vin dupa multa "transpiratie" si studiu personal asiduu.

 

LE: ceee ce am scris pana acum, in cea mai mare parte se aplica in orice limbaj, inclusiv in asamblare pentru ca descrie arhitectura interna a controlerului. Se poate vedea ca fac referire continua la pasaje din datasheet.

Programatorul embedded practic doarme cu datasheet-ul in brate si eventual cu application notes, daca exista. Indiferent de limbajul in care programeaza.

Editat de mars01
Link spre comentariu

FELICITARI  , putini au bunavointa sa invete si pe altii, mi-am pus mereu intrebareade ce nu gasesc docomentatii tehnice  , tutoriale in limba romana. ma interesa documentatii legate de PLC miniPLC senzori traductoare multe din cele gasite pe net au scop didactic (dar nu in limba romina)  daca aveti placerea  invatati si pe altii .

Link spre comentariu

Multumesc pentru aprecieri dar sincer astept si alti colegi binevoitori sa intervina, sa completeze pentru ca este un domeniu vast iar cunostiintele mele sunt limitate.

 

Bun.

 

In lupta noastra cu registrii inamicului PIC 16F877A pentru a face din pinul 2 un pin iesire digitala, fiind aliati cu datasheet-ul (foaia tehnica) oferita de Microchip, am "doborat" pana acum:

- registrul CMCON -> am dezactivat comparatorul cu linia:

CMCON = 0b00000111; 

- registrul ADCON0 -> am dezactivat complet convertorul ADC (analog to digital converter) cu linia:

ADCON0 = 0b00000000; 

Mai departe.

 

3. In lista registrilor asociati portului A mai este si un registru CVRCON.

Este un registru care controleaza o referinta de tensiune interna pe 4 biti (adica sunt 2^4 - 2 la puterea 4 = 16 trepte de tensiune. Aceasta referinta ajustabila este folosita de comparator cand este setat intr-un anume mod.

In principiu daca am dezactivat comparatorul nu ar trebui sa mai avem treaba cu acest periferic (modul) care produce o tensiune de referinta.

 

Dar tot din principiu, ca sa mai reducem si din consum (foarte mic dar oricum este acolo) hai sa il dezactivam si pe acest periferic prin configurarea registrului sau, CVRCON.

 

In datasheet la pagina 141 gasim:

 

Posted Image

 

Asadar, daca facem bitul 7 din registrul CVRCON zero, adica bitul CVREN il incarcam cu valoarea zero, vom dezactiva modulul (perifericul) care genereaza tensiunea de referinta ajustabila pentru comparator.

Fiindca registrul se ocupa numai de acest periferic, putem fara grija sa il initializam pe tot cu 0 logic (adica ii facem "clear" la tot).

CVRCON = 0b00000000;

Atentie: pentru dezactivare conteaza numai primul 0 de dupa '0b' adica bitul 7. Restul pot fi ce vreti voi. In acest caz este asa dar in alte cazuri nu, pentru ca spuneam ca sunt unii registri care trebuie tratati cu grija si modificat doar bitul care vrem sa il modificam. Nu este cazul aici asa ca mergem mai departe.

Misiune indeplinita.

Editat de mars01
Link spre comentariu

Ne apropiem rapid de momentul cand o sa trecem la programarea efectiva in mikroC si sa facem programul nostru "licurici".

 

Dar inainte de aceasta mai avem de tratat doi registri: TRISA si PORTA, ambii registri asociati portului A (se vede dupa 'A'-ul de la final).

Am pastrat acesti registri la final pentru ca sunt extrem de folositi si o sa va izbiti de ei tot timpul. 

 

[NOTA: Controlerele din seria 16F clasica au acesti registri TRISx si PORTx. Controlerele din seria 18F (si controlerele din seria 16F Enhanced) mai au un registru LATx. Unde x este numele portului(A sau B sau C sau D sau E samd functie de cat de multi pini are controlerul - cu cat mai multi pini cu atat mai multe porturi pentru ca spuneam ca pinii controlerului sunt grupati cate maxim 8 dar se poate si mai putini, minus pinii dedicati: alimentare, oscilator). O sa vorbim de spre LATx si ce aduce el in plus mai tarziu cand o sa discutam de problema READ-MODIFY-WRITE.

END NOTA]

 

4. Registrul TRISA.

 

Acest registru seteaza directia pinului.

Daca bitul asociat pentru pin este facut 1 logic (adica este "setat") atunci pinul asociat bitului este facut INPUT (intrare).

Daca bitul asociat pentru pin este facut 0 logic (adica este "cleared") atunci pinul asociat bitului este facut OUTPUT(iesire).

 

Remarcati ca regula mnemotehnica faptul ca 1 logic seamana cu I de la INPUT si 0 logic seamana cu litera O de la OUTPUT.

 

Posted Image

 

Remarcati ca directia pinului RA0 (adica pinul 2 al controlerului)  se modifica din bitul registru TRISA pe aceasi pozitie cu numarul din nume.

Mai concret,

directia (intrare sau iesire) pentru pinul RA0 se face modificand bitul 0 al registrului TRISA.

directia (intrare sau iesire) pentru pinul RA1 se face modificand bitul 1 al registrului TRISA.

directia (intrare sau iesire) pentru pinul RA2 se face modificand bitul 2 al registrului TRISA.

..............

directia (intrare sau iesire) pentru pinul RA5 se face modificand bitul 5 al registrului TRISA.

 

Observati ca m-am oprit la 5.

De ce?

Pentru din datasheet se vede ca portul A are doar 6 pini marcati RA0:RA5 (si care corespund pinilor fizici 2,3,4,5,6,7)

 

Posted Image

 

Bun.

 

Vrem ca pinul 2 adica RA0 sa fie iesire. Regula mnemotehnica ne spune ca il vom face pe bitul 0 al registrului TRISA, 0 logic (adica ii facem "clear"). 0 logic de la Output.

TRISA = 0b11111110;

Observati ca am lasat restul de biti in 1 logic (adica pinii asociati sunt  INTRARI) si doar bitul 0 corespunzator pinului RA0 (sau mai bine zis pinul 2 al controlerului) este in 0 logic adica IESIRE. Spun "am lasat" pentru ca dupa cum am citit noi in datasheet anterior, la pornirea controlerului bitii din TRISA sunt in 1 logic adica toti pinii asociati sunt intrari.

 

PARANTEZA:

Este un lucru bun de stiut ca pinii sunt INTRARI la pornirea controlerului pentru urmatorul motiv.

 

Sa zicem ca vom conecta pe unul din acesti pini grila unui tranzistor MOSFET-N cu care o sa controlam un motor. Un pin de controler nu are atata curent cat sa poata porni un motor si din aceasta cauza ne folosim de un MOSFET ca de un switch.

Stim ca MOSFET-ul nu are nevoie de cine stie ce curent pentru a fi pornit, doar atata cat sa incarce capacitatea de intrare si sa treaca de platoul Miller. Asa ca vom conecta un MOSFET-N ca sa pornim motorul (logic level adica cu un Vgs-th In jur de 1 .. 2 V astfel incat atunci cand pinul controlerului trece in 1 logic - adica ~ 3.3V sau 5V functie de controller - sa se deschida la maxim, Rds minim).

Dar la pornirea controlerului, pentru un timp foarte scurt, pana programul probabil va seta acel pin ca pin digital si ii va da valoarea 0 logic ca sa nu porneasca motorul pana nu apasam de exemplu un buton sau cine stie ce senzor, acel pin al controlerului va fi INTRARE.

Ori atunci cand pinul este in starea de INTRARE, el este floating adica poate avea orice potential intre 0V si VDD (tensiunea de alimentare a controlerului). Si cum MOSFET-ul nu are nevoie de cine stie ce curent pentru a porni, te pomenesti ca porneste motorul aiurea, aleator. Ba porneste, ba se opreste de zici ca a innebunit :)

 

Problema se rezolva usor cu o rezistenta de pull down din grila MOSFET-N catre GND cu o valoare de cca 47K sau mai mare functie de cat de zgomotos dpdv electric este mediul ambiant.

Aceasta va avea grija sa tina potentialul pe grila MOSFET-ului in 0 logic pana cand vom modifica pinul clar in 1 logic.

Din aceasta cauza este bine de stiut ca portul A (cel putin) porneste setat ca INTRARI.

END PARANTEZA.

 

Ce te faci insa cand vrei sa faci un pin INTRARE (sau IESIRE) dar ceilalti vrei sa ii lasi cum sunt ei? Poate ca programul i-a setat cumva functie de anumite conditii si nu vrei sa stai sa tii minte ce erau fiecare....

 

Exista o modalitate care am sa o explic mai tarziu cand vom vorbi de operatiile cu biti dar deocamdata luati-o ca atare:

Pentru setarea (adica punerea de 1 logic pe un bit, adica in cazul nostru transformarea in INTRARE) unui bit in TRISA se foloseste urmatorul cod:

TRISA = TRISA | (1 << x);// unde x este numarul bitului in port la care vrem sa ii facem pinul asociat INTRARE// pentru RA0 este asa:TRISA = TRISA | (1 << 0);// care se mai poate scrie:TRISA = TRISA | 0b00000001;// se mai poate scrie:TRISA = TRISA | 1;//sau se mai poate scrie folosind operatorul compus:TRISA |= 1;

Pentru a face clear (adica punerea de 0 logic pe un bit, adica in cazul nostru transformarea in IESIRE) unui bit in TRISA se foloseste urmatorul cod:

TRISA = TRISA & (~(1 << x));// unde x este numarul bitului in port la care vrem sa ii facem pinul asociat IESIRE// pentru RA0 este asa:TRISA = TRISA & (~(1 << 0));// care se mai poate scrie:TRISA = TRISA & ~(0b00000001);// se mai poate scrie:TRISA = TRISA & 0b11111110;//sau se mai poate scrie folosind operatorul compus:TRISA &= 0b11111110;//sau aici se vede utilitatea format hexazecimal:TRISA &= 0xFE;
Editat de mars01
Link spre comentariu

Multumesc dar si eu am primit asa ca dau mai departe ...

 

Mai greu de inceput :) ca pe urma vine de la sine ...

Interesat la o mica contributie? :) Putem imparti subiectele ca sa nu duplicam eforturile ... Nu neaparat acum, ma refer cand o sa ajung la subiecte mai avansate unde o sa fie mai greu de explicat incat sa fim si intelesi ...

Editat de mars01
Link spre comentariu

pentru a invata programare, in sensul de a intelege, trebui sa cunosti "limbajul", termenii cu care se lucreaza, si nu in ultimul rand arhitectura masinii ce trebuie programate.

 

legat de termenul de "registru", nu am vazut sa fie facut referire clara ca pot fi registri de intrare si iesire, registri doar de intrare, registri doar de iesire (care se pot asemana cu intrerupatoarele si schimba o actiune). Registri pot fi mapati pe memorie (pe ROM - read only memory, RAM) sau mapeaza direct stari de control sau semnale externe.

 

nu am vazut intrebari, de la cei care invata, comentarii la pagini intregi de text. Ar fi util ca @mars01 sa primeasca un raspuns de la cei interesati, daca li se pare mai usor de inteles, sau daca termenii sau expresiile le sunt necunoscute, sa se poata "calibra", sau sa puna accent mai mult sau mai putin pe anumite aspecte.

 

o intrebare de la mine: ce e aia periferic?

Link spre comentariu

Creează un cont sau autentifică-te pentru a adăuga comentariu

Trebuie să fi un membru pentru a putea lăsa un comentariu.

Creează un cont

Înregistrează-te pentru un nou cont în comunitatea nostră. Este simplu!

Înregistrează un nou cont

Autentificare

Ai deja un cont? Autentifică-te aici.

Autentifică-te acum
×
×
  • Creează nouă...

Informații Importante

Am plasat cookie-uri pe dispozitivul tău pentru a îmbunătății navigarea pe acest site. Poți modifica setările cookie, altfel considerăm că ești de acord să continui.Termeni de Utilizare si Ghidări