Sari la conținut
ELFORUM - Forumul electronistilor

Putin ajutor cu Texas Instruments Lounchpad


adyyo

Postări Recomandate

Vizitator

N-am avut timp să mă uit la codul dat de tine. Încearcă aşa:

#include "msp430g2231.h"#define	LED_ROSU	BIT0#define	LED_VERDE	BIT6#define	BUTON_S2	BIT3void main(void) {   	WDTCTL = WDTPW + WDTHOLD;      //Stop watchdog timer   	P1DIR = LED_VERDE | LED_ROSU;	//Configureaza pinii P1.0 si P1.6 ca iesiri (restul ca intrari)	P1REN = BUTON_S2;				//Activeaza rezistoarele de pe intrarea P1.3	P1OUT = LED_VERDE | BUTON_S2;   //Aprinde LED-ul verde, de control, stinge restul									//iar pe P1.3 activeaza pull up resistor	while(1) {		if (!(P1IN & BUTON_S2))	//daca butonul S2 e apasat (P1.3 = 0 inseamna apasat)			P1OUT |= LED_ROSU;	//atunci aprinde LED-ul rosu (fara sa umble la LED-ul verde)		else			P1OUT &= ~LED_ROSU;	//altfel stinge LED-ul rosu (fara sa umble la LED-ul verde)	}}

Merge?

Link spre comentariu
  • Răspunsuri 155
  • Creat
  • Ultimul Răspuns

Top autori în acest subiect

  • adyyo

    64

  • Liviu M

    31

  • picolo

    4

  • MifTy

    1

Top autori în acest subiect

Da, merge perfect :101 Multumesc mult pentru timpul si ajutorul acordat!Am un mic proiect in cap, singura problema era cu butonul...Cand voi avea timp o sa construiesc circuitul si va voi prezenta evolutia.Inca odata multumesc mult :aplauze

Link spre comentariu
Vizitator

Între timp am aflat de ce pe LaunchPad-ul meu mergea iar pe al tău nu mergea.

 

Există cel puţin două versiuni de LaunchPad.

- Prima versiune are o rezistenţă R34, de 47 K, rezistenţă care ţine pinul P1.3 la +V (1 logic) atunci când nu e butonul apăsat. Tot pe P1.3 mai este un condensator C24 de 100 nF pentru debouncing.

- A doua versiune de LaunchPad, cum e a ta, vine fără R34 şi C24. Există loc pe placă pentru ele dar nu au fost montate.

În afară de R34 şi C24 lipsă, mai sunt unele mici diferenţe. Conectorul J3 are pinii în altă ordine iar MCU-urile (MCU = MicroController Unit) cu care se livrează sunt mai puternice: MSP430G2553 şi MSP430G2452 în loc de MSP430G2231 şi MSP430G2211.

 

Primul program pentru citirea butonului nu mergea pentru că nu exista rezistenţa R34 care să dea 1 logic. Al doilea program merge pentru că în loc de R34 am activat rezistorul de pull up al pinului P1.3

 

Pentru aproape fiecare pin, în interiorul MCU-ului există există căte o rezistenţă care poate fi legată la +V (pull up), la GND (pull down) sau poate fi dezactivată. Asta se face cu ajutorul următoarelor registre:

- PxREN (Port x REsistor Enable) unde x e numărul portului, foloseşte pentru activare sau dezactivarea rezistoarelor pentru fiecare bit în parte din portul Px

- un bit 1 din PxREN activează rezistorul corespunzător acelui bit din portul Px

- un bit 0 din PxREN dezactivează rezistorul corespunzător acelui bit din portul Px. Implicit, la pornirea MCU-ului toţi biţii din PxREN sunt 0, adică rezistoarele sunt dezactivate- PxOUT (Port x OUT) unde x e numărul portului, foloseşte pentru a stabili unde se leagă rezistoarele activate, la Vcc sau GND, pentru fiecare bit în parte din portul Px

- un bit 1 din PxOUT pune la Vcc rezistorul corespunzător acelui bit din portul Px

- un bit 0 din PxOUT pune la GND rezistorul corespunzător acelui bit din portul Px

Reţine rolul registrelor PxREN şi PxOUT în activarea şi configurarea rezistorului de pe fiecare pin.

E foarte important pentru configurarea corectă a porturilor de intrare.

 

Încă o observaţie despre ultimul program. A fost făcut foarte simplu, doar în ideea de a demonstra că se poate şi fără întreruperi. Din această cauză, nu are implementată funcţia de debouncing.

 

 

 

Ce este debouncing-ul?

-----------------------------

În mod normal, atunci când se închid sau se deschid contactele unui întrerupător, cum ar fi de exemplu un buton, contactele mecanice vibrează. Din cauza asta, în loc să trimită un singur impuls către MCU, orice buton trimite zeci sau sute de impulsuri parazite, foarte scurte, până când vibraţiile se stabilizează şi contactul electric devine ferm. Durata până la stabilizarea unui contact ferm depinde de construcţia mecanică a lamelelor de contact din buton şi de materialele folosite. De obicei este de ordinul milisecundelor.

 

Necazul este că MCU-urile sunt foarte rapide, ele văd fiecare vibraţie ca pe o apăsare distinctă. Astfel, dacă apăs o singură dată butonul, MCU-ul crede că l-am apăsat de zeci sau sute de ori. Ca să scap de problema asta trebuie să fac debouncing, adică să-i spun MCU-ului să nu ia în considerare şi vibraţiile contactelor, doar contactul ferm, de lungă durată.

 

Din fericire vibraţiile apar doar la începutul şi la sfârşitul apăsării. Tot ce am de făcut este ca, înainte de a considera butonul apăsat, să-i spun MCU-ului să aştepte câteva milisecunde pentru stabilizarea contactelor. Asta este metoda software pentru debouncing. Există si metoda hardware, în care se pune un condensator extern care să suprime vibraţiile, aşa cum era C24, care la noile versiuni de LaunchPad lipseşte de pe placă.

 

Ca să vezi ce probleme apar la citirea butoanelor şi de ce e nevoie de debouncing, scrie un program care să facă aşa:

- la o apăsare a butonului S2, aprinde LED-ul verde

- la următoarea apăsare a butonului S2, stinge LED-ul verde

- la următoarea apăsare aprinde iar LED-ul verde, şi tot aşa, aprinde - stinge - aprinde - stinge...

 

Spor la butonat!

Link spre comentariu

Salutare.Nu prea am avut timp saptamana asta de jucat, dar am icercat azi sa fac programelul propus, dar iar am intampinat o pb. Cat de greu poate fi sa aprinzi si sa stingi un led? :sparge: Deci am scris astfel:#include "msp430g2553.h"#define LED_ROSU BIT0#define BUTON_S2 BIT3void main(void) { WDTCTL = WDTPW + WDTHOLD; //Stop watchdog timer P1DIR = LED_ROSU; //Configureaza pinii P1.0 P1REN = BUTON_S2; //Activeaza rezistoarele de pe intrarea P1.3 P1OUT = BUTON_S2; //Pe P1.3 activeaza pull up resistor while(1) { if (!(P1IN & BUTON_S2)) if ((P1OUT & LED_ROSU)) P1OUT = 0x00; else P1OUT = LED_ROSU; }}Am incercat fara sa dau run ci cu step into si am vazut astfel: ajunge la primul if si asteapta. Apas S2 si simultan dau step into, merge mai departe...trece peste al doilea if, executa else-ul si aprinde LED-ul. Toate bune pana aici. La urmatorul F5, se intoarce programul la primul if si, chiar daca nu este apasat butonul, intra in al doilea if si stinge LED-ul. Ce gresesc?

Link spre comentariu

Reia te rog povestea de mai sus. La un moment dat acolo scrie:

 

...

Pentru aproape fiecare pin, în interiorul MCU-ului există există căte o rezistenţă care poate fi legată la +V (pull up), la GND (pull down) sau poate fi dezactivată. Asta se face cu ajutorul următoarelor registre:

- PxREN (Port x REsistor Enable) unde x e numărul portului, foloseşte pentru activare sau dezactivarea rezistoarelor pentru fiecare bit în parte din portul Px

- un bit 1 din PxREN activează rezistorul corespunzător acelui bit din portul Px

- un bit 0 din PxREN dezactivează rezistorul corespunzător acelui bit din portul Px. Implicit, la pornirea MCU-ului toţi biţii din PxREN sunt 0, adică rezistoarele sunt dezactivate- PxOUT (Port x OUT) unde x e numărul portului, foloseşte pentru a stabili unde se leagă rezistoarele activate, la Vcc sau GND, pentru fiecare bit în parte din portul Px

- un bit 1 din PxOUT pune la Vcc rezistorul corespunzător acelui bit din portul Px

- un bit 0 din PxOUT pune la GND rezistorul corespunzător acelui bit din portul Px

Reţine rolul registrelor PxREN şi PxOUT în activarea şi configurarea rezistorului de pe fiecare pin.

E foarte important pentru configurarea corectă a porturilor de intrare.

...

 

Asta înseamnă că fiecare bit dintr-un port de iesire (PxOUT) are două roluri:

1. Să presupunem că pinul respectiv este configurat ca ieşire. În cazul ăsta, dacă scriu la BITy din PxOUT, atunci pe pinul corespunzător acelui bit voi găsi 0 sau 1 logic, nimic deosebit până aici.

2. Să presupunem acum că pinul este configurat ca intrare. O intrare lăsată în gol, prinde din aer brum şi tot felul de paraziţi. Pentru asta se obişnuieste legarea ei la + sau la masă printr-un rezistor. Astfel stabilim un 1 sau un 0 logic pe intrare şi o facem să nu mai flencăne aiurea. În cazul nostru, rezistorul care se leagă pe intrare este construit chiar în interiorul integratului. Rezistorul se poate activa din registrul PxREN. Odată activat, rămâne să stabilim dacă vrem să legăm rezistorul la + sau la masă, asta se face tot cu biţii din PxOUT, chiar dacă pinul e configurat ca intrare.

Tu ai schimbat starea LED-ului roşu scriind în toţi biţii din P1OUT, inclusiv în bitul 3, pe care l-ai suprascris, cu toate că de fapt vroiai să modifici doar LED-ul de pe bitul 0. Bitul 3 fusese configurat pe 1, adică cu rezistorul la +. Când l-ai suprascris cu 0, ai pus rezistorul la masă. La următoarea citire, chiar dacă nu apeşi butonul, intrarea de pe bitul 3 e ţinută la masă de către rezistorul intern şi, ca urmare, vei citi întotdeauna 0.

 

Ca să nu mai ai surprize, când modifici starea LED-ului umblă doar la bitul corespunzător acelui LED. Întâi corectează asta şi pe urmă vezi ce surprize mai apar, că mai sunt câteva.

 

-----------------------------------------------

 

Separat de problemele de mai sus, vreau să mai explic ceva, ca să fie mai clar pentru eventualii începători în ale C-ului:

#define BUTON_S2 BIT3 // BIT3 e definit ca 0x0008, 8 în hexazecimal inseamnă in binar 1000...P1REN = BUTON_S2;              // înseamnă P1REN = 0000 1000 în binar, adică bitul 3 e 1 şi aşa trebuie să rămână                                         //  pentru că semnifică rezistor activat pe pinul de intrare P1.3 (unde e legat şi S2)P1OUT = BUTON_S2;             // înseamnă P1OUT = 0000 1000 în binar, adică bitul 3 e 1 şi aşa trebuie să rămână                                        // pentru că semnifică rezistor legat la +
Link spre comentariu

O da! :101 In sfarsit am inteles care e treaba cu biti. Nu imi era foarte clara legatura intre hexa si binar. Am gasit un tabel pe gogu si, impreuna cu explicatia de mai sus am priceputif (!(P1IN & BUTON_S2)) if ((P1OUT & LED_ROSU)) P1OUT = BUTON_S2; else P1OUT = 0x09;Multumesc de luminare!Doar ca acum se stinge si se aprinde, cam ce trebuia da o aparut ceea ce mi-ai explicat mai sus legat de vibratii. Daca apas scurt si repede se stinge/aprinde relativ ok, dar daca apas usor clipeste. Cum fac debounce-ul din soft?

Link spre comentariu

Aşa e, toate etichetele alea cu litere mari nu sunt altceva decât numere:

BIT0 înseamnă 0000 0001 în binar

BIT3 înseamnă 0000 1000 în binar

BIT6 înseamnă 0100 0000 în binar

BUTON_S2 este BIT3 iar BIT3 este 0000 1000. În concluzie BUTON_S2 inseamnă 0000 1000 în binar.

Similar, LED_ROSU înseamnă 0000 0001 în binar.

 

Atunci de ce nu lucrăm direct cu numerele în binar?

S-ar putea şi aşa dar, într-un program mare, ar fi greu de înţeles ce înseamnă P1OUT = 0100 0000.

Dacă scriu P1OUT = LED_VERDE, devine mult mai clar de înţeles ce face acea instrucţiune.

Un alt avantaj este că, dacă mut LED-ul verde de pe pinul P1.6 pe P1.5, modific doar instrucţiunea de la început, unde am definit LED_VERDE, fără să trebuiască să modific peste tot în interiorul programului.

 

Tot pe biţi trebuie să le vezi şi când faci operaţii cu ele. Exemplu:

0000 0001 (adică LED_ROSU) +

0000 1000 (adică BUTON_S2)

----------

0000 1001

 

Deci LED_ROSU + BUTON_S2 este 0000 1001 sau, dacă scriem în hexazecimal, 0x09.

Operatorii logici pe biţi sunt:

~ este funcţia NOT, "inversează" fiecare bit

| este funcţia OR, face "sau logic" pe biţi

& este funcţia AND, face "şi logic" pe biţi

^ este funcţia XOR, face "sau exclusiv" pe biţi

http://www.cprogramming.com/tutorial/bi ... ators.html

 

După exemplele de mai sus, zi-mi te rog, cât înseamnă în binar:

1. LED_VERDE

2. ~LED_VERDE

3. (LED_VERDE + BUTON_S2)

4. (LED_VERDE | LED_ROSU)

5. (LED_VERDE & BUTON_S2)

6. ~(LED_ROSU | BUTON_S2)

7. 1111 1111 ^ LED_VERDE?

 

-----------------------------------------------

 

Când ai scris în programul tău P1OUT = 0x09, a mers pentru că ştiai sigur ce stare avea fiecare bit. Ce faci dacă vrei să modifici un singur bit fără să ştii ce valoare au ceilalţi biţi? Nu mai merge cu P1OUT = 0x09. Înainte de a ajunge la debouncing trebuie să mai învăţăm ceva: cum umblăm doar la biţii care ne interesează fără să îi modificăm pe ceilalţi.

 

Pentru debouncing ideea este să citeşti S2 şi dacă îl găseşti apăsat atunci mai faci o citire peste câteva milisecunde, să zicem peste 5 ms. Dacă şi atunci e tot apăsat atunci poţi să spui că ai o apăsare fermă, altfel consideri că a fost vibraţie.

Link spre comentariu

Ce faci dacă vrei să modifici un singur bit fără să ştii ce valoare au ceilalţi biţi?

Citeste postul meu (ala cu informatie utila) :da

sau sa folosesti "masti":

P1DIR = 0x40;P1DIR = P1DIR | 0x01; //folosind OR am lasat bitii 7..1 neschimbati si am facut bitul 0 = 1;P1OUT = 0x41; //aici n-are rost sa folosesti masti, pentru ca vrei sa comuti ambele iesit o data
Link spre comentariu

Aşa e.

 

P1OUT = 0x41; //aici n-are rost sa folosesti masti, pentru ca vrei sa comuti ambele iesit o data
Exact genul ăsta de instrucţiuni vreau să descurajez.

Măştile şi denumirile simbolice trebuie folosite întotdeauna, chiar şi la programe foarte simple, cu scopul de a forma deprinderi corecte.

Nimic nu e mai urât de depanat sau de întreţinut decât un program care conţine elemente hard coded.

 

În programul lui adyyo, exact o instrucţiune de genul ăsta a făcut butonul S2 nefuncţional.

Link spre comentariu

Daca am ambele LED-uri aprinse si vreau sa sting doar LED-ul verde fac in felul urmator:0100 0000 + 0000 0001 = 0100 0001 (ambele aprise)0100 0001 ^ 0100 0000 = 0000 0001 (LED rosu aprins, verde stins)Sau din exemplul lui Liviu M:0100 0000 | 0000 0001 = 0100 001 (ambele aprinse)

Link spre comentariu

Si tot legat de operatori logici, cum ar trebui sa citesc o intructiune de genul: P1OUT &= ~LED_ROSU (P1OUT AND= cu NOT LED_ROSU)Adica compar ceea ce era deja pe P1OUT cu LED_ROSU negat si apoi, rezultatul in trec in P1OUT?Mai exact:0100 1000 (ce era scris in P1OUT)0100 1000 &= ~0000 0001 deci,0100 1000 &= 1111 1110 deci,0100 1000 il trec in P1OUT

Link spre comentariu

Să zicem că vreau să aprind LED_ROSU, fără să modific ceilalţi biţi din P1OUT:P1OUT = P1OUT | LED_ROSU; //citesc starea portului, apoi fac sau logic pe biţi cu mascaasta se mai scrie prescurtatP1OUT |= LED_ROSU // aşa se aprind doar biţii specificaţi în masca "LED_ROSU" (in cazul nostru doar BIT0), fără să îi modificăm pe ceilalţiAlt exemplu care aprinde ambele LED-uri fără să umble la ceilalţi biţi:P1OUT |= LED_ROSU | LED_VERDECa să sting doar biţii din mască, mai întâi inversez masca iar apoi fac şi logic cu ce era înainte la P1OUT:P1OUT = P1OUT & ~LED_ROSU; //stinge doar biţii din masca LED_ROSUAceeaşi instrucţiune se scrie prescurtatP1OUT &= ~LED_ROSU;In afară de stins sau aprins, uneori trebuie să inversez starea biţilor specificaţi de mască (toggle bits). Se poate face într-o singură instrucţiune, similar cu stingerea sau aprinderea.Ştii cum?

Link spre comentariu

Măştile şi denumirile simbolice trebuie folosite întotdeauna,

Hm, as zice depinde.

Aplicatul de masti consuma resurse. Compilatorul nu stie ca tu vrei sa scrii cod citibil, asa ca "implementeraza" si operatiile de mascare (cel putin asa cred :nas: ).

Asa ca uneori e mai "eficient" un comentariu in cod.

Asta pe de o parte. Pe de alta, define-ul ascunde valoarea pe care o "denumeste", asa ca uneori ingreuneaza debuggul. Drept pentru care eu mi-am creat prostul obicei sa le evit.

 

Si tot legat de operatori logici, cum ar trebui sa citesc o intructiune de genul:

 

P1OUT &= ~LED_ROSU (P1OUT AND= cu NOT LED_ROSU)

 

Adica compar ceea ce era deja pe P1OUT cu LED_ROSU negat si apoi, rezultatul in trec in P1OUT?

.

 

Operatiile de tipul

A += B
sunt transcrierile prescurtate ale
A = A+B

In cazul tau se "transcrie" in

P1OUT = P1OUT & (~LED_ROSU)
Adica da, ai interpretat bine.

 

LE RoGeorge a fost mai rapid.

Link spre comentariu

RoGeorge, presupun ca are legatura cu intrebarea 7 de mai sus.Ca sa fac toggle scriu stfel, cred: P1OUT = P1OUT | LED_ROSU ^ 1111 1111 sauP1OUT |= LED_ROSU ^ 1111 1111

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