Sari la conținut
ELFORUM - Forumul electronistilor

Invatat programare de la zero


riciu

Postări Recomandate

hai ca usor usor , incep sa ies din ceata. Cu desene in fata, cu explicatiile voastre scoase la imprimanta, cu cele din data sheet,  parca incep sa ma misc pe drumul drept si sa prind curaj. Multumesc mai ales lui mars01 ca are un stil bun de a explica, dar si explicatiile celorlalti devin pe inteles incet incet.

Link spre comentariu

Continuare Variabile (basic)

Ziceam de program, dar sa termin ce vreau sa spun despre variabile.

 

Nu am de gand sa epuizez aici tot subiectul variabilelor si al tipurilor de variabile. Vreau insa sa mentionez ca mai exista si alte genuri de variabile cum ar fi: enumerari, structuri, stringuri, arii si pointeri (ariile si pointerii sunt enumerati unul langa celalalt pentru ca exista o relatie de "rudenie" intre ei).

 

Poate vom discuta si despre aceste genuri de variabile dar mai tarziu deoarece nu sunt esentiale pentru moment. 

Cand ajungem la functii vom discuta si despre ce inseamna variabile locale si ce inseamna variabile globalevariabile statice.

Cand vom discuta de librarii, fisiere header, atingem si ce inseamna cuvantul cheie "extern".

 

Lucruri pe care poate veti vrea sa le atingeti in studiu sunt asa numitii "qualifiers" const si volatile.

Cand ajungem la intreruperi o sa vorbim despre volatile

Stiu ca las mai multe intrebari decat raspunsuri, dar sincer nu pot altfel.

 

Vorbeam anterior de asa numitele variabile "constante".

 

Cand in C se declara o variabila constanta, hai sa ii spunem constanta (pentru ca se bat cap in cap conceptele de variabil cu constant), noi facem automat si initializarea constantei cu ceva. Fie cu un numar, fie cu un string de caractere. Despre stringuri discutam mai tarziu.

 

O variabila normala o poti pur si simplu declara (tot timpul la inceputul sectiunii de program cel putin asta spune ANSI) asa:

int x;

Dar in acest moment in locatia de memorie unde este variabila x poate sa fie orice valoare. Daca am tipari variabila x (adica valoarea din ea) ar putea sa apara orice. Evident acest "orice" poate fi in intervalul -32768 ... 32767. De ce? Pentru ca intr-o variabila tip INT nu poti pune alte valori decat in acest interval.

In orice caz, daca am vrea sa stim sigur ce este in variabila pentru mai tarziu (poate facem o comparatie cu ea sau mai stiu eu ce) atunci trebuie sa o intializam cu, ceva. Poate zero de ex:

x = 0;

Sau putem face declaratie simultan cu initializarea:

int x = 0;

In cazul contantei, este obligatoriu ca odata cu declaratia sa faci si initializarea.

const int y = 0;

O variabila normala poate fi modificata in program. Acum poate x = 0, mai tarziu x = -1 si mai tarziu x poate fi 5000. Etc

O constanta, odata definita si initializata numai poate fi modificata. Deloc. Daca incerci sa o modifici in program primesti o eroare.

Remarcati cuvantul cheie: const

Cu el ii spunem programului (si programatorului care citeste programul) ca variabila declarata ca si const, pe nume y, este o constanta care va ramane cu acea valoare tot timpul.

 

La ce te ajuta constantele atunci? Mai intai programatorului ii este mai usor sa tina cont de logica programului. Cand vede "const" in program stie ca acea "variabila" este o constanta si ca nu se modifica.

In al doilea rand este mai usor de inteles cand zici asa:

const unsigned int pin_corect = 1234;

Si pe urma cand testezi in program:

unsigned int pin_introdus = ...if (pin_introdus == pin_corect) {  // daca pinul introdus este cel corect, adica pin_corect care este 1234// fa ceva}else { // altfel//fa altceva}

Variabila pin_introdus poate fi o variabila care stocheaza o valoare introdusa la un cifru.

Este mult mai sugestiv cand comparam cu "pin_corect" pentru ca denumirea "pin_corect" deja ne spune ca sectiunea de cod dintre urmatoarele acolade va reflecta succesul.

 

Daca am testa ceva de genul:

unsigned int pin_introdus = ...if (pin_introdus == 1234) {  // daca pinul introdus 1234// fa ceva}else { // altfel//fa altceva}

In acest caz, daca programul este suficient de mare, ai putea spune: "ce naiba este 1234? oare este codul corect sau doar o varianta care poate imi blocheaza definitiv intrarea"

 

Se vede utilitatea de a compara cu un nume si nu direct cu un numar ... In plus, daca acest cod "pin_corect" este folosit in mai multe locuri in program si sa zicem ca vrem sa il modificam, in loc sa cautam prin tot programul dupa 1234 si sa schimbam peste tot sa zicem in 7777, cand folosim o constanta atunci este suficient sa modificam declaratia (de fapt partea de initializare din declaratie) la inceputul programului

 

din:

const unsigned int pin_corect = 1234;

in 

const unsigned int pin_corect = 7777;

si tadaa, modificarea se propaga peste tot in program, acolo unde este folosita constanta pin_corect.

 

La un moment dat o sa discutam si despre directiva preprocesor "#define" care face cam acelasi lucru. Cu avantaje si dezavantaje.

 

Mai vreau sa spun un singur lucru: TYPE CASTING. O sa mai vorbim ulterior dar in mare vreau sa amintesc acum despre aceasta.

 

Spuneam anterior ca o variabila are o adresa in memorie si cand ii declaram tipul (signed int, char, unsigned long etc etc) stabilim si cati biti sunt rezervati la acea locatie (de ex pentru unsigned char va amintiti, se alocau 8biti si astfel se puteau pune in aceasta variabila valori de la 0 la 255. numai valori pozitive, nu? deoarece este unsigned ...)

 

Dar ce te faci cand incerci sa aduni doua variabile ca mai jos:

unsigned int y = 2100;unsigned char z = 33;unsigned int suma;suma = y + z;

Variabila y este tip unsigned int (deci se stocheaza pe 16bit). Variabila z este de tip unsigned char (deci se stocheaza pe 8bit). Variabila suma este tip unsigned int (deci tot pe 16bit stocata).

Cand le aduni pe y si z este ca si cum aduni mere cu pere. Ori aceasta nu se poate face dpdv logic.

 

In acest caz se pot intampla doua situatii:

1. daca lasam pur si simplu codul ca atare, compilatorul va face un casting implicit. Ce inseamna aceasta? Inseamna ca atunci cand compilatorul vede ca aduna un tip de variabila stocata pe mai putini biti (unsigned char este stocata pe 8biti) cu un tip de varibila stocata pe mai multi biti (unsigned int este stocata pe 16biti), el va "promova" variabila cu biti mai putini in tipul variabilei cu mai multi biti.

Cu alte cuvinte, compilatorul cu de la sine putere, ia decizia si il face pe unsigned char z intr-un unsigned int, muta valoarea 33 in noul spatiu de 16 biti (ca doar este unsigned int acum), aduna pe y si pe z (acum au amandoua acelasi tip si se poate face adunarea) si pune valoarea rezultata (2133) in variabila suma.

 

2. sau facem noi casting explicit, ca si programatori. Adica:

unsigned int y = 2100;unsigned char z = 33;unsigned int suma;suma = y + (unsigned int)z;

Remarcati "(unsigned int)" in fata lui z. Prin aceasta ii spunem compilatorului, ca in acest caz particular, sa trateze variabila tip unsigned char z ca pe un unsigned int. (cu consecintele de rigoare, spatiu stocare format din 16bit ...)

In mare (informativ)  cam asta este type casting-ul.

Editat de mars01
Link spre comentariu

mars01, ai spus la CONFIGURATION WORDS ca " bit 1 si bit 0 FOSC1:FOSC0 = 01 adica bit 1 = 0 iar bit 0 = 0."  DAR BIT 0 NU TREBUIA SA FIE 1 CA SA IASA CUM AI SPUS TU EGAL CU 01 ?  

 apoi "Foarte IMPORTANT. Ii spunem astfel controllerului ca am optat sa ii conectam un cuartz (adica un High Speed Oscillator) pe pinii dedicati (pinii 13 si 14)" DACA ALEGEM OSCILATOR HS, DATASHEETUL SPUNE CA TREBUIE SA-I PUNEM VALOAREA 10, DECI AR VENI BIT1=1 SI BIT0 = 0. AM INTELES BINE SAU NU?

Link spre comentariu

M-ai prins :) doua greseli una dupa alta. Daca as putea edita as edita acel paragraf dar din pacate odata scris, dupa ce trece perioada de gratie de cca 1 ora nu se mai poate edita.

 

Ma bucur ca ai prins greseala, arata ca incerci sa intelegi si depui efort personal fara ca doar sa copiezi. Bravo tie!

Editat de mars01
Link spre comentariu

Stiu ca nu am tratat aproape nimic din ce inseamna decizii in C dar iata un program care face urmatoarele:

- configuram pinul 2 al controlerului, RA0, ca si intrare digitala si conectam aici un switch la GND si un rezistor de cca 4.7K catre VDD

- configuram pinul 33 al controlerului, RB0, ca si iesire digitala si conectam aici un LED

 

Daca intrarea RA0 trece din HIGH in LOW adica switchul este apasat, se face un debouncing (voi explica maine ce este cu debouncing-ul) la buton, se aprinde LED-ul si se intra intr-o bucla de tip while(expresie) in care se va sta cca 10minute. Dupa iesirea din bucla while se stinge LED-ul si se ia de la capat programul, asteptand o apasare de switch (adica intrarea RA0 sa devina LOW).

void main() {  /*declaram o variabila numita timp, de tip unsigned int - deci poate lua valori intre 0 si 65535  Aceasta variabila va tine in ea numarul de zeci de milisecunde care va constitui perioada de temporizare.  Initializam aceasta variabila cu val 60000 care corespunde la 60000 cicluri de 10ms adica 10minute */  unsigned int timp = 6000;    /*Declaram doua constante ON si OFF ca sa ne fie mai usor de inteles programul*/  const unsigned char ON = 1;  const unsigned char OFF = 0;      /************** INITIALIZARE***************************/  CMCON = 0b00000111;  //dezactivam comparator  ADCON0 = 0;          //dezactivam ADC  CVRCON = 0;          //dezactivam referinta variabila de tensiune  TRISA = 0b00000001;  //facem INTRARE din pinul2 adica RA0; aici vom avea switch-ul conectat  TRISB = 0b00000000;  //facem IESIRE din pinul 33 adica RB0; aici vom avea LED-ul conectat  PORTB = 0b00000000;  //pornim cu LED-ul atasat pe pinul33 stins. Adica RB0 = LOW;  /**************SFARSIT INITIALIZARE********************/  /*urmeaza bucla infinita  Cat timp 1 este egal cu 1(si 1 este egal cu 1 tot timpul) executa ce este intre acolade  */  while(1 == 1) {        if (RA0_bit == 0) {   //daca intrarea este LOW      delay_ms(10);       //asteptam 10 milisecunde      if (RA0_bit == 0) { //daca intrarea inca mai este LOW atunci chiar ca avem o apasare reala de switch        RB0_bit == ON;    //aprindem LED-ul                while (timp != 0) {     //cat timp timpul este diferit de zero          //variabila timp va scadea cu o unitate pentru fiecare 100ms care trec          timp = timp - 1;      // sau se poate scrie timp--;          delay_ms(10);         //aceasta este intarzierea esentiala pentru cronometrarea timpului cat LED-ul sta aprins                  }        //timpul cat LED-ul trebuie sa stea ON a trecut si acum facem LED-ul OFF        RB0_bit == OFF;      }    }  }}

Si o varianta care difera prin faptul ca, in timp ce se sta in bucla de temporizare si se asteapta trecerea celor 10 minute, daca cumva intrarea RA0 unde este conectat switch-ul devine LOW (adica switch-ul este apasat) atunci temporizarea este resetata si se va relua asteptarea de la inceput.

void main() {  /*declaram o variabila numita timp, de tip unsigned int - deci poate lua valori intre 0 si 65535  Aceasta variabila va tine in ea numarul de zeci de milisecunde care va constitui perioada de temporizare.  Initializam aceasta variabila cu val 60000 care corespunde la 60000 cicluri de 10ms adica 10minute */  unsigned int timp = 6000;    /*Declaram doua constante ON si OFF ca sa ne fie mai usor de inteles programul*/  const unsigned char ON = 1;  const unsigned char OFF = 0;      /************** INITIALIZARE***************************/  CMCON = 0b00000111;  //dezactivam comparator  ADCON0 = 0;          //dezactivam ADC  CVRCON = 0;          //dezactivam referinta variabila de tensiune  TRISA = 0b00000001;  //facem INTRARE din pinul2 adica RA0; aici vom avea switch-ul conectat  TRISB = 0b00000000;  //facem IESIRE din pinul 33 adica RB0; aici vom avea LED-ul conectat  PORTB = 0b00000000;  //pornim cu LED-ul atasat pe pinul33 stins. Adica RB0 = LOW;  /**************SFARSIT INITIALIZARE********************/  /*urmeaza bucla infinita Cat timp 1 este egal cu 1(si 1 este egal cu 1 tot timpul) executa ce este intre acolade  */  while(1 == 1) {        if (RA0_bit == 0) {   //daca intrarea este LOW      delay_ms(10);       //asteptam 10 milisecunde      if (RA0_bit == 0) { //daca intrarea inca mai este LOW atunci chiar ca avem o apasare reala de switch        RB0_bit == ON;    //aprindem LED-ul                while (timp != 0) {     //cat timp timpul este diferit de zero          /*Urmatoarele doua conditii if(expresie) se folosesc pentru ca daca cumva in timpul de asteptare mai apasam          cumva pe buton, timpul trecut se reseteaza si temporizarea o ia de la inceput*/          if (RA0_bit == 0) {   //daca intrarea  este LOW            delay_ms(10);       //asteptam 10 milisecunde            if (RA0_bit == 0) { //daca intrarea inca mai este LOW atunci chiar ca avem o apasare reala de switch              timp =  60000;     //resetam timpul la valoarea initiala, 60000 * 10ms = 600000ms = 600sec = 10minute            }          }          //variabila timp va scadea cu o unitate pentru fiecare 100ms care trec          timp = timp - 1;      // sau se poate scrie timp--;          delay_ms(10);         //aceasta este intarzierea esentiala pentru cronometrarea timpului cat LED-ul sta aprins                  }        //timpul cat LED-ul trebuie sa stea ON a trecut si acum facem LED-ul OFF        RB0_bit == OFF;      }    }  }}

Maine discutam pe marginea programului si incerc sa explic fiecare linie a programului (apar si chestii noi cum este RB0_bit, RA0_bit, conditia if(expresie) etc).

CONFIGURATION WORDS raman la fel cum i-am explicat anterior si se configureaza la crearea proiectului.

Editat de mars01
Link spre comentariu

@core este cel cu maparea.

Poate te ajuta el dar va trebui sa dai mai multe detalii legate de context.

La modul general, maparea a ceva corespunde cu conceptul de asociere a doua sau mai multe "lucruri" si/sau crearea unei structuri ordonate.

Link spre comentariu

Intrebare:

 

Cand stingem ledul scriem RB0_bit == OFF;  dar putem scrie si PORTB=0b00000000; ???  in cazul in care nu sunt declarate variabilele?

Editat de bobinatorul
Link spre comentariu

Cand stingem ledul scriem RB0_bit == OFF;  dar putem scrie si PORTB=0b00000000; ???

== nu modifica valoarea, == e operatie de "testare".

Si da, daca scriai PORTB = 0b00000000 il faceai 0 pe RB0, dar odata cu el si pe ceilalti 7 biti ai portului. De obicei porturile au mai multi pini folositi, asa ca de obicei nu e cea mai buna idee sa modifici tot portul odata.

Link spre comentariu

@mars01_o intrebare te rog_ce inseamna ""mapare""

momentan citesc online despre C++ , termenul mapare apare si la tine

poate se lipeste ceva de mine

E vorba despre modul în care structurezi memoria. De exemplu, adresele vectorilor de întrerupere pot fi în cod (flash) sau în RAM. Cînd faci maparea sau remaparea, trebuie să ţii cont de cîtă memorie e folosită şi de către cine. Chestia asta se face manual sau automat în linker file, în funcţie de compilator.

 

Alt exemplu ar putea fi memoria paginată, fiecare pagină avînd o dimensiune oarecare.

 

Un alt exemplu e organizarea memoriei: flash, EEPROM şi RAM, toate începînd de la adresa logică 0x0000. În mod normal s-ar suprapune, dar adresele fizice sînt altele.

Posted Image

 

Intrebare:

 

Cand stingem ledul scriem RB0_bit == OFF;  dar putem scrie si PORTB=0b00000000; ???  in cazul in care nu sunt declarate variabilele?

Se poate masca folosind PORTB astfel:

// Ştergerea bituluiPORTB &= ~0x01;// Setarea bituluiPORTB |= 0x01;// Verificare bit setatif ((PORTB & 0x01) == 0x01)// Verificare bit ştersif ((PORTB & 0x01) == 0x00)// Metode mai elegante de a seta, şterge şi verifica un bit#define TRUE   1#define FALSE  0#define SET_BIT(var, b)      var |= (1 << b)#define CLR_BIT(var, b)      var &= ~(1 << b)#define IS_BIT_CLR(var, b)   (var & (1 << b))?FALSE:TRUE#define IS_BIT_SET(var, b)   (var & (1 << b))?TRUE:FALSE
Link spre comentariu

 

dar aceasta reprezinta "mascarea"bitilor?

 

Mascarea bitilor inseamna modificarea anumitor biti intr-un grup (octet, word...), cu pastrarea celorlalti nemodificati (prin folosirea unor operatii speciale si masti potrivite).

La operatiile de mascare se folosesc operatiile logice pe biti (bitwise, prin cartile in engleza). Nu stiu sigur daca astea-s toate, dar eu cel mai des am folosit AND (SI, &), OR (SAU, |), NOT (negare, ~), XOR (^).

AND se foloseste cand vrem sa facem bitii 0 (X AND 0 = 0, X AND 1 = X), OR cand vrem sa facem bitii 1 ( X OR 1 = 1, X OR 0 = X), NOT cand vrem sa negam toti bitii (~0000 = ~1111), XOR cand vrem sa negam anumiti biti (X XOR 1 = !X, X XOR 0 = X).

Exemple. Considerand X = 0b11001100, ca sa obtinem:

- 0b11000000 facem AND cu masca 0b11110011 (1 unde nu vrem sa modificam, 0 unde vrem) => 0b11001100 & 0x11110011 = 0b11000000

- 0b11001111 facem OR cu masca 0b00000011 (0 unde nu vrem sa modificam, 1 unde vrem)

- 0b00110011 facem NOT X

- o iesire (sa zicem bitul 3) care sa-si modifice starea intr-o bucla, la fiecare trecere prin bucla - folosim XOR cu masca 0x00001000.

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