Sari la conținut
ELFORUM - Forumul electronistilor

Invatat programare de la zero


riciu

Postări Recomandate

"bit 13 CP il facem 0 = nu vrem sa protejam la copiere "

 

 In data sheet scrie asa: 

 

bit 13 CP: Flash Program Memory Code Protection

                bit 1 = Code protection off

                     0 = All program memory code-protected

 

deci trebuie sa fie 1 ca sa nu fie protejat, nu?

Link spre comentariu

OK.

 

Modulul WatchDog a aparut ca urmare a expeditiilor spatiale sau in medii periculoase (radiatii etc) cand un operator uman nu poate din diferite motive sa reseteze un automat cu microcontroler in mod direct si/sau rapid, atunci cand controlerul se blocheaza.

In cazul expeditiilor spatiale, problema este data de intarzierea comunicatiilor radio datorata distantei mari.

 

Inginerii au venit cu solutia de a implementa dpdv hardware un modul timer mai aparte care functioneaza independent de controller si care odata activat dintr-un registru special (este vorba de CONFIGURATION WORDS la controlerul nostru 16F877A) va incepe sa se incrementeze. In momentul cand ajunge la valoarea maxima care se poate stoca in el, va da un reset controlerului si o ia de la capat (de la 0) cu numaratul.

 

Cu alte cuvinte, dupa un timp xxx el va reseta controlerul automat.

Daca e lasat de capul lui, va reseta controlerul in mod regulat ceea ce este contraproductiv.

De acea in programul care ruleaza in controler trebuie sa fie resetat regulat, inainte sa expire (adica sa ajunga la valoarea maxima). Un exemplu de comanda assembler de resetare a timerului WatchDog este CLRWDT (de la clear watchdog).

 

Utilitatea sta in faptul ca daca de ex controlerul se blocheaza intr-o sectiune de program (poate un bug, poate o interferenta electromagnetica) el nu va mai ajunge sa dea comanda de reset pentru timerul WatchDog, timerul WatchDog isi va face treaba, va ajunge la maxim (va expira) si va reseta controlerul. Sperand ca odata cu resetarea controlerului, factorul care a provocat blocajul nu va mai fi prezent si programul din controler va rula corect.

 

De aceea spuneam ca trebuie avut grija in program si resetat periodic acest timer cu o comanda speciala, intotdeauna inainte ca acest timer sa expire (Sa ajunga la maxim). Evident daca cineva la activat in prealabil.

 

E ceva ca o bomba care are un temporizator si tick tick contorizeaza catre zero. Doar ca sta cineva langa ea si inainte sa ajunga la zero, reseteaza temporizatorul dintr-un buton de reset :) asa ca nu detoneaza niciodata.

"bit 13 CP il facem 0 = nu vrem sa protejam la copiere "

 

 In data sheet scrie asa: 

 

bit 13 CP: Flash Program Memory Code Protection

                bit 1 = Code protection off

                     0 = All program memory code-protected

 

deci trebuie sa fie 1 ca sa nu fie protejat, nu?

 

Corect, iar am dat-o-n bara.

Din pacate eu nu pregatesc un material si scriu la inspiratie si din ce stiu. Asta face ca ceea ce scriu sa fie predispus la greseli. De acea am si emis avertismentul ca pot fi greseli. Si iata ca sunt.

Scriu repede si nu stau sa verific 100%.

Imi pare rau dar nu cred ca pe viitor se va schimba ceva.

Editat de mars01
Link spre comentariu

Am sa incerc sa fac un gen de descriere a programului 2 din postul 66 pagina 5.

 

Functionare:

 

Vrem ca atunci cand apasam pe buton, led-ul sa se aprinda si sa ramana aprins pentru un anume timp, predefinit, dupa care se va stinge.

Daca in timp ce led-ul este aprins mai apasam o data pe buton, timpul scurs nu va mai conta si temporizarea este resetata la valoarea initiala.

 

- avem un pin setat ca intrare digitala, este vorba de pinul 2.

- mai avem un alt pin setat ca iesire digitala, este vorba de pinul 33 

 

Nota: intrare sau iesire digitala inseamna ca pinul in cauza poate avea numai stari de LOW (~0V) sau HIGH (~Vdd). Intrarea va sesiza aceste nivele (provenite din mediul ambiant) si le va stoca in registrul PORTx corespunzator. Iesirea va genera aceste nivele (conform la ce setam noi de data aceasta) functie de ce este in registrul PORTx, bitul corespunzator pinului.

 

- in montajul fizic vom monta un rezistor (de pull-up) din pinul 2 catre Vdd. Acest rezistor are rolul de a tine nivelul default pe pin in HIGH. In acest fel, intrarea va fi LOW cand apare un nivel de LOW pe pinul 2 (RA0). Tot din pin se va conecta un switch catre GND. Acest switch va fi responsabil de aparitia nivelului LOW pe pinul 2 (setat ca intrare) atunci cand este apasat (ON). Spunem ca intrarea in aceasta configuratie este ACTIVE LOW.

Pe pinul 33(RB0) conectam un LED catre GND. Acest LED se aprinde cand bitul RB0 din PORTB este 1 si se stinge cand bitul RB0 din PORTB este 0. Aceasta configuratie se numeste "sourcing" deoarece pinul ofera o tensiune catre LED. 

[Daca LED-ul era conectat de la pin la Vdd atunci se numea ca pinul face "sinking" deoarece ofera LED-ului o cale catre GND]

 

NOTA: in general pinii setati ca iesiri digitale sunt de tip push - pull adica pot genera intern atat nivelele de HIGH cat si LOW. Exista si cazurile in care iesirile sunt de tip Open -Drain si au nevoie de un rezistor de pull-ul de la pin catre Vdd. Un exemplu este pinul RA4 al controllerului. In datasheet, pagina 10 tabela 1-3 gasiti toate datele necesare cu privire la pini. Unii pini atunci cand sunt setati ca intrari digitale sunt intrari Schmitt trigger (cu histerezis).

 

Observati ca primele linii dupa void main() (aceasta este functia principala in program, intotdeauna o sa o gasiti in orice program. Uneori este scrisa altfel, void main (void) ) se face declaratia variabilelor (cat si initializarea, desi nu este obligatoriu sa fie facuta exact aici. Dar este recomandat).

 

Declaram variabila timp cu tipul unsigned int

Daca va aduceti aminte, unsigned int inseamna ca variabila timp poate avea numai valori intre 0 si 65535.

O initializez cu valoarea 60000. (In program este gresit initializata cu 6000, am mancat un zero tot schimband aceasta valoare ca sa gasesc una care sa imi convina). Aceasta valoare de 60000 reprezinta timpul cat LED-ul este aprins.

In variabila timp (care pleaca cu o valoare de 60000) se stocheaza in cadrul programului "trecerea timpului". Deci rolul sau este de a tine cont re trecerea timpului.

 

Urmatoarele doua linii (observati ca mai toate liniile se termina cu punct si virgula, este o regula in C spre deosebire de alte limbaje care nu cer asa ceva) contin delaratiile a doua constante. Si fiind constante, obligatoriu le si dam valoare.

Ambele au tipul unsigned char  asadar valorile pe care le putem pune in ele (numai la initializare adica in momentul declaratiei) pot fi intre 0 si 255. Noi vom stoca in ele valorile 1, respectiv 0 asadar ne incadram.

Motivul pentru care cream aceste constante este ca sa ne fie mai usor in program. Este mai sugestiv cand facem o testare daca cutare pin este ON decat daca testam daca cutare pin este 1. Sau in cazul nostru concret, este mai sugestiv sa facem ON bitul RB0 din PORTB (corespunzator pinului 33) decat sa spunem ca il facem 1.

Aceasta pentru ca ON = 1 (ON fiind constanta de tip unsigned char)

La fel si pentru OFF = 0 (OFF fiind constanta de tip unsigned char).

 

Urmeaza o sectiune de initializare  in care avem de-a face cu registri, facem din pinii alesi, pini digitali (prin dezactivarea modulelor care nu ne intereseaza: comparator, convertor ADC, referinta variabila de tensiune. Pe urma, dupa caz, ii facem intrari sau iesiri. La pinul facut iesire (RB0 sau bitul 0 din PORTB) ii incarcam si o valoare initiala de 0 pentru a stinge LED-ul.

 

Nota: Amintesc ca valoarea de 0 in bitul din PORTx corespunzator pinului hardware inseamna ca pe pinul hardware avem 0V si daca incarcam valoarea 1 in acel bit, pe pinul HW corespunzator vom avea o tensiune de cca Vdd (in cazul nostru ~5V).

 

Urmeaza bucla principala a programului.

Un program in microcontroler incepe cu o linie, executa fiecare linie in parte pana la ultima linie, executa si ultima linie si si-a terminat job-ul. In acest moment sta degeaba si este total inutil. Adica trece odata prin program si s-a terminat.

Ori noi nu vrem acest gen de comportament. Noi vrem ca el, controlerul, sa functioneze non-stop, urmarind schimbarile unor pini (prin registrii aferenti) sau al unor module interne (prin registrii aferenti acestora) conform cu ce ii spunem noi in program sa faca.

 

Pentru aceasta apare conceptul de bucla infinita.

Odata ce noi am facut setarile de inceput, am efectuat initializari si cand suntem gata sa incepem adevaratul program, vom introduce o bucla infinita in care programul va sta la nesfarsit (pana ii oprim tensiunea de alimentare, pana se strica :) sau pana apare un reset dat de: pinul MCLR, sau de modulul WATCHDOG sau modulul BROWN-OUT etc).

 

Bucla infinita poate aparea asa:

while(1) {//programul}

sau 

while(3==3) {//programul}

sau poate cum sugera Liviu anterior:

for(;;){//programul}

sau cum sugera colegul Vezi Muti

while(1+1 == 2) {/*programul*/}

Instructiunea while(expresie) {//cod}  va executa codul din acolade pana expresie devine falsa. Si cum 3 = 3 este adevarat intotdeauna, bucla va fi infinita.

 

Cu alte cuvinte, cand expresie devine FALSA atunci se sare peste codul din acolade si se merge mai departe cu codul ce urmeaza dupa acolada de inchidere.

Cat timp (traducere pentru "while" din lb engleza) expresie este adevarat se executa codul din acolade de la prima linie de dupa deschiderea acoladei pana la ultima linie inainte de inchiderea acoladei. Dupa care se sare din nou la inceput, la while(expresie) si se testeaza din nou expresia. Si tot asa pana expresie devine falsa.

 

[o acolada deschisa, ca si o paranteza deschisa, trebuie intotdeuna inchisa. Daca deschidem 7 acolade trebuie sa le inchidem cu alte exact 7 acolade. Este un motiv frecvent de erori la compilare, uneori te incurci in gramada de paranteze dar din fericire compilatorul verifica si iti arata unde e problema.]

 

Bun, dar cand devine expresie falsa? Cum se testeaza expresie ca sa vedem daca este falsa sau adevarata?

 

Observati in:

while (x == 3){//cod}sauwhile (y <= 10){//cod}

operatorii: '==', '<='. Alti operatori din aceasi categorie mai sunt: < (mai mic), > (mai mare), != (diferit), == (egal), <= (mai mic sau egal), >= (mai mare sau egal). Mai sunt si altii cum ar fi MOD (modulo) etc

 

Cred ca se explica singuri acesti operatori. Cand comparatia este adevarata se executa ce este intre acoladele aflate imediat dupa while(expresie). Cand comparatia este falsa se sare peste acoladele lui while(expresie) si se merge mai departe cu programul de dupa.

 

Ce nu se explica este ca de ex daca variabila x (sau y in a 2 a forma de mai sus) este initializata cu 1 (1 nu este nici 3 si nu este nici 10, si este mai mic ca 10) si, IMPORTANT, variabila respectiva (fie x, fie y) nu se modifica in interiorul acoladelor, bucla va fi infinita. Aceasta deoarece x (sau y) trebuie sa se schimbe in interiorul acoladelor lui while(expresie) pentru ca la un moment dat expresie sa fie falsa.

 

IMPORTANT: asa cum o sa vedeti in liniile de program urmatoare, avem un bug foarte insiduos si care va poate manca mult timp. Este vorba de confuzia care se genereaza uneori intre operatorul de atribuire '=' si operatorul conditional (de testare) '=='.

 

Egalul dublu testeaza expresia in care se gaseste si ofera un rezultat pozitiv (de regula numarul 1) daca expresia este adevarata si ofera un rezultat zero daca expresia este falsa.

Egalul simplu este un operator de asignare si pur si simplu face egal intre ce este in stanga sa cu ce este in dreapta sa.

 

Ex. Daca x = 32 atunci:

x = 50; //valoarea variabilei x se transforma din 32 cat era anterior in 50/*rezultatul operatiei este adevarat, deci rezultatul este 1, daca x are o valoare de 50 inainte de aceasta testare  rezultatul operatiei este fals, deci zero, daca x are o valoare diferita de 50 inate de testare, ceea ce este  cazul la noi pentru ca anterior x era 32 */x == 50; 

Va urma.

Editat de mars01
Link spre comentariu

 

Cred ca se explica singuri acesti operatori. Cand comparatia este adevarata se executa ce este intre acoladele aflate imediat dupa while(expresie). Cand comparatia este falsa se sare peste acoladele lui while(expresie) si se merge mai departe cu programul de dupa.

 

Ce nu se explica este ca de ex daca variabila x (sau y in a 2 a forma de mai sus) este initializata cu 1 (1 nu este nici 3 si nu este nici 10, si este mai mic ca 10) si, IMPORTANT, variabila respectiva (fie x, fie y) nu se modifica in interiorul acoladelor, bucla va fi infinita. Aceasta deoarece x (sau y) trebuie sa se schimbe in interiorul acoladelor lui while(expresie) pentru ca la un moment dat expresie sa fie falsa.

 

 

Cred ca nu e tot timpul adevarat. Variabila se poate schimba si in afara blocului asociat instructiunii while. Un caz ar fi, din intrerupere cu variabila globala volatila, al doilea cu salt la eticheta, in afara blocului si revenire, sa sa nu spunem si de cazul simplu cand blocul de acolade lipseste fiind folosita o instructiune simpla: "while (y<=10) y++;"

Link spre comentariu

O completare justa si la obiect, intreruperile schimba regulile jocului prin caracterul asincron (pot aparea oricand si vor intrerupe functionarea programului).

Cand o sa scriu despre intreruperi atunci am sa incerc sa explic si notiunea de variabila volatile.

Instructiunile GOTO eticheta merita mentionate dar nu merita folosite pentru ca dincolo de o anumita complexitate a programului, acesta va fi tot mai greu de urmarit si inteles.

 

E un moment la fel de bun ca oricare altul pentru a mentiona ca acoladele incadreaza mai multe linii de program care se doreste ca din punct de vedere functional sa fie executate impreuna.

De asemenea in sintaxa C se arata ca daca acolo unde in mod normal sunt folosite acolade (cu exceptia functiilor unde acoladele sunt obligatorii pentru a defini corpul functiei) nu avem decat o singura linie de program, acoladele se pot omite si se poate scrie in continuare doar linia de program urmata de punct si virgula.

Ex:

unsigned int x = 0;while (x < 10) {   x = x + 1;}//restul de program

se poate scrie fara probleme:

unsigned int x = 0;while (x < 10) x = x + 1;//restul de program

Functionarea este similara.

Editat de mars01
Link spre comentariu

TRISA = 0b11111110;

 

daca TRISA are doar 6 pini si il facem pe pinul 2 ( bitul 0) iesire, nu trebuie scris  0b111110  ???

 

Daca ce intentionezi sa scrii reprezinta:

TRISA = 0b00111110; 

care este totuna cu 

TRISA = 0b111110; 

Bitul 0 este LSB adica cel mai putin semnificativ bit (bitul cel mai din dreapta).

Datorita faptului ca TRISA arata asa:

 

Posted Image

 

Ia aminte ca bitii 7 si bitii 6 din TRISA sunt neimplementati. In principiu puteai sa scrii in TRISA asa ceva:

TRISA = 0b00111110;

sau asa ceva:

TRISA = 0b11111110;

Sau orice alta combinatie de 1 si 0 pe pozitiile 7 si 6. Nu conteaza ce scrii pe pozitiile 7 si 6 din byte. Pentru ca acei biti sunt neimplementati, doar bitii pe pozitiile 5,4,3,2,1,0 conteaza. Asa ca ambele variante sunt corecte.

Editat de mars01
Link spre comentariu

TRISA = 0b11111110;

 

daca TRISA are doar 6 pini si il facem pe pinul 2 ( bitul 0) iesire, nu trebuie scris  0b111110  ???

De obicei e specificat în datasheet ce să scrii în poziţiile rezervate, cum e cazul multora dintre regiştri.

Link spre comentariu

Revenind la oile (bitii) noastre :)

 

In postul #109 am descris programul (al 2 lea) din postul #66 pana la punctul in care se intra in bucla infinita:

while (1 == 1) {...}

S-au spus destule lucruri despre bucla infinita in care expresia din while(expresie) nu devine niciodata falsa si astfel ce este intre acoladele care apartin lui while(expresie) se va executa la nesfarsit (pana controlerul ramane fara alimentare sau primeste un reset sau, de ce nu, se blocheaza).

Colegul @core a subliniat un lucru important care arata cum intreruperile (un concept care il vom discuta mai tarziu) pot sa influenteze mersul unui program.

 

Dintr-un anume punct de vedere, intreruperile sunt cam cum sunt "minunile" in religie. O gramada de adepti vad cum din senin, fara absolut nici-un avertisment, apare o coloana de flacari sau mai stiu eu ce in fata lor, isi lasa amprenta, efecte si apoi dispare la fel de subit. Lasand in urma o gramada de indivizi cu ochii mari :)

 

Tot asa si intreruperile (unele sincrone altele asincrone) apar, genereaza efecte (cum ar fi modificarea unei variabile) si apoi dispar. Uneori ii lasa si pe programatori cu ochii holbati  pentru ca problemele date de intreruperi sunt foarte dificil de depistat chiar si atunci cand se foloseste un debugger.

 

Dar mai multe despre intreruperi mai tarziu, este un subiect, zic eu, avansat.

 

Prima linie din bucla infinita (while (1 == 1) este aceasta bucla infinita la care fac referire) este:

if (RA0_bit == 0) {   //daca intrarea este LOW...}

Observati ca acolada se deschide si se inchide. Majoritatea editoarelor dintr-un IDE (Integrated Development Enviroment) sunt capabile sa iti arate, daca dai click langa o acolada care se deschide, care este acolada corespondenta care se inchide. 

 

Atentie: daca lipseste vreo acolada (se sterge din greseala sau mai stiu eu ce, regula este ca acolada care se deschide "fura" prima acolada de inchidere chiar daca aceasta apartine altei acolade de deschidere.

Remarcati ca dupa acolade nu se pune niciodata punct si virgula (';').

 

Tratam acum intructiunea de "branching" (decizie) numita if ... else.

 

Intalnim instructiunea if (tradus "daca") atunci cand trebuie sa luam o decizie.

Forma este asa:

if (expresie) {//program}

Si se traduce: "Daca expresie este adevarata atunci executa instructiunile dintre urmatoarele acolade. Daca expresie este falsa atunci sari peste instructiunile dintre urmatoarele acolade si executa ce este dupa"

 

Spre ex:

if (x == 3) {  var1 = 1523;  j = j + 1;}k = 25;m = x * x;

Tradus ce am scris anterior:

 - daca x == 3 (remarcati dublu egal pentru ca avem comparatie si nu asignare) atunci executa in ordine: var1 = 1523 (remarcati egalul simplu care arata ca avem operatie de asignare), apoi executa j = j + 1, se termina bucla si se continua executia: k = 25, apoi se executa m = x * x samd

- daca x nu este 3 (poate fi mai mare sau mai mic) atunci se executa in ordine k = 25 urmat de executia m = x * x samd

 

Remarcati ca ce este intre acolade se executa daca si numai daca x este egal cu 3.

 

O alta forma a instructiunii decizionale if este if ... else.

 

Forma este asa:

if (expresie) {//linii de program}else {// alte linii de program}

Intr-un mod simplist traducem ce este deasupra:

"daca expresie este adevarata atunci executa ce este intre primele acolade. Daca expresie este falsa atunci, altfel (else se traduce "altfel") executa ce este in acoladele de dupa else."

 

Diferenta fata de prima situatie este ca aici se specifica clar situatiile: ori aia, ori aia.

 

Am sterpelit o poza de aici (poate cititi si acel tutorial, este foarte bun - parerea mea):

 

http://www.tutorialspoint.com/cprogramming/images/if_else_statement.jpg

 

 

Am ajuns astlfe la expresia din if (acum ma refer la programul de la postul 66):

RA0_bit == 0

Se vede clar ca este vorba de o comparatie, daca RA0_bit este zero atunci se executa ce este dupa acolada, daca RA0_bit este altceva (adica 1; RA0_bit poate lua valori doar de 1 sau 0 explic imediat de ce) se sare la acolada de inchidere si se merge mai departe cu programul.

 

RA0_bit este o chestie specifica compilatorului mikroC.

Nu are legatura cu C-ul standard.

RA0_bit este un "shortcut" , o modalitate usoara de a accesa bitul 0 din registrul PORTA.

 

Cu ajutorul RA0_bit se acceseaza un bit dintr-un registru (registrul PORTA in acest caz) si cum un bit poate avea valoare doar 1 sau 0, si RA0_bit poate avea valoare numai 1 sau 0.

 

Exista si RA1_bit pana la RA5_bit.

Desigur, daca controlerul are si alte porturi cum ar fi un port de pini hardware B (care evident are si un registru PORTB asociat) atunci gasim "shortcut-uri" RB0_bit pana la RB7_bit (daca portul are grupati 8 pini, daca sunt mai putini evident si RB bitii aia sunt mai putini :)

 

Cu alte cuvinte putem face asa:

 - Daca pinul corespunzator RA0 este setat din portul TRISA ca si intrare, 

(va amintiti ca daca pinul corespunzator lui RA0 din registrul TRISA este setat - facut 1 - atunci pinul este INTRARE, daca este cleared(sters) - facut 0 - atunci este IESIRE) 

atunci putem testa RA0_bit sa vedem daca este 0 sau 1

 

- Daca pinul HW corespunzator lui RA0 este cleared in portul TRISA, deci este iesire,

atunci putem sa asignam valori de 1 sau 0 lui RA0_bit si in consecinta pinul hardware asociat (la noi, PIC16F877A este vorba de pinul 2) va avea o valoare HIGH (1 logic), respectiv LOW (0 logic).

 

NOTA: si ca sa vezi, tipii de la mikroC, ca sa faca treburile usoare pentru noi, ne-au oferit access direct la mai toti bitii din registri, oricare registri asociati controlerului. Si sunt destul de multi ... Spre ex, putem face iesire sau intrare pe RA0 doar folosind comenzile:

TRISA0_bit = 1; (RA0 este facut intrare)TRISA0_bit = 0; (RA0 este facut iesire)

In acest fel numai este necesar sa facem operatii cu bitii din registri (ca sa influentam doar un bit si sa nu ii deranjam pe ceilalti) asa cum am atins si eu subiectul anterior si l-a dezvoltat colegul nostru @ratza in postul #73.

Editat de sofian
Link spre comentariu

Mi-am prins urechile in acolade !

 

Asdar avem expresiile :

 

if (RA0_bit == 0) { //daca intrarea este LOW
delay_ms(10); //asteptam 10 milisecunde

 

...dar acolada nu se inchide aici (cum m-as fi asteptat eu) , ci la sfarsitul programului , dupa linia "RB0_bit == OFF;"

 

De ce se inchide la sfarsit si nu dupa linia "delay_ms(10);"  ?

Link spre comentariu

Ce este intre acolade este un asa numit bloc de instructiuni. Aceasta inseamna ca se vor executa acele instructiuni atunci cand expresia evaluata in instructiunea if este adevarata. Toate instructiunile dintre acolada de deschidere si cea de inchidere.

 

Care este acolada de deschidere este usor de identificat.

Care este acolada de inchidere este mai greu de identificat, trebuie numarat acoladele sau daca se folosesc tab-urile pentru indentare corect, se poate urmari dupa acest criteriu.

Din aceasta cauza majoritatea editoarelor pentru programare au implementata acea facilitate ca daca dai un click langa o acolada deschisa iti subliniaza acolada inchisa care ii este asociata.

 

Si ca sa iti raspund punctual la intrebare, intr-adevar programul nu face nimic interesant pana nu este indeplinita prima conditie, ma refer la evaluarea din primul if, macar odata. Cand spun conditie indeplinita, se poate citi si ca, "conditie adevarata".

 

Pana nu apesi butonul odata, practic tot ce face programul este sa treaca prin bucla while (1 == 1) fara sa faca nimic altceva decat sa testeze daca butonul este apasat.

Testeaza 1 == 1, evident vede ca este adevarat, testeaza daca butonul este apasat si daca nu este este adevarat ajunge la acolada sa de inchidere adica penultima acolada (ultima acolada inchide functia void main() ) si sare din nou la instructiunea while (1 == 1) si tot asa pana apesi odata butonul. Abia atunci va incepe sa execute si altceva, mai exact ce este intre acoladele primului if.

 

LE: Am sa explic mai tarziu ce este cu prima utilizare a functiei delay_ms(10). E normal ca sa fie confuz la acest moment, nu-ti face griji. Cand ajungem la etapa aceea, curand, o sa intelegi ce si cum. Faptul ca este confuza situatia acum este o chestie educationala. Te forteaza sa iti atingi limitele in intelegere. Pentru ca ne sacaie cand nu intelegem. Asa ca atunci cand apare explicatia, esti pregatit pentru ea (practic "infometat") si se intipareste.

Editat de mars01
Link spre comentariu

Acolada adună la un loc mai multe instrucţiuni.

Exemplul 1:

if (RA0 == 0){  _delay_ms(10);}RB0 = 1;

Exemplul 2:

if (RA0 == 0){  _delay_ms(10);  RB0 = 1;}

În primul exemplu RB0 se setează indiferent de valoarea lui RA0, pe cînd în al doilea se execută doar dacă RA0 este 0.

Link spre comentariu

Tocmai ce citeam si am dat peste licurici(operandul negatie).

 

void main() {  PORTB = 0; // initializare port B(toate iesirile in low)  TRISB = 0; // port B setat ca iesire

  while(1) {   PORTB =  ~PORTB; // basculare port B(isi schimba starea)   Delay_ms(1000);   // cu o pauza de 1 secunda  }}

Interesan e ca pare mai simplu.Intradevar modifica toti pinii portului dar avnd in vedere ca avem doar un led nu are importanta(zic eu...)

 

tocmai de-aia când o să vrei să aprinzi 2 leduri în contratimp şi o să foloseşti acelaşi cod, cu copy/paste, modificând doar pinul din acelaşi port, o să-ţi bagi unghia în gât că nu reuşeşti să le faci decât să se aprindă sincron!

dar dacă pui al doilea led pe alt port, o să meargă! (da, Stan Păţitu's voice! :rade: )

Link spre comentariu

tocmai de-aia când o să vrei să aprinzi 2 leduri în contratimp şi o să foloseşti acelaşi cod, cu copy/paste, modificând doar pinul din acelaşi port, o să-ţi bagi unghia în gât că nu reuşeşti să le faci decât să se aprindă sincron!

dar dacă pui al doilea led pe alt port, o să meargă! (da, Stan Păţitu's voice! :rade: )

Exprimarea este total aiurea.

Ce problema ai cu "contratimpul" si "sincron".

Chiar ai ceva de spus? De ce ai postat aberatia de mai sus?

 

LE:  te rog sa nu raspunzi aici. Poate pe privat. Sa nu transformam incercarea lui mars01 in altceva.

Editat de Vezi Muti
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