Sari la conținut
ELFORUM - Forumul electronistilor

Exercitii programare de la zero


Vizitator ciocanaru

Postări Recomandate

Cateva completari:

- Foarte buna initiativa. Asa trebuie invatat !

Mai este un topic aici "Programare de la 0" cu foarte multe pagini. Acolo as fi vrut sa scriu partea asta, dar e foarte incarcat.

Am vazut pe acel topic ca se vrea mai intai aprofundarea teoriei cat mai complet si apoi practica ceea ce zic eu e gresit ar trebui sa meraga simultan ambele.

 

Pentru ca incepatorul toceste ce este un registru, nu prea intelege ce este, afla apoi cum e configurat, nu stie cat de importa este, dar memoreaza, iar la practica nu reuseste sa faca conexiuni intre ele.

 

Sa nu fiu inteles gresit - imi pace mult teoria, dar cea facuta bine......

 

- Sfatul pe care il dau aici este urmatorul:

 Este mult mai greu sa intelegi programul facut de altul. Este mult mai simplu sa faci propriul tau program.

 

Deci ca incepator iei exemplele de aici, lasi programele facute de altii, faci propriul tau program si dupa ce ai terminat si functioneaza, le compari, vezi si cum au facut altii.

 

Este atat de multa informatie incat chiar nu merita sa me incarcam memoria cu ea.  E un mare avantaj sa mai schematizezi sintetizezi informatia asta.

Editat de Mondan
Link spre comentariu
  • 4 săptămâni mai târziu...

salutare ,

ma chinui de cateva zile sa fac un program in care am 4 intrari (butoane) si 6 iesiri9 ceea ce vreau eu sa faca mC:

1. sa scaneze incontinu intrarile

2. in momentu cand un buton este apasat sa execute un program (ex.out 1 & out 3 = on ,la a doua apasare

 out 1&out3=off),butoanele sa aiba comenzi independente 

apasat sa pastrze comanda anterioara si sa o execute pe urmatoarea

3.microcomtroleru este din seria 16f627 sau 16f84.

Eu am testat programu de mai jos cu doua butoane  fara functia de off prima comanda merge(aprinde ledurile rb2;rb3) dar pentru aprinderea

rb4 tine cont si de apasarea butonului ra0(trebuie apasat simultan ra0+ra2 si eliberat ra0 inaintea ra2 ca rb4 sa se aprinda)

SI marea problema este ca aici m-am blocat nu stiu ce comanda sa ii mai dau.

const unsigned char ON = 1;
  const unsigned char OFF = 0;
void prog1(){
     RB2_bit = on ;
         RB3_bit = on  ;
   }
void prog2 (){
      RB4_bit = on ;
    }
 
void main () {
 
 
 
  /************** INITIALIZARE***************************/
 
  TRISA = 0b00000111;  //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********************/
 
 
 
 
     
 
 
 
 
     while(1) {
 
    if (RA0_bit == 1) {
 
           prog1 ();
 
       if (RA2_bit == 1) {
        delay_ms(1);
          prog2();
 
       }
       
 
 
      }
     }
 
}
Link spre comentariu

Pe topicul http://www.elforum.info/topic/111858-invatat-programare-de-la-zero/ a fost postat urmatorul program, intrebarea fiind de ce nu functioneaza corect.

const unsigned char ON = 1;const unsigned char OFF = 0;void prog1(){     RB2_bit = on ;     RB3_bit = on  ;}void prog2 (){     RB4_bit = on ;} void main () {  /************** INITIALIZARE***************************/   TRISA = 0b00000111;  //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********************/  while(1) {     if (RA0_bit == 1) {       prog1 ();       if (RA2_bit == 1) {         delay_ms(1);         prog2();       }    }  } }

Eu am testat programu de mai jos cu doua butoane  fara functia de off prima comanda merge(aprinde ledurile rb2;rb3) dar pentru aprinderea

rb4 tine cont si de apasarea butonului ra0(trebuie apasat simultan ra0+ra2 si eliberat ra0 inaintea ra2 ca rb4 sa se aprinda)

SI marea problema este ca aici m-am blocat nu stiu ce comanda sa ii mai dau.

 

Acest fenomen apare deoarece :

if (RA0_bit == 1) {       prog1 ();       if (RA2_bit == 1) {         delay_ms(1);         prog2();       }    }

dupa cum se vede al 2 lea if este conditionat de faptul ca primul if sa fie adevarat. Cu alte cuvinte doar dupa ce RA0 este apasat, se testeaza daca RA2 este apasat. Daca se inchidea acolada primului if imediat dupa 

prog1();

atunci ar fi mers cum doreai. Adica asa:

if (RA0_bit == 1) {     prog1 ();}       if (RA2_bit == 1) {    delay_ms(1);    prog2();}

Dar cred ca apareau probleme de debouncing (oscilatii elastice ale lamelelor switch-urilor la actionarea acestora. Aceasta se rezolva ca mai jos.

 

 

Presupun ca se doreste folosirea unor intrerupatoare mecanice (intre intrare si GND) iar pe intrari se vor conecta rezistori de pull-up catre VCC. Astfel, cand intrerupatorul este apasat intrarea va avea nivel LOW iar in starea default intrarea va avea nivel HIGH.

 

Presupun ca a fost efectuata configurarea corecta a registrilor CONFIG deci a oscilatorului, watchdog etc.

Programul ar fi asa:

// controller folosit 16F627const unsigned char ON = 1;const unsigned char OFF = 0;void prog1(){     RB2_bit = !RB2_bit;   // schimba starea pin RB2 in starea opusa celei anterioare     RB3_bit = !RB3_bit;   // schimba starea pin RB3 in starea opusa celei anterioare}void prog2(){     RB4_bit = !RB4_bit;   // schimba starea pin RB4 in starea opusa celei anterioare}void main () {  /************** INITIALIZARE***************************/  CMCON = 7;           // comparatoare OFF  VREN_bit = 0;        // dezactivare voltage reg    //TRISA = 0b00000111;  //facem INTRARE din pinul2 adica RA0; aici vom avea switch-ul conectat  TRISA0_bit = 1;       // RA0 este INTRARE  TRISA2_bit = 1;       // RA2 este INTRARE    TRISB = 0b00000000;   //facem PORTB numai IESIRI  PORTB = 0b00000000;   //pornim cu PORTB in stare LOW    /**************SFARSIT INITIALIZARE********************/  while(1) {    if (RA0_bit == 0) { // daca intrerupator RA0 este apasat deci LOW atunci      delay_ms(10);      if (RA0_bit == 0) { // daca dupa 10ms intrerupator RA0 este in continuare apasat atunci chiar avem o apsarare reala        prog1();  // si atunci execut functia prog1()      }    }        if (RA2_bit == 0) { // daca intrerupator RA2 este apasat deci LOW atunci      delay_ms(10);      if (RA2_bit == 0) { // daca dupa 10ms intrerupator RA2 este in continuare apasat atunci chiar avem o apsarare reala        prog2();  // si atunci execut functia prog2()      }    }  }}

LE: Data viitoare foloseste si tu butonul CODE din menu (cand scrii mesajul) arata asa: <>

Si incearca sa respecti regulile de indentare ca uite cat de usor te poti incurca in if-uri.

Editat de mars01
Link spre comentariu
Vizitator vezi_muti

 nu merge si asa? nu stiu ce returneaza delay. poate trebuie !delay

if (!RA0_bit && delay_ms(10) && !RA0_bit) prog1();
Editat de vezi_muti
Link spre comentariu

eu as mai recomanda o bucatica de cod, mai ales ca functia se executa foarte repede si este posibilitatea ca iesirea sa comute de cateva ori daca se apara butoanul mai masnegeste.  :rade:

in programul initial acest efect nu se vedea, pentru ca nu se comutau iesirile, doar se facea o stare stabila, probabil de mai multe ori.

...    if (RA0_bit == 0) { // daca intrerupator RA0 este apasat deci LOW atunci      delay_ms(10);      if (RA0_bit == 0) { // daca dupa 10ms intrerupator RA0 este in continuare apasat atunci chiar avem o apsarare reala        prog1();  // si atunci execut functia prog1()        while ( 0 == RA0_bit )          continue;    //asteapta eliberarea butonului apasat      }    }...
Link spre comentariu

@core foarte buna contributia. Nu exista doar posibiliatea ci chiar asa si este. In mod normal eu as fi folosit o variabila cu last_time etc ... dar nu m-am focalizat pe solutie ci pe problema.

Solutia oferita de tine este insa ceva inedit :) Omul cat traieste invata, multumesc pentru imbunatatire!

LE: nu mergea si adaugand pur si simplu:

while (RA0_bit == 0);

?

Editat de mars01
Link spre comentariu

Programul corect, cu debouncing pentru switch-uri cat si cu apasari ferme, practic iesirilor se schimba doar la trecerea din INACTIV in ACTIV (adica din HIGH in LOW):

const unsigned char ON = 1;const unsigned char OFF = 0;// variabile care tin minte starea anterioara a intrarilorunsigned short last_RA0 = 1;unsigned short last_RA2 = 1;void prog1(){     RB2_bit = !RB2_bit;   // schimba starea pin RB2 in starea opusa celei anterioare     RB3_bit = !RB3_bit;   // schimba starea pin RB3 in starea opusa celei anterioare}void prog2(){     RB4_bit = !RB4_bit;   // schimba starea pin RB4 in starea opusa celei anterioare}void main () {  /************** INITIALIZARE***************************/  CMCON = 7;           // comparatoare OFF  VREN_bit = 0;        // dezactivare voltage reg    //TRISA = 0b00000111;  //facem INTRARE din pinul2 adica RA0; aici vom avea switch-ul conectat  TRISA0_bit = 1;       // RA0 este INTRARE  TRISA2_bit = 1;       // RA2 este INTRARE    TRISB = 0b00000000;   //facem PORTB numai IESIRI  PORTB = 0b00000000;   //pornim cu PORTB in stare LOW    /**************SFARSIT INITIALIZARE********************/  while(1) {    if (RA0_bit == 1) last_RA0 = 1;    if (RA0_bit == 0 && last_RA0 == 1) { // daca intrerupator RA0 este apasat, deci LOW, si data trecuta a fost HIGH atunci      delay_ms(10);      if (RA0_bit == 0) { // daca dupa 10ms intrerupator RA0 este in continuare apasat atunci chiar avem o apsarare reala        prog1();  // si atunci execut functia prog1()      }      last_RA0 = 0;    }        if (RA2_bit == 1) last_RA2 = 1;        if (RA2_bit == 0 && last_RA2 == 1) { // daca intrerupator RA2 este apasat, deci LOW, si data trecuta a fost HIGH atunci      delay_ms(10);      if (RA2_bit == 0) { // daca dupa 10ms intrerupator RA2 este in continuare apasat atunci chiar avem o apsarare reala        prog2();  // si atunci execut functia prog2()      }      last_RA2 = 0;    }  }}
Link spre comentariu

Am pierdut doua zile ca sa scriu o banalitate de program si ca sa n-o pierd si pe a treia va cer ajutorul . 

 

Asadar vreau sa fac un sistem de iluminare "in cascada" : adica avem un intrerupator cu revenire si vreo 17 becuri ; in momentul in care se apasa butonul becurile incep sa se aprinda , pe rand , la interval de o secunda unul fata de celalalt ; dupa ce s-au aprins toate becurile si se actioneaza din  nou intrerupatorul ,becurile se sting in acelasi fel dar in ordine inversa .

 

Am de gand sa folosesc un PIC 16F74 care sa comande prin intermediul unor tranzistori 17 relee corespunzatoare celor 17 becuri ; problema e ca nu reusesc sa scriu un cod functional . 

 

Am incercat cu acest cod si cateva variante modificate ale lui ; niciuna n-a mers . Ledurile ori nu se aprind deloc ori se aprind si raman aprinse ori intra intr-o bucla infinita si se tot aprind si sting .

 void main() {  /*Declaram doua constante ON si OFF */  const unsigned char ON = 1;  const unsigned char OFF = 0;  /************** INITIALIZARE***************************/  ADCON0 = ADCON1 = 0;          //dezactivam ADC  TRISA = 0b00000001;  //facem INTRARE din pinul 2 adica RA0; aici vom avea switch-ul conectat  TRISB = 0b00000000;  //facem portul B B0-B7 ,iesire  TRISC = 0b00011111;  //RC 5-7 setati ca iesiri  TRISD = 0b00000011;  //RD 2-7 setati ca iesiri  PORTB = 0b00000000;  //pornim cu becurile de pe PORTB stinse  PORTC = 0b00000000;  //pornim cu becurile de pe PORTC stinse  PORTD = 0b00000000;  //pornim cu becurile de pe PORTD stinse  /**************SFARSIT INITIALIZARE********************/  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        RD2_bit = ON;    //aprindem becul        delay_ms(1000);  // intarziere de o secunda        RD3_bit = ON;        delay_ms(1000);        RC5_bit = ON;        delay_ms(1000);        RC6_bit = ON;        delay_ms(1000);        RC7_bit = ON;        delay_ms(1000);        RD4_bit = ON;        delay_ms(1000);        RD5_bit = ON;        delay_ms(1000);        RD6_bit = ON;        delay_ms(1000);        RD7_bit = ON;        delay_ms(1000);        RB0_bit = ON;        delay_ms(1000);        RB1_bit = ON;        delay_ms(1000);        RB2_bit = ON;        delay_ms(1000);        RB3_bit = ON;        delay_ms(1000);        RB4_bit = ON;        delay_ms(1000);        RB5_bit = ON;        delay_ms(1000);        RB6_bit = ON;        delay_ms(1000);        RB7_bit = ON;        delay_ms(1000);         }        }    if (RA0_bit == 0) {        delay_ms(10);     if (RA0_bit == 0) {        RD2_bit = OFF;    //Stingem becul        delay_ms(1000);  // intarziere de o secunda        RD3_bit = OFF;        delay_ms(1000);        RC5_bit = OFF;        delay_ms(1000);        RC6_bit = OFF;        delay_ms(1000);        RC7_bit = OFF;        delay_ms(1000);        RD4_bit = OFF;        delay_ms(1000);        RD5_bit = OFF;        delay_ms(1000);        RD6_bit = OFF;        delay_ms(1000);        RD7_bit = OFF;        delay_ms(1000);        RB0_bit = OFF;        delay_ms(1000);        RB1_bit = OFF;        delay_ms(1000);        RB2_bit = OFF;        delay_ms(1000);        RB3_bit = OFF;        delay_ms(1000);        RB4_bit = OFF;        delay_ms(1000);        RB5_bit = OFF;        delay_ms(1000);        RB6_bit = OFF;        delay_ms(1000);        RB7_bit = OFF;        delay_ms(1000);     }    }   }  } }
Editat de iuli09
Link spre comentariu

Iti mai trebuie o variabila care sa memoreze starea becurilor - aprinse sau stinse. O folosesti intr-un if dupa debouncing:

- if RA0 = 0- debouncing- RA0 tot 0- if(luminaStinsa)aprinde 11 secaprinde 21 sec...else //adica lumina aprinsastinge 11 secstinge 2...
Link spre comentariu

ADCON1 ar trebui sa fie 7, adica:

ADCON1 = 7;

LLE: sau mai corect spus ADCON1 poate avea valoarea: 4 sau 5 sau 6 sau 7. Toate aceste valori ne asigura ca RA2 este un I/O digital.

 

Posted Image

 

LE:

 

In acest caz pentru a fi usor de citit programul. as grupa codul de aprins lumini si cel de stins lumini in cate o functie.

Tinand cont de sugestia lui Liviu, as face programul asa:

#define ON    1#define OFF   0void lights_on() {  RD2_bit = ON;    //aprindem becul  delay_ms(1000);  // intarziere de o secunda  RD3_bit = ON;  delay_ms(1000);  RC5_bit = ON;  delay_ms(1000);  RC6_bit = ON;  delay_ms(1000);  RC7_bit = ON;  delay_ms(1000);  RD4_bit = ON;  delay_ms(1000);  RD5_bit = ON;  delay_ms(1000);  RD6_bit = ON;  delay_ms(1000);  RD7_bit = ON;  delay_ms(1000);  RB0_bit = ON;  delay_ms(1000);  RB1_bit = ON;  delay_ms(1000);  RB2_bit = ON;  delay_ms(1000);  RB3_bit = ON;  delay_ms(1000);  RB4_bit = ON;  delay_ms(1000);  RB5_bit = ON;  delay_ms(1000);  RB6_bit = ON;  delay_ms(1000);  RB7_bit = ON;  delay_ms(1000);}void lights_off() {  RD2_bit = OFF;    //Stingem becul  delay_ms(1000);  // intarziere de o secunda  RD3_bit = OFF;  delay_ms(1000);  RC5_bit = OFF;  delay_ms(1000);  RC6_bit = OFF;  delay_ms(1000);  RC7_bit = OFF;  delay_ms(1000);  RD4_bit = OFF;  delay_ms(1000);  RD5_bit = OFF;  delay_ms(1000);  RD6_bit = OFF;  delay_ms(1000);  RD7_bit = OFF;  delay_ms(1000);  RB0_bit = OFF;  delay_ms(1000);  RB1_bit = OFF;  delay_ms(1000);  RB2_bit = OFF;  delay_ms(1000);  RB3_bit = OFF;  delay_ms(1000);  RB4_bit = OFF;  delay_ms(1000);  RB5_bit = OFF;  delay_ms(1000);  RB6_bit = OFF;  delay_ms(1000);  RB7_bit = OFF;  delay_ms(1000);}void main() {  unsigned char stare_lumini = OFF; // variabila care tine minte starea curenta a luminilor    /************** INITIALIZARE***************************/  ADCON0 = 0;          //dezactivam ADC  ADCON1 = 7;          //port A and E pins are digital I/O    TRISA = 0b00000001;  //facem INTRARE din pinul 2 adica RA0; aici vom avea switch-ul conectat  TRISB = 0b00000000;  //facem portul B B0-B7 ,iesire  TRISC = 0b00011111;  //RC 5-7 setati ca iesiri  TRISD = 0b00000011;  //RD 2-7 setati ca iesiri    PORTB = 0b00000000;  //pornim cu becurile de pe PORTB stinse  PORTC = 0b00000000;  //pornim cu becurile de pe PORTC stinse  PORTD = 0b00000000;  //pornim cu becurile de pe PORTD stinse  /**************SFARSIT INITIALIZARE********************/  while(1) {    if (RA0_bit == 0 && stare_lumini == OFF) {   //daca intrarea este LOW si luminile sunt oprite      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        lights_on();        stare_lumini = ON;      }    }    if (RA0_bit == 0 && stare_lumini == ON) {   //daca intrarea este LOW si luminile sunt pornite        delay_ms(10);      if (RA0_bit == 0) {        lights_on();        stare_lumini = OFF;      }    }  }}

sau mai corect (in caz ca butonul de pe intrarea RA2 ramane blocat in stare apasat, mai mult de 17 secunde):

#define ON  1#define OFF 0void lights_on() {  RD2_bit = ON;    //aprindem becul  delay_ms(1000);  // intarziere de o secunda  RD3_bit = ON;  delay_ms(1000);  RC5_bit = ON;  delay_ms(1000);  RC6_bit = ON;  delay_ms(1000);  RC7_bit = ON;  delay_ms(1000);  RD4_bit = ON;  delay_ms(1000);  RD5_bit = ON;  delay_ms(1000);  RD6_bit = ON;  delay_ms(1000);  RD7_bit = ON;  delay_ms(1000);  RB0_bit = ON;  delay_ms(1000);  RB1_bit = ON;  delay_ms(1000);  RB2_bit = ON;  delay_ms(1000);  RB3_bit = ON;  delay_ms(1000);  RB4_bit = ON;  delay_ms(1000);  RB5_bit = ON;  delay_ms(1000);  RB6_bit = ON;  delay_ms(1000);  RB7_bit = ON;  delay_ms(1000);}void lights_off() {  RD2_bit = OFF;    //Stingem becul  delay_ms(1000);  // intarziere de o secunda  RD3_bit = OFF;  delay_ms(1000);  RC5_bit = OFF;  delay_ms(1000);  RC6_bit = OFF;  delay_ms(1000);  RC7_bit = OFF;  delay_ms(1000);  RD4_bit = OFF;  delay_ms(1000);  RD5_bit = OFF;  delay_ms(1000);  RD6_bit = OFF;  delay_ms(1000);  RD7_bit = OFF;  delay_ms(1000);  RB0_bit = OFF;  delay_ms(1000);  RB1_bit = OFF;  delay_ms(1000);  RB2_bit = OFF;  delay_ms(1000);  RB3_bit = OFF;  delay_ms(1000);  RB4_bit = OFF;  delay_ms(1000);  RB5_bit = OFF;  delay_ms(1000);  RB6_bit = OFF;  delay_ms(1000);  RB7_bit = OFF;  delay_ms(1000);}void main() {  unsigned char stare_lumini = OFF; // variabila care tine minte starea curenta a luminilor  unsigned char last_RA0 = 1;       // variabila care tine minte starea anterioara a butonului    /************** INITIALIZARE***************************/  ADCON0 = 0;          //dezactivam ADC  ADCON1 = 7;          //port A and E pins are digital I/O    TRISA = 0b00000001;  //facem INTRARE din pinul 2 adica RA0; aici vom avea switch-ul conectat  TRISB = 0b00000000;  //facem portul B B0-B7 ,iesire  TRISC = 0b00011111;  //RC 5-7 setati ca iesiri  TRISD = 0b00000011;  //RD 2-7 setati ca iesiri    PORTB = 0b00000000;  //pornim cu becurile de pe PORTB stinse  PORTC = 0b00000000;  //pornim cu becurile de pe PORTC stinse  PORTD = 0b00000000;  //pornim cu becurile de pe PORTD stinse  /**************SFARSIT INITIALIZARE********************/  while(1) {      if (RA0_bit == 1) last_RA0 == 1;        if (RA0_bit == 0 && last_RA0 == 1) {   //daca intrarea este LOW si anaterior intrarea a fost HIGH      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        if (stare_lumini == OFF) {          lights_on();          stare_lumini = ON;        }        else {          lights_off();          stare_lumini = OFF;        }      }      last_RA0 = 0;    }  }}
Editat de mars01
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