adyyo Postat Mai 18, 2012 Autor Partajează Postat Mai 18, 2012 Am vazut si eu ca am 3,6 V la bornele MCU-ului si la iesisea pentru alimentare monaje externe. Oricum, am izolat matricea fata de MCU si pe anozi si pe catozi. Sper sa am timp diseara sa plantez 4017-le pentru comanda catozilor si sa fac si un test. Revin cu o poza si eventual un programel. Link spre comentariu
Vizitator Postat Mai 18, 2012 Partajează Postat Mai 18, 2012 am izolat matricea fata de MCU si pe anozi si pe catozi Pune o poză cu schema că nu se înţelege cum vrei să faci. Deseneaz-o de mână, ca să nu pierzi timp cu editarea pe calculator, dar să fie cât mai completă.Dacă ai nevoie de +5V pentru montajul cu LED-uri, poţi să îi iei tot din LauncPad.Chiar lângă mufa USB, este pe placă un testpoint numit TP1. Acolo ai +5V din USB. Standardul USB suportă două regimuri de curent, maxim 100mA sau maxim 500mA. Dacă iei +5V din USB, atunci încearcă să te încadrezi cu consumul în maxim 100mA. Sub niciun fel să nu depăşeşti 500 mA.Eu am lipit la TP1 un conector de tip mamă, şi am pus pe el varniş termocontractor (heat-shrink tube) ca să nu fac vreun scurt din greşeală. Conectorul este de fapt un pin de la un soclu Augat, pentru circuite integrate obişnuite, de tip DIL. Când am nevoie de +5V pentru montaje, înfig un fir în conector. Pentru fir, se potriveşte perfect sârma din care e făcut cablul UTP CAT5 (cablu de reţea de calculatoare). Tot sârmă de cablu UTP folosesc şi la realizarea legăturilor pe breadboard-urile solderless (plăcile alea de plastic, cu găurele, în care înfigi piesele şi sârmele în loc să le lipeşti). Link spre comentariu
adyyo Postat Mai 18, 2012 Autor Partajează Postat Mai 18, 2012 Pai in principiu am facut ca in schema. Nu luati in calcul numerotarea pinilor la MCU deoarece nu am gasit in biblioteca M430 si am folosit alt MCU la care am schimbat doar numele porturilor ca sa exemplific la ce porturi vreau sa leg eu matricea.L.E. Si la 4017, am desenat gresit pinii pe care i-am legat la MCU. Trebuia legat CLK si RESET, nu CLC si ENA ca in desen. Matrice LED.pdf Link spre comentariu
adyyo Postat Mai 19, 2012 Autor Partajează Postat Mai 19, 2012 Intrebare...Biti de la 0 la 7 din portul 1 ii accesez cu BIT0 pana la BIT7; dar bitii din portul 2? Is cumva in continuare numerotati adica P2.0 este BIT8 s.a.m.d. pana la portul P2.5 care este BIT D ? Link spre comentariu
Vizitator Postat Mai 19, 2012 Partajează Postat Mai 19, 2012 Foloseşti P2DIR, P2REN şi P2OUT cu aceleaşi măşti, de la BIT0 la BIT7. Link spre comentariu
adyyo Postat Mai 20, 2012 Autor Partajează Postat Mai 20, 2012 Bun folosesc P2DIR si P2OUT, dar cum declar biti, pentru ca de exemplu, pe portul unu am #define LED1 BIT0 iar pe portul doi vreau ca la BIT0 sa am alt LED, de exemplu LED7? Montajul l-am realizat ca in figura, i-am facut test fara a-l conecta la MCU si funtioneaza bine, singura problema e ca integratul 4017 este foarte sensibil si la un impuls, pentru ca era dat cu un buton, facea mai multi pasi decat 1, cat trebuia. Oricum, dupa ce l-am conectat la MCU nu mai are problema asta si functioneaza foarte bine cu un LED si un smenal de clik pentru a schimba intre cele 5 coloane. Mai departe am vrut sa aprind pe rand cate un LED si sa schimb coloanele, dar am dat de urmatoarea problema: cand rulez programul, mi se aprind toate LED-urile simultan si isi schimba coloana, in loc sa se aprinda doar LED1 #include "msp430g2553.h"#define LED1 BIT0 //LED-ul 1 al fiecarei coloane#define LED2 BIT4 //LED-ul 2 al fiecarei coloane#define LED3 BIT5 //LED-ul 3 al fiecarei coloane#define LED4 BIT7 //LED-ul 5 al fiecarei coloane#define CLK BIT6 //step pentru a schimba coloanavoid main(void){ WDTCTL = WDTPW + WDTHOLD; //opreste timerul watchdg P1DIR = LED1 | LED2 | LED3 | LED4 | CLK; //setez bitii 0, 4, 5, 6 si 7 ca iesiri while(1) { P1OUT |= LED1;//aprinde LED1 _delay_cycles(200000); P1OUT |= CLK; //schimba coloana P1OUT &= ~CLK; }} Link spre comentariu
adyyo Postat Iunie 1, 2012 Autor Partajează Postat Iunie 1, 2012 In cele din urma i-am dat de cap. Nu era problema de programare ci un circuit defect. Am facut un mic programel care deseneaza un romb #include "msp430g2553.h"#define LED1 BIT6 //LED-ul 1#define LED2 BIT0 //LED-ul 2#define LED3 BIT4 //LED-ul 3#define LED4 BIT3 //LED-ul 4#define LED5 BIT2 //LED-ul 5#define LED6 BIT1 //LED-ul 6#define RST BIT7 //RESET counter#define CLK BIT5 //step pentru a schimba coloanavoid main(void){ WDTCTL = WDTPW + WDTHOLD; //opreste timerul watchdg P1DIR = LED1 | LED2 | LED3 | LED4 | LED5 | LED6 | RST | CLK; //setez bitii 0, 5, 6 ca iesiriwhile(1) { P1OUT |= RST; //resetez coloanele P1OUT &= ~RST; P1OUT |= LED3 | LED4; //aprinde LED3 si LED4 _delay_cycles(150000); P1OUT &= ~LED3; //stinge LED3 P1OUT &= ~LED4; //stinge LED4 P1OUT |= CLK; //schimba coloana P1OUT &= ~CLK; P1OUT |= LED5 | LED2; //aprinde LED5 si LED2 _delay_cycles(150000); P1OUT &= ~LED5; //stinge LED5 P1OUT &= ~LED2; //stinge LED2 P1OUT |= CLK; //schimba coloana P1OUT &= ~CLK; P1OUT |= LED6 | LED1; //aprinde LED6 si LED1 _delay_cycles(150000); P1OUT &= ~LED6; //stinge LED6 P1OUT &= ~LED1; //stinge LED1 P1OUT |= CLK; //schimba coloana P1OUT &= ~CLK; P1OUT |= LED5 | LED2; //aprinde LED5 si LED2 _delay_cycles(150000); P1OUT &= ~LED5; //stinge LED5 P1OUT &= ~LED2; //stinge LED2 P1OUT |= CLK; //schimba coloana P1OUT &= ~CLK; P1OUT |= LED3 | LED4; //aprinde LED3 si LED4 _delay_cycles(150000); P1OUT &= ~LED3; //stinge LED3 P1OUT &= ~LED4; //stinge LED4 }} Bon...sunt bucuros ca am reusit, dar tot nu pot sa folosesc pinii P2.0, P2.1, P2.2. De exemplu eu am incercat asa: #include "msp430g2553.h"#define LED1 BIT6#define LED2 BIT0#define LED3 BIT0void main(void){ WDTCTL = WDTPW + WDTHOLD; //opreste timerul watchdg P1DIR = LED1 | LED3; P2DIR = LED2; P1OUT |= LED1; _delay_cycles(200000); P2OUT |= LED2; _delay_cycles(200000); P1OUT |= LED3;}Dar nu merge. Se aprinde LED-ul1, apoi LED-ul 2, si atat. Link spre comentariu
adyyo Postat Iunie 4, 2012 Autor Partajează Postat Iunie 4, 2012 Pana la urma am reusit sa ii dau de cap, si mi-am scris numele. Voi posta un flmulet cu realizarea. Incerc mai departe sa derulez textul, dar cred ca trebuie sa fac altfel montajul. L.E. https://picasaweb.google.com/1001569190 ... 6008653010 Link spre comentariu
Vizitator Postat Iunie 4, 2012 Partajează Postat Iunie 4, 2012 Foarte bine că i-ai dat de cap, de ce nu mergea P2? Ca să faci derularea mai simplu, scoate jumper-ii (punţile) TxD şi RxD, şi leagă la montaj biţii din P1 la rând, nu pe sărite. Pe urmă poţi implementa derularea literelor facând deplasări de biţi la stânga sau la dreapta, cu ajutorul operatorilor "<<" sau ">>". Am văzut filmuleţul, felicitări! Link spre comentariu
adyyo Postat Iunie 4, 2012 Autor Partajează Postat Iunie 4, 2012 Multumesc:D Nu mergea P2 ca ma incurcasem eu in conectarea firelor . Deocamdata m-am hotarat sa imi mut montajul pe o placa de cabalaj si sa il fac sa arate inginereste si sa nu mai incurc conexiunile Nu stiu sigur daca va merge cu schimbarea bitilor deoarece am scris programul in sil propriu // ---------scris ADRIAN fara derulare---------//#include "msp430g2553.h"#define LED1 BIT0 //LED-ul 1#define LED2 BIT1 //LED-ul 2#define LED3 BIT2 //LED-ul 3#define LED4 BIT3 //LED-ul 4#define LED5 BIT4 //LED-ul 5#define LED6 BIT5 //LED-ul 6#define LED7 BIT6 //LED-ul 7#define LED8 BIT7 //LED-ul 8#define RST BIT4 //RESET counter#define CLK BIT5 //step pentru a schimba coloanaint i;int function;void SCHCOL (){ P1OUT |= CLK; //schimba coloana P1OUT &= ~CLK;}void literaA (){ P1OUT |= RST; //resetez coloanele P1OUT &= ~RST; P2OUT |= LED4 | LED5; //aprinde LED4 si LED5 _delay_cycles(2000); P2OUT &= ~(LED4 | LED5); //stinge LED4 si LED5 SCHCOL (); P2OUT |= LED3 | LED6; //aprinde LED3 si LED6 _delay_cycles(2000); P2OUT &= ~(LED3 | LED6); //stinge LED3 si LED6 SCHCOL (); P2OUT |= LED3 | LED4 | LED5 |LED6; //aprinde LED3, LED4, LED5, LED6 _delay_cycles(2000); P2OUT &= ~(LED3 | LED4 | LED5 | LED6); //stinge LED3, LED4, LED5, LED6 SCHCOL (); P2OUT |= LED3 | LED6; //aprinde LED3 si LED6 _delay_cycles(2000); P2OUT &= ~(LED3 | LED6); //stinge LED3 si LED6 SCHCOL (); P2OUT |= LED3 | LED6; //aprinde LED3 si LED6 _delay_cycles(2000); P2OUT &= ~(LED3 | LED6); //stinge LED3 si LED6}void literaD (){ P1OUT |= RST; //resetez coloanele P1OUT &= ~RST; P2OUT |= LED3 | LED4 | LED5 ; //aprinde LED3, LED4 si LED5 _delay_cycles(2000); P2OUT &= ~(LED3 | LED4 | LED5); //stinge LED3, LED4 si LED5 SCHCOL (); P2OUT |= LED3 | LED6 ; //aprinde LED3, LED6 _delay_cycles(2000); P2OUT &= ~(LED3 | LED6); //stinge LED3, LED6 SCHCOL (); P2OUT |= LED3 | LED6 ; //aprinde LED3, LED6 _delay_cycles(2000); P2OUT &= ~(LED3 | LED6); //stinge LED3, LED6 SCHCOL (); P2OUT |= LED3 | LED6 ; //aprinde LED3, LED6 _delay_cycles(2000); P2OUT &= ~(LED3 | LED6); //stinge LED3, LED6 SCHCOL (); P2OUT |= LED3 | LED4 | LED5 ; //aprinde LED3, LED4 si LED5 _delay_cycles(2000); P2OUT &= ~(LED3 | LED4 | LED5); //stinge LED3, LED4 si LED5}void literaR (){ P1OUT |= RST; //resetez coloanele P1OUT &= ~RST; P2OUT |= LED3 | LED4 | LED5 ; //aprinde LED3, LED4 si LED5 _delay_cycles(2000); P2OUT &= ~(LED3 | LED4 | LED5); //stinge LED3, LED4 si LED5 SCHCOL (); P2OUT |= LED3 | LED6 ; //aprinde LED3, LED6 _delay_cycles(2000); P2OUT &= ~(LED3 | LED6); //stinge LED3, LED6 SCHCOL (); P2OUT |= LED3 | LED4 | LED5 ; //aprinde LED3, LED4 si LED5 _delay_cycles(2000); P2OUT &= ~(LED3 | LED4 | LED5); //stinge LED3,LED4 si LED5 SCHCOL (); P2OUT |= LED3 | LED5 ; //aprinde LED3 si LED5 _delay_cycles(2000); P2OUT &= ~(LED3 | LED5); //stinge LED3 si LED5 SCHCOL (); P2OUT |= LED3 | LED6 ; //aprinde LED3 si LED6 _delay_cycles(2000); P2OUT &= ~(LED3 | LED6); //stinge LED3 si LED6}void literaI (){ P1OUT |= RST; //resetez coloanele P1OUT &= ~RST; P2OUT |= LED3 | LED4 | LED5 ; //aprinde LED3, LED4 si LED5 _delay_cycles(2000); P2OUT &= ~(LED3 | LED4 | LED5); //stinge LED3,LED4 si LED5 SCHCOL (); P2OUT |= LED4; //aprinde LED4 _delay_cycles(2000); P2OUT &= ~LED4; //stinge LED4 SCHCOL (); P2OUT |= LED4; //aprinde LED4 _delay_cycles(2000); P2OUT &= ~LED4; //stinge LED4 SCHCOL (); P2OUT |= LED4; //aprinde LED4 _delay_cycles(2000); P2OUT &= ~LED4; //stinge LED4 SCHCOL (); P2OUT |= LED3 | LED4 | LED5 ; //aprinde LED3, LED4 si LED5 _delay_cycles(2000); P2OUT &= ~(LED3 | LED4 | LED5); //stinge LED3,LED4 si LED5}void literaN (){ P1OUT |= RST; //resetez coloanele P1OUT &= ~RST; P2OUT |= LED3 | LED6 ; //aprinde LED3 si LED6 _delay_cycles(2000); P2OUT &= ~(LED3 | LED6); //stinge LED3 si LED6 SCHCOL (); P2OUT |= LED3 | LED4 |LED6; //aprinde LED3, LED4 si LED6 _delay_cycles(2000); P2OUT &= ~(LED3 | LED4 | LED6); //stinge LED3, LED4 si LED6 SCHCOL (); P2OUT |= LED3 | LED5 |LED6; //aprinde LED3, LED5 si LED6 _delay_cycles(2000); P2OUT &= ~(LED3 | LED5 | LED6); //stinge LED3, LED5 si LED6 SCHCOL (); P2OUT |= LED3 | LED6 ; //aprinde LED3 si LED6 _delay_cycles(2000); P2OUT &= ~(LED3 | LED6); //stinge LED3 si LED6 SCHCOL (); P2OUT |= LED3 | LED6 ; //aprinde LED3 si LED6 _delay_cycles(2000); P2OUT &= ~(LED3 | LED6); //stinge LED3 si LED6}void main(void){ WDTCTL = WDTPW + WDTHOLD; //opreste timerul watchdg P1DIR = LED7 | LED8 | RST | CLK; //setez bitii de pe 6, 7, 4 ,5 de pe P1 ca iesiri P2DIR = LED1 | LED2 | LED3 | LED4 | LED5 | LED6; //setez bitii 0, 1, 2, 3, 4, 5, 6 de pe P2 ca iesi while(1) { for (i = 0 ; i <50 ; i++) { literaA (); } for (i = 0 ; i <50 ; i++) { literaD (); } for (i = 0 ; i <50 ; i++) { literaR (); } for (i = 0 ; i <50 ; i++) { literaI (); } for (i = 0 ; i <50 ; i++) { literaA (); } for (i = 0 ; i <50 ; i++) { literaN (); } _delay_cycles(2000000); }}Daca vei avea timp zilele astea te rog sa te uiti putin si sa-mi zici daca pot sa utilizez deplasarea de biti. Multumesc pentru ajutor. Link spre comentariu
Vizitator Postat Iunie 4, 2012 Partajează Postat Iunie 4, 2012 Ar merge, dar îţi propun o metodă mai elegantă. Faci o funcţie care să fie chemată automat, în mod periodic, folosind o întrerupere. Funcţia respectivă va citi 5 octeţi din memorie şi îi va afişa pe LED-uri. Fiecare bit din cele 5 locatii de memorie, va corespunde unui LED. Programul principal va desena litera în cele 5 locaţii de memorie, nu direct la porturi. Mai departe, afişarea la porturi şi reîmprospătarea imaginii se vor face automat, pe întreruperi, de către funcţia de mai sus. Dacă faci aşa, ai următoarele avantaje: - Înveţi să foloseşti întreruperile. - Nu e nevoie să umbli la fire. - Nu e nevoie să refaci montajul. - Programul iese mai simplu. - Cu acelaşi program poţi scrie orice text, nu doar un singur cuvânt. - Poţi face efecte de animaţie cu litere sau cu desene. Când ai timp, zi-mi te rog pe scurt, ca să ştiu cum să-ţi explic, ce ştii despre arhitectura unui microcontroler? Dar despre întreruperi? Link spre comentariu
adyyo Postat Iunie 4, 2012 Autor Partajează Postat Iunie 4, 2012 In primul rand nu stiu mai nimic despre intreruperi...Stiu doar ca este o portiune de cod care se executa atunci cand se comanda acest lucru, MCU-ul oprind orice executa pana in momentul in care primeste comanda de intrerupere. Cat despre arhitectura...aici chiar is 0, adica ma uit pe o schema cu arhitectura si inteleg cum is legate intre ele partile componente, dar cam atat... Daca poti si vrei, explica cat mai intelesul muritorilor, sa poata intelege si altii care vor sa inceapa sa se joace cu MCU-urile. Eu de exemplu am inteles toate lectiile primite pana acum. Daca nu ma ajutai, nu cred ca reuseam sa aprind nici macar un amarat de LED. Link spre comentariu
Vizitator Postat Iunie 8, 2012 Partajează Postat Iunie 8, 2012 Povestea întreruperii Ce este o întrerupere? Să presupunem că tocmai te joci ultimul trăznet de joc. În timp ce sfârtecai la monştri cu spor, sună telefonul! N-ai încotro, te opreşti din joc ca să răspunzi la telefon. Asta este o întrerupere. Un eveniment independent de voinţa ta, dar care vrea ceva de la tine. La fel e şi în lumea MCU-urilor. În timp ce se execută programul principal, apare o întrerupere (un eveniment special), întrerupere generată de un dispozitiv periferic. Exemple de întreruperi: un bit de intrare dintr-un port îşi schimbă starea (s-a apăsat un buton), sau un numărător ajunge la valoarea maximă, etc. Cum se tratează întreruperile? Revenim la exemplul cu jocul. Ce faci când sună telefonul (când vine întreruperea)? - Mai tragi trei gloanţe în monstrul din faţa ta, până cade lat (adică termini de executat instrucţiunea curentă). - Dacă nu ai chef să răspunzi (adică eşti cu întreruperea dezactivată) atunci îţi continui jocul. - Dacă ai chef să răspunzi (întreruperea este activată), atunci pui pauză la joc, şi astfel marchezi unde ai rămas (salvezi pe stivă adresa la care ai rămas cu execuţia programului principal). - Vezi ce e cu telefonul (sari la executarea subrutinei de tratare a întreruperii). - După ce ai terminat cu telefonul (ai tratat întreruperea), te întorci la joc (la execuţia programului principal). La fel face şi MCU-ul. Observăm că în urma unui eveniment (sună telefonul) independent de programul principal (jocul), se înregistrează o cerere de întrerupere. Dacă întreruperea este activată (adică avem chef să răspundem la telefon), atunci mergem să răspundem, altfel ignorăm evenimentul. Înainte de a răspunde la telefon, salvăm (în stiva de adrese) unde am rămas (adică salvăm starea programului principal), apoi sărim la subrutina de tratare a întreruperii (răspundem la telefon). După ce am terminat de vorbit, continuâm jocul de unde am rămas (extragem din stivă ce salvasem şi continuîm execuţia programului principal). Prioritatea întreruperilor Să presupunem o situaţie şi mai complicată. Imediat după ce a sunat telefonul, în timp ce vâram ultimele două gloanţe în cel mai înfiorător monstru, sună cineva la uşa! Acum avem două evenimente (întreruperi) netratate, telefonul şi uşa de la intrare. Ce facem mai întâi? Răspundem la uşă, pentru că dacă am răspunde mai întâi la telefon, atunci persoana din faţa uşii ar putea pleca, crezând că nu e nimeni acasă. Deci, soneria de la uşă are prioritate mai mare decât cea de la telefon. Dacă mai multe întreruperi apar simultan, atunci se tratează mai întăi cele cu prioritate mai mare, apoi cele cu prioritate mai mică. Prioritatea întreruperilor la MCU-uri este stabilită din fabrică şi nu poate fi schimbată. Fiecare periferic (ex: WDT, TIMERS, ADC, USI/UART, I/O PORTS) are prioritea lui şi nu poate fi schimbată. În concluzie, o întrerupere este un eveniment ce se produce independent de programul principal, dar cere o intervenţie imediată. Când apare o întrerupere, execuţia programului principal este întreruptă (de aia îi zice întrerupere), se salvează starea şi locul unde s-a rămas cu execuţia programului principal, apoi se execută funcţia de tratare a întreruperii. Cât timp se execută întreruperea, în mod normal nu se mai primesc alte cereri de întrerupere (întreruperile sunt dezactivate în mod automat, pe toată perioada tratării întreruperii). După terminarea executării unei funcţii de întrerupere (odată cu întâlnirea instrucţiunii de asamblare RETI - RETurn from Interrupt), întreruperile suint reactivate automat. Dacă apar simultan mai multe cereri de întrerupere, se tratează mai întâi cele cu prioritate mai mare. După ce se tratează o întrerupere, se reia programul principal, de unde rămăsese. Mai sunt câteva detalii, dar cred că pentru început ajunge. Să trecem, la un exemplu. Aproape orice MCU are un watchdog. În englază, watchdog înseamnă câine de pază sau ceas deşteptător. Rolul unui watchdog este să detecteze şi să resetezedacă MCU-ul, dacă acesta s-a blocat. La un calculator e clar dacă ceva s-a blocat, dar la o maşină de spălat ce faci dacă se blochează programul? S-ar putea să-ţi stoarcă rufele la nesfârşit, sau să rămână pornită rezistenţa de încălzire, fapte de neacceptat. Pentru detectarea unor astfel de situaţii, s-a inventat watchdog-ul. În mod normal, watchdog-ul este un simplu numărător care poate fi adus la zero prin program. Programul trebuie să aibă grijă ca, din când în când, watchdog-ul să fie resetat. Dacă nu-l aduce nimeni la zero în timp util, atunci watchdog-ul consideră că programul s-a blocat şi resetează MCU-ul (MCU = Micro Controller Unit, adică microcontroler), pentru a-l debloca. La familia MSP430, WDT+ (Watch Dog Timer plus) poate fi folosit ca un simplu contor de timp, care în loc de reset, generează o întrerupere. Voi da şi un exemplu de folosire a WDT+ pe post de timer pentru generarea de întreruperi, dar nu acum, că e prea târziu. Link spre comentariu
adyyo Postat Iunie 9, 2012 Autor Partajează Postat Iunie 9, 2012 M-am apucat in dimineata asta sa incerc ceva intreruperi. Foarte interesata analogia cu un joc si totodata foare bine explicat si usor de inteles. Multumesc inca odata pentru timpul si rabdarea acordata. In alta ordine de idei, cred ca i-am dat de cap. Mi se parea mai complicat la prima vedere, dar dupa ce am facut vreo 2 programele am inteles in mare cum lucreaza intreruperea. //---comanda LED cu intreruperi---#include "msp430g2553.h"#define Rosu BIT0 //defineste BIT0 ca fiind led-ul rosu#define Verde BIT6 //defineste BIT6 ca fiind led-ul verde#define S2 BIT3 //defineste BIT3 ca fiind S2ul S2void main(void){ WDTCTL = WDTPW + WDTHOLD; //opreste timerul watchdg P1DIR = Rosu | Verde; //seteaza biti 0 si 6 ca iesiri P1OUT &= ~(Rosu | Verde); //sting preventiv LED-urile P1REN |= S2; //enable rezistor pe bit-ul 3 P1OUT = S2; //setez rezistor pullup P1IE |= S2; //initializez intreruperea pe bit-ul 3 P1IES |= S2; //setez momentul cand sa aiba loc intreruperea P1IFG &= ~S2; //sterg IFG _EINT(); //pornesc intreruperile while(1) { P1OUT ^= (Rosu | Verde); //clipesc simultan LED-urile _delay_cycles(200000); }}#pragma vector=PORT1_VECTOR__interrupt void PORT1(void) { _delay_cycles(1000); P1OUT &= ~(Rosu | Verde); //sting LED-urile _delay_cycles(200000); P1OUT |= Rosu; //aprinde LED ros _delay_cycles(200000); P1OUT |= Verde; //aprind LED verde _delay_cycles(200000); P1OUT &= ~Verde; _delay_cycles(200000); P1OUT &= ~Rosu; //sting LED-urile P1IFG &= ~S2; //sterg IFG } Link spre comentariu
Vizitator Postat Iunie 9, 2012 Partajează Postat Iunie 9, 2012 Foarte bine. Să revenim la montajul tău. Ca să arăt ideea de reîmprospătare a afişajului în timpul unei întreruperi periodice, dau un exemplu foarte simplu. //******************************************************************************// MSP430G2xx1 WDT+ Timer interrupts semo//// Description: The red LED toggle every 30 ms, on each WDT+ timer interrupt.// The green LED toggle every 1 s, in the main loop//// Author: RoGeorge// // 2012.06.09 v1.0// Built with CCS Version 4.2.4//******************************************************************************#include "msp430g2231.h"//------------------------------------------------------------------------------// Hardware-related definitions//------------------------------------------------------------------------------#define UART_RXD BIT2 // RxD is on P1.2#define S2_BUTTON BIT3 // S2 button is on P1.3#define RED BIT0 // Red LED is on P1.0#define GREEN BIT6 // Green LED is on P1.6void main(void)//------------------------------------------------------------------------------// main()//------------------------------------------------------------------------------{ WDTCTL = WDTPW + WDTHOLD; // Stop watchdog timer WDTCTL = WDT_MDLY_32; // Start Watchdog Timer (interval is ~32ms)// WDTCTL = WDT_MDLY_8; // Start Watchdog Timer (interval is ~8ms)// WDTCTL = WDT_MDLY_0_5; // Start Watchdog Timer (interval is ~0.5ms) IE1 |= WDTIE; // Enable WDT+ interrupts P1OUT = 0x00 & RED; // Initialize P1OUT P1DIR = 0xFF & ~UART_RXD & ~S2_BUTTON; // Set all P1 pins to output, except P1.2 and P1.3 __enable_interrupt(); // Enable interrupts (global) for(;;) { // Infinite main loop //other instructions here _delay_cycles(1000000); // Wait 1 s P1OUT ^= GREEN; // toggle the green LED }}#pragma vector = WDT_VECTOR__interrupt void Watchdog_Timer(void)//------------------------------------------------------------------------------// Watchdog Timer interrupt service routine//------------------------------------------------------------------------------{ P1OUT ^= RED; // toggle the red LED every 30 ms}WDT este programat să dea întreruperi la fiecare 30 ms. LED-ul roşu joacă rolul matricei de LED-uri. Până acum, exemplele au fost cu ceasul MCU-ului la 1 MHz. Pe viitor setează ceasul la maxim (16 MHz) şi programează WDT+ să dea întreruperi la fiecare 2 ms. De câte ori va veni o întrerupere de la WDT+, vei afişa următoarea coloană. Ca să ţii minte la ce coloană ai rămas cu afişarea, declară în interiorul funcţiei de întrerupere, o variabilă de tip static. Ca să ştii ce LED-uri trebuie aprinse, declari o matrice de numere. Fiecare număr va reprezenta o coloană. Ultimii biţi din fiecare număr al matricei vor reprezenta starea unui LED, fiecare LED cu bitul lui. Funcţia de tratare a întreruperii va lua din memorie numărul corespunzător unei coloane, se va uita la fiecare bit din acel număr şi va aprinde LED-urile corespunzătoare. La următoarea întrerupere, va lua următorul număr din matrice şi va afişa următoarea coloană, şi tot aşa. La fiecare întrerupere se va afişa câte o coloană de LED-uri. Ca să desenezi din programul principal o literă, nu vei folosi scrieri la P1OUT, ci vei desena litera în biţii numerelor din matrice. Întreruperea este cea care se va ocupa de citirea matricei şi de aprinderea LED-urilor, câte o coloană la fiecare întrerupere. Ar fi prea dificil să dau un exemplu de cod, pentru ca nu am afişajul. Încearcă să faci singur. Ce n-am explicat suficient de clar, întreabă. Încă ceva. Dacă te uiţi mai atent la exemplele de cod, observi că unele denumiri sunt scrise numai cu litere mari. De ce? În programare există mai multe reguli nescrise, reguli pe care programatorii profesionişti le respectă, chiar dacă nu sunt obligatorii. Le respectă pentru că sunt extrem de utile. Una dintre ele este că toate constantele se scriu din litere MARI. Respectând regula asta, atunci cînd te uiţi peste un program, vezi imediat care sunt constantele şi care sunt variabilele acelui program. Regula asta e deosebit de utilă în înţelegerea codului scris de altcineva sau chiar de tine, mai ales la programele mari. De exemplu, WDTCTL, WDT_MDLY_8, BIT0, GREEN, toate sunt constante. Ele nu se modifică de-a lungul execuţiei programului. 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