Mondan Postat Mai 16, 2016 Partajează Postat Mai 16, 2016 (editat) 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 Mai 16, 2016 de Mondan Link spre comentariu
laur234 Postat Iunie 11, 2016 Partajează Postat Iunie 11, 2016 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
mars01 Postat Iunie 11, 2016 Partajează Postat Iunie 11, 2016 (editat) 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 Iunie 11, 2016 de mars01 Link spre comentariu
Vizitator vezi_muti Postat Iunie 11, 2016 Partajează Postat Iunie 11, 2016 (editat) nu merge si asa? nu stiu ce returneaza delay. poate trebuie !delay if (!RA0_bit && delay_ms(10) && !RA0_bit) prog1(); Editat Iunie 11, 2016 de vezi_muti Link spre comentariu
core Postat Iunie 11, 2016 Partajează Postat Iunie 11, 2016 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. 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
mars01 Postat Iunie 11, 2016 Partajează Postat Iunie 11, 2016 (editat) @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 Iunie 11, 2016 de mars01 Link spre comentariu
laur234 Postat Iunie 11, 2016 Partajează Postat Iunie 11, 2016 multumesc mars01 modificarea pe care mi-ai sugerato mai sus merge foarte bine am modificat programu dupa cum ai zis tu si functioeaza. Deci trebuie tinut cont de fiecare acolada Link spre comentariu
mars01 Postat Iunie 11, 2016 Partajează Postat Iunie 11, 2016 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
iuli09 Postat Iunie 13, 2016 Partajează Postat Iunie 13, 2016 (editat) 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 Iunie 13, 2016 de iuli09 Link spre comentariu
Liviu M Postat Iunie 13, 2016 Partajează Postat Iunie 13, 2016 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
Liviu M Postat Iunie 13, 2016 Partajează Postat Iunie 13, 2016 (editat) Nu mai pot sa editez, dar cred ca e clar ca valoarea variabilei luminaStinsa va trebui actualizata de fiecare data la aprindere/stingere. Editat Iunie 13, 2016 de Liviu M Link spre comentariu
iuli09 Postat Iunie 13, 2016 Partajează Postat Iunie 13, 2016 (editat) Ok , am inteles ideea ,o sa vad daca ma descurc s-o implementez ; o sa revin cu o varianta modificata . Multumesc ! Editat Iunie 13, 2016 de iuli09 Link spre comentariu
mars01 Postat Iunie 13, 2016 Partajează Postat Iunie 13, 2016 (editat) 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. 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 Iunie 13, 2016 de mars01 Link spre comentariu
iuli09 Postat Iunie 13, 2016 Partajează Postat Iunie 13, 2016 gresesc eu sau ati uitat sa implementati protectia in caz ca ramane cuplat butonul mai mult de 17 secunde despre care ati pomenit? Link spre comentariu
Liviu M Postat Iunie 13, 2016 Partajează Postat Iunie 13, 2016 E prima propozitie dupa while(1). Link spre comentariu
Postări Recomandate
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 contAutentificare
Ai deja un cont? Autentifică-te aici.
Autentifică-te acum