Sari la conținut
ELFORUM - Forumul electronistilor

Putin ajutor cu Texas Instruments Lounchpad


adyyo

Postări Recomandate

  • 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

Multumesc:D

 

Acum sa revenim la treaba:))

Prima data am incercat sa schimb frecventa DCO-ului pentru a scapa de LED-urile semi aprinse dar nu mi-a iesit ceva...Am scris

BCSCTL1 = CALBC1_16MHZ;DCOCTL = CALDCO_16MHZ;

Dar nu am reusit sa configurez WDT+ sa imi dea impuls la alte valori decat cele patru date:

#define WDT_MDLY_32         (WDTPW+WDTTMSEL+WDTCNTCL)                         /* 32ms interval (default) */#define WDT_MDLY_8          (WDTPW+WDTTMSEL+WDTCNTCL+WDTIS0)                  /* 8ms     " */#define WDT_MDLY_0_5        (WDTPW+WDTTMSEL+WDTCNTCL+WDTIS1)                  /* 0.5ms   " */#define WDT_MDLY_0_064      (WDTPW+WDTTMSEL+WDTCNTCL+WDTIS1+WDTIS0)           /* 0.064ms " */

Si in plus, nu exista o alta varianta de a produce un delay? Sa nu mai stau sa calculez cate zerouri trebuiesc puse ca sa am nush cate secunde pauza? Ceva mai direct si mai precis de genu "delay(20s)"

Link spre comentariu

Pare corect cum ai setat ceasul, totuşi nu am verificat cu datasheet-ul. Voi verifica, dar nu în seara asta.Valorile în milisecunde, din comentariile de la WDT+, sunt pentru frecvenţa implicită, adică 1 MHz. Pentru 16 MHz, vor fi de 16 ori mai mici.Fişierul header (msp430g2553.h) e foarte util, dar atunci cănd ai nelămuriri, fişierele de referinţă sunt datasheet-urile şi errata. La MSP430, sunt două datasheet-uri pentru acelaşi MCU. Unul este general, pentru toată familia de MCU-uri, şi altul specific fiecărui model în parte. Se mai pot face temporizări hardware cu timer-ele, dar trebuie să calculezi singur duratele. Mai există temporizări software, cu funcţia _delay_cycles(). Ar putea exista şi alte funcţii software de tip _delay(), n-am căutat. Oricum, vei vedea că folosirea delay-urilor software nu este indicată, pentru că în timp ce execută delay-ul software, procesorul munceşte şi consumă curent degeaba. La delay-urile hardware, poate fi lăsat să meargă doar timer-ul, iar restul procesorului poate fi adormit, reducând astfel consumul.De preferat sunt delay-urile hardware, în care procesorul este "adormit" (adică pus în standby, sau low power mode - LPM) intr-unul din modurile low power (LPMx) şi apoi, după scurgerea intervalului de timp programat într-un timer, este trezit de către o întrerupere dată de acel timer.Când ai timp, să pui şi ultima versiune de cod, te rog, ca să îl putem discuta împreună.Nu contează dacă nu e perfect, pune-l aşa cum e.

Link spre comentariu

Pana la urma merge si cu DCO la 16MHz dar din nou se vad umbrele la LED-uri, foarte foarte slab, mult mai slab ca la varianta v1.2, dar e acolo.

/*---------------------------Matrice LED 5x8, v1.4Made by adyyo15-06-2012---------------------------*/#include "msp430g2553.h"#define RST  BIT5				// RST setat pe bit5#define CLK  BIT4				// CLK setat pe bit4int i;							// Variabila iconst int ColMax = 5;			// Numar maxim coloaneconst int RandMax = 8;			// Numar maxim de randurichar display_buffer[5];			// Matricea display_buffer cu 5 elementeunsigned char ContorLinie;		// Contor pentru linieunsigned char ContorColoana;	// Contor pentru coloana//---Tabelele de caractere---const int LITERA_A[5] = {0x0E,0x11,0x1F,0x11,0x11};const int LITERA_D[5] = {0x0F,0x11,0x11,0x11,0x0F};const int LITERA_R[5] = {0x0F,0x11,0x0F,0x09,0x11};const int LITERA_I[5] = {0x0E,0x04,0x04,0x04,0x0E};const int LITERA_N[5] = {0x11,0x13,0x15,0x19,0x11};void pulseP2(int bit) 			//Comanda impuls CLK/RST{   P2OUT |= bit;   P2OUT &= ~bit;}//---Programul principal---void main(void){	BCSCTL1 = CALBC1_16MHZ;			// Seteaza DCO la 16 MHz	DCOCTL = CALDCO_16MHZ;   WDTCTL = WDTPW + WDTHOLD; 		// Stop watchdog timer   WDTCTL = WDT_MDLY_32; 			// Start Watchdog Timer (interval is 32)   IE1 |= WDTIE; 					// Enable WDT+ interrupts   P1DIR = 0xFF; 					// setez toti biti lui P2 ca iesiri   P2DIR = RST | CLK;				// Setez RST si CLK iesiri pe P1   __enable_interrupt();  			// Enable interrupts (global)   for(;;)   {for (i = 0; i < ColMax ; i++){	display_buffer[i] = LITERA_A[i];  				// Incarca litera in bufferul care va fi afisat pe LED-uri} 													// End for (i = 0; i < ColMax ; i++)	_delay_cycles(16000000);	for (ContorLinie = 0; ContorLinie < RandMax ; ContorLinie++)    {		for (ContorColoana = 0 ; ContorColoana < ColMax ; ContorColoana++)      	{			display_buffer[ContorColoana] <<= 1; 	// Muta fiecare bit cu cate un pas la stanga      	} 											// End for (ContorColoana = 0 ; ContorColoana < ColMax ; ContorColoana++)    _delay_cycles(1600000);    } 												// End for (ContorLinie = 0; ContorLinie < RandMax ; ContorLinie++)for (i = 0; i < ColMax ; i++){	display_buffer[i] = LITERA_D[i];  				// Incarca litera in bufferul care va fi afisat pe LED-uri} 													// End for (i = 0; i < ColMax ; i++)	_delay_cycles(16000000);	for (ContorLinie = 0; ContorLinie < RandMax ; ContorLinie++)    {		for (ContorColoana = 0 ; ContorColoana < ColMax ; ContorColoana++)		{			display_buffer[ContorColoana] <<= 1; 	// Muta fiecare bit cu cate un pas la stanga		} 											// End for (ContorColoana = 0 ; ContorColoana < ColMax ; ContorColoana++)	_delay_cycles(1600000);	}												// End for for (ContorLinie = 0; ContorLinie < RandMax ; ContorLinie++)for (i = 0; i < ColMax ; i++){	display_buffer[i] = LITERA_R[i];  				// Incarca litera in bufferul care va fi afisat pe LED-uri} 													// End for (i = 0; i < ColMax ; i++)	_delay_cycles(16000000);	for (ContorLinie = 0; ContorLinie < RandMax ; ContorLinie++)	{		for (ContorColoana = 0 ; ContorColoana < ColMax ; ContorColoana++)		{			display_buffer[ContorColoana] <<= 1; 	// Muta fiecare bit cu cate un pas la stanga		} 											// End for (ContorColoana = 0 ; ContorColoana < ColMax ; ContorColoana++)	_delay_cycles(1600000);	}												// End for for (ContorLinie = 0; ContorLinie < RandMax ; ContorLinie++)for (i = 0; i < ColMax ; i++){	display_buffer[i] = LITERA_I[i];  				// Incarca litera in bufferul care va fi afisat pe LED-uri} 													// End for (i = 0; i < ColMax ; i++)	_delay_cycles(16000000);	for (ContorLinie = 0; ContorLinie < RandMax ; ContorLinie++)	{		for (ContorColoana = 0 ; ContorColoana < ColMax ; ContorColoana++)		{			display_buffer[ContorColoana] <<= 1; 	// Muta fiecare bit cu cate un pas la stanga		} 											// End for (ContorColoana = 0 ; ContorColoana < ColMax ; ContorColoana++)	_delay_cycles(1600000);	}												// End for for (ContorLinie = 0; ContorLinie < RandMax ; ContorLinie++)for (i = 0; i < ColMax ; i++){	display_buffer[i] = LITERA_A[i];  				// Incarca litera in bufferul care va fi afisat pe LED-uri} 													// End for (i = 0; i < ColMax ; i++)	_delay_cycles(16000000);	for (ContorLinie = 0; ContorLinie < RandMax ; ContorLinie++)	{		for (ContorColoana = 0 ; ContorColoana < ColMax ; ContorColoana++)		{			display_buffer[ContorColoana] <<= 1; 	// Muta fiecare bit cu cate un pas la stanga		} 											// End for (ContorColoana = 0 ; ContorColoana < ColMax ; ContorColoana++)	_delay_cycles(1600000);	}												// End for for (ContorLinie = 0; ContorLinie < RandMax ; ContorLinie++)for (i = 0; i < ColMax ; i++){	display_buffer[i] = LITERA_N[i];  				// Incarca litera in bufferul care va fi afisat pe LED-uri} 													// End for (i = 0; i < ColMax ; i++)	_delay_cycles(16000000);	for (ContorLinie = 0; ContorLinie < RandMax ; ContorLinie++)	{		for (ContorColoana = 0 ; ContorColoana < ColMax ; ContorColoana++)		{			display_buffer[ContorColoana] <<= 1; 	// Muta fiecare bit cu cate un pas la stanga		} 											// End for (ContorColoana = 0 ; ContorColoana < ColMax ; ContorColoana++)		_delay_cycles(1600000);	}												// End for for (ContorLinie = 0; ContorLinie < RandMax ; ContorLinie++)	_delay_cycles(32000000);	} 												// End for(;;)} 													// End main#pragma vector = WDT_VECTOR__interrupt void Watchdog_Timer(void){   static int col;   P1OUT &= ~0xFF;									// Stinge coloana anterioara   col++;											// incrementare col   if (col > ColMax)								// Daca col > 5   {      col = 0;										// Adu contorul la 0      pulseP2(RST);									// Reseteaza numarator coloane   } 												// End if (col > COL_MAX)   else												// Daca nu   {	   pulseP2(CLK);								// Schimba coloana   } 												// End else   P1OUT = display_buffer[col];						// Afiseaza pe matrice buffer-ul} 													// End interrupt
Link spre comentariu

Fa totusi si functia aia de afisare, ca sa scapam de scroluit. :da Altminteri felicitari. :aplauze Eu n-am avut atata rabdare cu launchpad-ul.

Link spre comentariu

Multumesc Liviu M.

 

De dimineata ma tot chinui cu functia de afisare dar ceva imi scapa si nu stiu ce.

/*---------------------------Matrice LED 5x8, v2.0Made by adyyo16-06-2012---------------------------*/#include "msp430g2553.h"#define RST  BIT5				// RST setat pe bit5#define CLK  BIT4				// CLK setat pe bit4int i;							// Variabila iconst int ColMax = 5;			// Numar maxim coloaneconst int RandMax = 8;			// Numar maxim de randurichar display_buffer[5];			// Matricea display_buffer cu 5 elementeunsigned char ContorLinie;		// Contor pentru linieunsigned char ContorColoana;	// Contor pentru coloana//---Tabelele de caractere---const int LITERA_A[5] = {0x0E,0x11,0x1F,0x11,0x11};const int LITERA_D[5] = {0x0F,0x11,0x11,0x11,0x0F};const int LITERA_R[5] = {0x0F,0x11,0x0F,0x09,0x11};const int LITERA_I[5] = {0x0E,0x04,0x04,0x04,0x0E};const int LITERA_N[5] = {0x11,0x13,0x15,0x19,0x11};void pulseP2(int bit) 			//Comanda impuls CLK/RST{   P2OUT |= bit;   P2OUT &= ~bit;}void LitAfisata(const int litera){	for (i = 0; i < ColMax ; i++)	{		display_buffer[i] = litera;  				// Incarca litera in bufferul care va fi afisat pe LED-uri	}}//---Programul principal---void main(void){	BCSCTL1 = CALBC1_16MHZ;			// Seteaza DCO la 16 MHz	DCOCTL = CALDCO_16MHZ;   WDTCTL = WDTPW + WDTHOLD; 		// Stop watchdog timer   WDTCTL = WDT_MDLY_32; 			// Start Watchdog Timer (interval is 32)   IE1 |= WDTIE; 					// Enable WDT+ interrupts   P1DIR = 0xFF; 					// setez toti biti lui P2 ca iesiri   P2DIR = RST | CLK;				// Setez RST si CLK iesiri pe P1   __enable_interrupt();  			// Enable interrupts (global)   for(;;)   {	   LitAfisata(LITERA_A[5]);	   _delay_cycles(16000000);	   	for (ContorLinie = 0; ContorLinie < RandMax ; ContorLinie++)	       {	   		for (ContorColoana = 0 ; ContorColoana < ColMax ; ContorColoana++)	         	{	   			display_buffer[ContorColoana] <<= 1; 	// Muta fiecare bit cu cate un pas la stanga	         	} 											// End for (ContorColoana = 0 ; ContorColoana < ColMax ; ContorColoana++)	       _delay_cycles(1600000);	       } 												// End for (ContorLinie = 0; ContorLinie < RandMax ; ContorLinie++)   } 												// End for(;;)   } 													// End main   #pragma vector = WDT_VECTOR   __interrupt void Watchdog_Timer(void)   {      static int col;      P1OUT &= ~0xFF;									// Stinge coloana anterioara      col++;											// incrementare col      if (col > ColMax)								// Daca col > 5      {         col = 0;										// Adu contorul la 0         pulseP2(RST);									// Reseteaza numarator coloane      } 												// End if (col > COL_MAX)      else												// Daca nu      {   	   pulseP2(CLK);								// Schimba coloana      } 												// End else      P1OUT = display_buffer[col];						// Afiseaza pe matrice buffer-ul   } 													// End interrupt

Asa arata acum codul , face derularea, dar nu imi afiseaza A ci doua bare verticale pe bit-ul 1 si 3 al matricei . Iar in dreptul

LitAfisata(LITERA_A[5]);
am eroarea #177-D subscript out of range

Presupun ca problema e din cauza tipului de data declarat, dar nu stiu ce ar trebui sa folosesc in loc de consr int.

 

L.E. Unde gasesc un tabel cu fiecare tip de data si ce poate face aceasta, dar explicata mai pe intelesul meu? Eu ma uit pe http://msdn.microsoft.com/en-us/library/s3f49ktz(v=vs.80).aspx dar nu prea pricep mare lucru.

Link spre comentariu

Eu ma gandeam la ceva de genul:

 

const int LITERA[][5] = {{0x0E,0x11,0x1F,0x11,0x11},{0x0F,0x11,0x11,0x11,0x0F,{0x0F,0x11,0x0F,0x09,0x11},{0x0E,0x04,0x04,0x04,0x0E},{0x11,0x13,0x15,0x19,0x11}};void AfisareLitera(int *litera){   int i;   int ColMax = 5; // aici folosesti conventiile pe care ti le-a povestit deja RoGeorge si pe care eu le-am sarit   int RandMax = 8;   int display_buffer[5] ;   int ContorLinie =0 ;   int ContorColoana = 0 ;   for (i = 0; i < ColMax ; i++)    {      display_buffer[i] = litera[i];              // Incarca litera in bufferul care va fi afisat pe LED-uri   }  // for (i = 0; i < ColMax ; i++)   _delay_cycles(16000000);   for (ContorLinie = 0; ContorLinie < RandMax ; ContorLinie++)    {      for (ContorColoana = 0 ; ContorColoana < ColMax ; ContorColoana++)      {         display_buffer[ContorColoana] <<= 1;    // Muta fiecare bit cu cate un pas la stanga      }                                  // End for (ContorColoana = 0 ; ContorColoana < ColMax ; ContorColoana++)    _delay_cycles(1600000);    }   // for (ContorLinie = 0; ContorLinie < RandMax ; ContorLinie++)} //void AfisareLitera(int *litera)void main(void){...  for(ContorLitere = 0; ContorLitere<MaxLitere; ContorLitere++)   {       AfisareLitera(LITERA[ContorLitere]); // aici nu-s chiar sigur ca e bine si nu am cum sa testez chiar acum   }...}
Link spre comentariu

Să luăm la periat v2.0, ţine-te bine!

1. Păstrează indentarea icon_axe, ca să fie codul lizibil. Compilatorul de C nu ţine cont de indentare, dar trebuie să fii riguros, ca să se înţeleagă ce ai vrut să scrii. Indentarea e importantă. Acum ai un program mic şi deja îl ştii pe de rost, dar la cele mari, fără indentare corectă nu se mai înţelege nimic.

- dacă ai hotărât să pui acoladele una sub alta, atunci aşa să fie. Acolada care termină funcţia main() e indentată greşit.

- hotărăşte-te, ori deschizi acolada aliniată cu instrucţiunea de mai sus, ori cu cea de mai jos. Multe bucle "for" au acoladele indentate greşit.

- Instrucţiunile grupate de o pereche de acolade formează un bloc de instrucţiuni. Treci cu un tab la dreapta numai dacă apar blocuri noi. Toată funcţia Watchdog_Timer() e indentată greşit.

Cum să indentezi mai multe rânduri deodată:

Mai întâi selectezi rândurile şi apoi dai TAB, sau SHIFT+TAB, după cum ai nevoie să le deplasezi, la dreapta sau la stânga.

 

2. Identificatorii constantelor se scriu cu toate literele mari icon_axe, adică cu CAPS LOCK. ColMax şi RandMax sunt scrise greşit. Fă-le te rog, ori COLMAX, ori COL_MAX, cum vrei tu, dar nu cu litere mici. Programul funcţionează şi dacă le scrii cu litere mici, dar aşa e convenţia.

 

Limbajul C este case sensitive.

Pentru că tot vorbim de litere mari şi mici, fac o mică paranteză. Limbajul C este case sensitive, adică face distincţie între literele mari şi cele mici. De exemplu, pentru limbajul C,

ColoanaDeLaStânga şi

ColoanaDELaStânga sunt doi identificatori complet diferiţi, din cauză literei E mare.

Alte limbaje, de exemplu limbajul BASIC, nu sunt case sensitive.

 

3. "const int RAND_MAX = 8;" versus "#define RAND_MAX 8", care e mai potrivită?

Depinde, e de preferat varianta a doua. Explicaţia e mai lungă, o lăsăm pentru altă dată.

Aici ar merge povestit despre preprocesor (preprocessor), despre compilator (compiler), despre editorul de legături (linkeditor), despre asamblor (assembler) şi despre tot procesul prin care se ajunge de la codul sursă scris în C, limbaj pe care să îl înţeleagă oamenii, la un şir de biţi de 0 şi de 1, pe care să-i înţeleagă MCU-ul. Pe scurt, tot procesul de traducere a codului sursă din limbaj uman în limbaj maşină, se numeşte compilare.

 

Am scris mai demult ceva despre toate astea, viewtopic.php?p=276044#p276044, dar nu e suficient. Dacă ai răbdare să te uiţi acolo, vezi şi observaţia lui cirip.

 

3. Ce face calificativul "const" în declaraţii?

Are grijă să nu mai poţi face atribuiri. Dacă compilatorul vede

litera = AltăValoare;

face scandal, adică, odată declarată, nu te mai lasă să schimbi valoare lui "litera". Efectul este că "litera" va rămâne la aceeaşi valoare pe toată execuţia programului, adică va fi o constantă.

 

Pentru compilator, în

const int x; şi

int y;

atât x cât şi y sunt variabile de tip întreg. Singura diferenţă este că, lui y te va lăsa să-i schimbi valoarea, dar nu te va lăsa să-i schimbi valoarea lui x. Deci x este tot o variabilă, dar pe care nu o mai poţi schimba, adică x este constantă.

 

Din cauza asta, cred că altceva vroiai să scrii aici:

void LitAfisata(const int litera)

 

4. P1OUT &= ~0xFF; icon_axe // Stinge coloana anterioara

Să traducem:

P1OUT &= ~0xFF; // vreau să sting toţi biţii, nu mă interesează ce valoare aveau înainte!

înseamnă

P1OUT = P1OUT & (~0xFF); // 0xFF negat dă 0x00

adică

P1OUT = P1OUT & 0x00; // x AND 0 dă 0, indiferent de x

adică

P1OUT = 0;

 

Vrei să stingi ledurile, le stingi cu P1OUT = 0;, şi gata, fără să faci atâtea operaţii.

 

5. Aşa-i că n-ai desenat mai întâi pe foaie ce vroiai să faci? icon_axe

Pun pariu că ai sărit direct la tastatură. Ca urmare, buclele for nu au cum să meargă.

 

6.

am eroarea #177-D subscript out of range

Presupun ca problema e din cauza tipului de data declarat, dar nu stiu ce ar trebui sa folosesc in loc de consr int.L.E.

"out of range" înseamnă că "dă pe-afară"

În C, indexare matricelor se face zero based, adică indicele pleacă de la 0.

Declararea spune câte elemente are matricea, nu spune indicele maxim.

Exemplu:

int x[2]; e o matrice cu 2 numere întregi, primul e x[0] şi al doilea e x[1]

Dacă apare pe undeva prin program x[2], înseamnă că ai depăşit indicele maxim, iar compilatorul îţi va da un mesaj de depăşire, adică out of range.

 

7.

Unde gasesc un tabel cu fiecare tip de data si ce poate face aceasta, dar explicata mai pe intelesul meu? Eu ma uit pe http://msdn.microsoft.com/en-us/library ... tz(v=vs.80).aspx dar nu prea pricep mare lucru.

Vezi care explicaţie de aici ţi-e mai potrivită:

http://lmgtfy.com/?q=tipuri+de+date+%C3%AEn+C

 

L.E.

Pentru început, fă două funcţii:

displayOneLetter() şi scrollBufferOnce(), apoi le chemi din main(), pentru fiecare literă în parte.

 

Ex.:

displayOneLetter(LITERA_A);

scrollBufferOnce();

displayOneLetter(LITERA_D);

scrollBufferOnce();

...

Link spre comentariu

Am zis că las la sfârşit, şi am uitat ce era mai important.

 

Dacă ai buffer-ul format din elemente de tip char, de ce ai declarat LITERA_X ca fiind o matrice formată din elemente de tip int?

Declară literele cu:

const char LITERA_A = ...;

pentru că dacă nu o faci, atunci când vei vărsa litera în buffer, compilatorul se va plânge că nu poate băga un întreg într-un caracter, şi aşa este. Un char este reprezentat pe 8 biţi iar un int, pe 16 biţi. 16 biţi nu încap în 8 biţi.

 

La declararea unei funcţii, spui ce tip de date primeşte funcţia, şi ce tip de dată scoate funcţia.

Dacă funcţia primeşte ca parametru de intrare o matrice de 5 caractere, atunci aşa o declari, cu matrice de 5 caractere:

void LitAfisata(const char LITERA_DE_AFIŞAT[5])

şi de chemat, o chemi cu:

LitAfisata(LITERA_A);

 

Când scrii doar LITERA_A, fără paranteze drepte, compilatorul pricepe că e vorba de toată matricea, şi o ia ca pe un pointer.

 

Mai sunt căteva lucruri de corectat, dar la alea va ţipa compilatorul, le descoperi singur.

 

Neapărat, citeşte primele capitole din orice manual de C. Citeşte despre:

- structura unui programului scris în C

- blocuri de instrucţiuni

- identificatori

- valabilitatea identificatorilor

- tipuri de date

- reprezentarea datelor în memorie.

Link spre comentariu

Multumesc din nou RoGeorge pentru lectii.

M-am apucat weekendul trecut de citit "TOTUL DESPRE C SI C++ [Kris Jamsa][Lars Kland]". Incepe sa se mai lumineze cate ceva in capsorul meu :nas: mai am doar 600 de pagini pana voi fi AS in programare :rade:

Revenind la programul meu, de fapt al tau, ca tot ce am scris in program au fost indicatiile tale...I-am facut si functiile de afisare si de deplasare, am facut si indentarea frumos. Varianta anterioara nu era indentata deoarece era in stadiu de testare :d.

intr-adevar, nu am facut pe foaie. Am incercat o schema inainte, dar mi se parea ca dureaza prea mult scrisul pe foaie. Incerc incet, incet sa ma obisnuiesc cu schemele pe foaie, dar mai dureaza putin...

Acum vreau sa citesc despre codul ASCII, pana diseara sper sa ma luminez.

Iata si varianta finala a programului:

/*---------------------------Matrice LED 5x8, v2.1Made by adyyo18-06-2012---------------------------*/#include "msp430g2553.h"#define RST  BIT5				// RST setat pe bit5#define CLK  BIT4				// CLK setat pe bit4#define COL_MAX 5				// Numar maxim coloane#define RAND_MAX 8				// Numar maxim de randuriint i;							// Variabila ichar display_buffer[5];			// Matricea display_buffer cu 5 elementeunsigned char ContorLinie;		// Contor pentru linieunsigned char ContorColoana;	// Contor pentru coloana//---Tabelele de caractere---const char LITERA_A[5] = {0x0E,0x11,0x1F,0x11,0x11};const char LITERA_D[5] = {0x0F,0x11,0x11,0x11,0x0F};const char LITERA_R[5] = {0x0F,0x11,0x0F,0x09,0x11};const char LITERA_I[5] = {0x0E,0x04,0x04,0x04,0x0E};const char LITERA_N[5] = {0x11,0x13,0x15,0x19,0x11};void pulseP2(int bit) 									//Comanda impuls CLK/RST{   P2OUT |= bit;   P2OUT &= ~bit;}void Afiseaza_Litera(const char LITERA_AFISATA[5])		// Incarca litera in bufferul care va fi afisat pe LED-uri{	for (i = 0; i < COL_MAX ; i++)	{		display_buffer[i] = LITERA_AFISATA[i];	}													// End for (i = 0; i < COL_MAX ; i++)}void Scroll_Buffer(void)								// Deplaseaza buffer-ul la stanga{	for (ContorLinie = 0; ContorLinie < RAND_MAX ; ContorLinie++)	{		for (ContorColoana = 0 ; ContorColoana < COL_MAX ; ContorColoana++)		{		display_buffer[ContorColoana] <<= 1; 			// Muta fiecare bit cu cate un pas la stanga		} 												// End for (ContorColoana = 0 ; ContorColoana < COL_MAX ; ContorColoana++)		_delay_cycles(1600000);	} 													// End for (ContorLinie = 0; ContorLinie < RAND_MAX ; ContorLinie++)}//---Programul principal---void main(void){	BCSCTL1 = CALBC1_16MHZ;								// Seteaza DCO la 16 MHz	DCOCTL = CALDCO_16MHZ;	WDTCTL = WDTPW + WDTHOLD; 							// Stop watchdog timer	WDTCTL = WDT_MDLY_32; 								// Start Watchdog Timer (interval is 32)	IE1 |= WDTIE; 										// Enable WDT+ interrupts	P1DIR = 0xFF; 										// setez toti biti lui P2 ca iesiri	P2DIR = RST | CLK;									// Setez RST si CLK iesiri pe P1	__enable_interrupt();  								// Enable interrupts (global)	for(;;)	{		Afiseaza_Litera(LITERA_A);						// A		_delay_cycles(16000000);		Scroll_Buffer();		Afiseaza_Litera(LITERA_D);						// D		_delay_cycles(16000000);		Scroll_Buffer();		Afiseaza_Litera(LITERA_R);						// R		_delay_cycles(16000000);		Scroll_Buffer();		Afiseaza_Litera(LITERA_I);						// I		_delay_cycles(16000000);		Scroll_Buffer();		Afiseaza_Litera(LITERA_A);						// A		_delay_cycles(16000000);		Scroll_Buffer();		Afiseaza_Litera(LITERA_N);						// N		_delay_cycles(16000000);		Scroll_Buffer();		_delay_cycles(32000000);	} 													// End for(;;)} 														// End main#pragma vector = WDT_VECTOR__interrupt void Watchdog_Timer(void){	static int col;	P1OUT = 0;											// Stinge coloana anterioara	col++;												// incrementare col	if (col > COL_MAX)									// Daca col > 5	{		col = 0;										// Adu contorul la 0		pulseP2(RST);									// Reseteaza numarator coloane	} 													// End if (col > COL_MAX)	else												// Daca nu	{		pulseP2(CLK);									// Schimba coloana	} 													// End else	P1OUT = display_buffer[col];						// Afiseaza pe matrice buffer-ul} 														// End interrupt

L.E. Totusi de ce se strica indentarea cand atasez codul in elforum? Ar trebui sa tin mai apropiate de cod comentariile?

Link spre comentariu

Acum, programul tău arată mult mai bine. :da

Faptul că ţii cont de ce te-am rugat, e cea mai mare mulţumire, nu-i nevoie să mai spui şi-n cuvinte.

 

Foarte bine că ai început să citeşti dintr-o carte. Oricâte sfaturi ai primi pe forumuri, ele nu înlocuiesc studiul sistematic. Sunt multe cărţi despre limbajul C, unele foarte bune, altele foarte proaste. Sper să fi nimerit o carte bună, n-o ştiu. Depinde şi de stilul fiecăruia. Unii preferă formalismul, alţii preferă o abordare mai prietenoasă.

 

O carte pe care multă lume o recomandă, scrisă chiar de către autorii limbajului C, Brian Kernighan şi Dennis Ritchie, este: "The C Programming Language". Detalii despre carte găseşti şi pe Wikipedia: http://en.wikipedia.org/wiki/The_C_Programming_Language. Oricum, nu contează ce recomandă alţii, tu citeşte-o pe cea care ţi se pare mai clară.

 

Poate că am intervenit prea brutal în programul început de tine, să ştii că m-am gândit şi eu la aspectul ăsta. Totuşi, am continuat să "forţez" cu cerinţe care depăşesc nivelul de hobby, pentru că primele deprinderi sunt foarte importante pentru evoluţia de mai târziu. Dacă îţi faci un stil defectuos, cu greu vei mai putea să te desprinzi de el. Mai târziu, când vei fi nevoit să programezi lucruri mai serioase, deprinderile anterioare fie te vor ajuta, dacă sunt corecte, fie te vor încurca suficient cât să nu poţi termina ce ai de făcut, dacă sunt greşite.

 

În plus, dacă spui că eşti energetician, disciplina din energetică este vecină cu milităria, ce facem noi aici, e poezie. Energetica nu e o joacă, responsabilităţile sunt foarte mari. N-aş fi aflat asta, pentru că nu sunt energetician, dar am făcut automatizări în energetică timp de cîţiva ani. Mai exact, am făcut SCADA pentru staţii de distribuţie de înaltă tensiune. Atunci am aflat cum stau lucrurile în energeticiă. Orice greşeală poate însemna pierderi de vieţi omeneşti sau pagube de milioane de euro.

 

Cam offtopic, dar ajută lumea să înţeleagă de ce trebuie să fie totul perfect: http://chzgifs.files.wordpress.com/2011 ... lordp1.gif

 

Să revenim, nu e nevoie să scrii linii de C pe foaie. E suficient să scrii în pseudocod lucrurile mai importante. de exemplu:

function print (text)   iau fiecare caracter, până întâlnesc sfărşitul textului      dacă este o literă sau cifră         afişez caracterul      dacă este un caracter netipăribil         este o comandă? atunci execută comanda (exemplu "backspace" sau secvenţe ESC)         este altceva? atunci ignor caracterul şi trec mai departeend
Nu strică să desenezi şi structurile de date, ca să ai o reprezentare cât mai clară.

Ce reprezintă o celulă de memorie din buffer, dar un bit din buffer, cui corespunde? Cum arată o literă în buffer[]? Ce trebuie să faci ca să obţii un scroll stânga-dreapta? Dar sus-jos? Dar rotiri? Odată desenată reprezentarea în memorie a matricii buffer[], toate răspunsurile devin evidente.

 

Cu tabela ASCII e foarte simplu. Fiecărei litere sau cifre, îi corespunde un cod, adică un număr. Fiecare caracter este reprezentat pe un singur octet, printr-un număr cuprins între 0 şi 255, în funcţie de caracter. Ce număr corespunde fiecărui caracter, este scris în tabela ASCII: http://www.asciitable.com/

Observăm că în afară de litere şi cifre, mai există semne de punctuaţie şi caractere netipăribile.

În C, caracterele sunt reprezentate folosind codul ASCII. Mai există şi alte metode de codare, dar nu le discutăm acum.

 

Alinierea se strică pentru că în editorul de texte din CSS, un TAB este reprezentat prin 4 spaţii, pe când în ElForum, un TAB este înlocuit cu 3 spaţii. Din cauza asta, se decalează. Ca să nu se mai strice alinierea atunci cînd copiezi codul pe Elforum, ai mai multe variante:

- faci TAB-ul să fie reprezentat pe 3 spaţii în CSS: te duci la Window->Preferences... În fereastra care se deschide mergi la General->Editors->Text Editors şi modifici valoare din text box-ul Displayed tab Width:. În loc de 4 pui 3, apoi dai OK. Pe urmă aliniezi frumos codul în CSS, pentru că atunci când treci de la TAB din 4 spaţii la TAB din 3, se va strica alinierea. Mai departe rămâne aliniat frumos, chiar şi atunci când îl copiezi pe forum.

- setezi CSS-ul să facă el înlocuirea TAB-urilor cu spaţii, dar asta e destul de enervant, pentru că te încurcă atunci când scrii în CSS. Se face din aceeaşi fereastră dar mergi la C/C++ -> Editors şi bifezi check box-ul Insert space for tabs. Nu recomand pentru că e enervant cănd dai Backspace în CSS, în loc să se dea cu un TAB mai la stânga, se dă cu un singur spaţiu.

- ar mai fi şi alte metode, dar nu are rost să insistăm, cea mai bună e prima.

Ca să nu întrec măsura cu tot felul de pretenţii, aş avea rugămintea să mai facem 2-3 exerciţii înainte de a te lăsa "de capul tău":

- scroll şi rotiri stănga, dreapta, sus, jos

- afişare de text cu diferite efecte

Pornim cu funcţii elementare, cât mai simple. Folosindu-te de funcţiile simple, construieşti altele din ce în ce mai complexe. Şi tot aşa, până ajungi să ai o funcţie:

print("HELLO WORLD ", WITH_LEFT_SCROLL, VERY_FAST);
Pentru asta va trebui să-ţi defineşti funcţii separate pentru scroll 1 pixel şi rotire 1 pixel pentru cele 4 direcţii.

 

Folosind funcţiile astea, implementezi funcţii pentru intrarea literei în afişaj, în diferite moduri:

- brusc (cum ai făcut prima dată)

- intrare literei prin stânga (cu deplasare)

- prin dreapta

- de sus

- de jos

 

La fel şi pentru ieşirea literei din afişaj

- prin stingere bruscă

- prin deplasare

 

Toate modurile de afişare vor fi trimise ca parametru către funcţia print. Clarificăm pe parcurs.

Dacă apucăm să facem şi astea, mai departe te vei putea descurca fără probleme.

 

Foarte important:

Programele în C trebuie să fie bine structurate, cu funcţii scurte şi clare.

Funcţiile trebuie să aibă, pe cât posibil, maxim 10-20 de rânduri, de preferat e să încapă toată funcţia într-un singur ecran.

 

La sfârşit, dar nu în ultimul rând, vreau să spun că, până acum ai făcut progrese foarte mari! :aplauze

Link spre comentariu

Off: Intr-adevar, cu energetica nu e de glumit. Si ca sa explicam lumii fenomenul din filmulet, este vorba despre o eroare foarte grava in ordinea de executie a deconectarii unei linii de inalta tensiune. Cele din imagine sunt separatoare, cu rolul de a intrerupe vizibil circuitul. Acestea nu ar trebui actionate niciodata sub tensiune deoarece nu au camera de stingere si nu au posibilitatea de a stinge arcul electric ce apare la deconectare. Intotdeauna inainte de actionarea separatoarelor, se deconecteaza intrerupatorul dinaintea si de dupa separator. Inapoi la problema, eu nu reusesc sa imi imaginez ceea ce mi-ai spus acum ceva vreme legat de rotirea scrisului:

Dacă vrei să roteşti litera, adică scrisul să iasă pe o parte şi să intre pe partea cealaltă, va trebui să salvezi bitul cel mai din stânga şi, după ce faci deplasarea la stânga, să îl suprapui peste bitul cel mai din dreapta.

Adica sa folosesc o variabila care sa imi numere bitii, si cand ajung la ultimul bit, valoara variabilei sa o introduc intr-o alta bucla care sa porneasca de la acea valoare?
Link spre comentariu

Offtopic:

Aşa e, în energetică, ordinea manevrelor e foarte importantă şi e respectată cu stricteţe, deşi există interblocaje care, teoretic, ar trebui să te oprească să faci prostii. Cu toate astea, apar situaţii în care, deşi ordinea manevrelor este corectă, dacă protecţiile şi interblocajele nu funcţionează, iese rău:

Acolo nu au mers interblocajele sau protecţia pentru necorespondenţă fază (după comanda de deschidere întreruptor, o fază a rămas totuşi conectată, apoi s-a dat comanda de deschidere separator, iar urmarea a fost cea din film).

 

Revenind ontopic, atunci când faci o deplasare, să zicem la stânga, bitul cel mai din stânga, numit şi MSB (Most Significant Bit), va fi pierdut după ce ai făcut deplasarea. Dacă vrei să roteşti ce e pe afişaj, atunci, înainte de deplasare, va trebui să salvezi bitul care urmează să se piardă. După ce faci deplasarea, bitul care a ieşit din display prin stânga, va fi reintrodus prin dreapta.

 

Aici apare avantajul mâzgălirii pe hîrtie, cum insistam mai devreme.

Cam aşa ar arăta paragraful de mai sus, desenat:

 

Posted Image

 

Pentru buffer, MSB este chiar bitul de semn, iar LSB (Least Significant Bit) este bitul cel mai din dreapta, sau bitul de paritate.

 

void rotire_stânga(int nr_pixeli_rotiţi) { // rotirea afişajului la stânga cu un nr de n pixeli (n=nr_pixeli_rotiţi)   char i, n, bit_salvat;   for (n = 1; n <= nr_pixeli_rotiţi; n++) {      for i = 0; i < MAX_COL; i++) {         if (buffer[i] < 0) // buffer[i] e negativ dacă MSB == 1            bit_salvat = 1; // salvez MSB         else            bit_salvat = 0; // salvez MSB         buffer[i] <<= 1; deplasere spre stînga         if (bit_salvat == 1) // în mod normal, LSB este 0 în urma deplasării, dacă MSB era 1 inainte,            ++buffer[i];  // atunci copiez MSB în LSB, adică pun 1 în LSB (fac asta prin incrementare)      }   }}
Codul de mai sus poate conţine erori, e scris doar în ElForum şi e netestat.
Link spre comentariu

Eu as fi facut testul direct dupa MSB (buffer & 0x80), astfel incat sa fiu independent de tipul de date (pot fi foarte bine si unsigned char). Daca vrea sa afiseze caractere chinezesti (ASCII extins), cu codul tau nu sunt sigur ca poate. :rade:

void rotire_stânga(int nr_pixeli_rotiţi) { // rotirea afişajului la stânga cu un nr de n pixeli (n=nr_pixeli_rotiţi)   char i, n, bit_salvat;   for (n = 1; n <= nr_pixeli_rotiţi; n++) {      for i = 0; i < MAX_COL; i++) {         if (buffer[i] & 0x80) // dacă MSB == 1            bit_salvat = 1; // salvez MSB         else            bit_salvat = 0; // salvez MSB         buffer[i] <<= 1; deplasere spre stînga         if (bit_salvat == 1) // în mod normal, LSB este 0 în urma deplasării, dacă MSB era 1 inainte,            ++buffer[i];  // atunci copiez MSB în LSB, adică pun 1 în LSB (fac asta prin incrementare)      }   }}
Link spre comentariu

Liviu M, exemplul tău este foarte bun, întotdeauna te-ai exprimat foarte concis. :da

 

Totuşi, am ales comparaţia cu zero, pentr că, în acelaşi timp cu alte concepte, vroiam să mai prind încă un aspect, şi anume că primul bit (asta numai în cazul numerelor cu semn, NU unsigned), reprezintă chiar semnul.

1 înseamnă negativ, iar 0 înseamnă pozitiv, noţiune pe care nu aveam chef să o prezint separat, pentru că se subînţelege din reprezentarea binară a numerelor întregi.

 

Să nu mă înţeleagă lumea greşit, intervenţiile lui Liviu M au fost întotdeauna remarcabile, mult mai practice şi mai pertinente decât am reuşit eu să exprim în toate paginile de teorie sau de filozofie.

Recunosc, din punct de vedere practic, Liviu M m-a întrecut. :31

Până la o exprimare foarte clară şi concisă, mai am un drum lung.

 

Deşi în cazul de faţă e vorba de altceva, şi anume de introducerea unei noţiuni noi (şi anume că la numerele cu semn, primul bit e semnul, iar dacă primul bit e 1, înseamnă că numărul e negativ), versus o altă soluţie de rezolvare a aceleiaşi probleme, consider că ambele contribuţii sunt binevenite.

Liviu M tinde să arate "cum se prinde un peşte anume", eu tind să arăt "cum se pescuieşte în general", niciunul dintre aspecte nefiind de neglijat.

Spor la programat! :wav:

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