1 /*
  2   * citeste/scrie24c16.c
  3   *
  4   * Created: 26.12.2015 13:40:56
  5   *  Author: Simpalean Nicolae
  6   */ 
  7  #include <avr/io.h>
  8  #include <util/delay.h> // librarie inclusa pentru utilizarea temporizarilor
  9  #include <stdlib.h> // librarie inclusa pentru a putea folosi functia "itoa" in program
 10  #include <avr/interrupt.h> // pentru utilizarea intreruperilor
 11  #include <string.h> // pentru siruri de carcatere
 12  #define BAUDRATE 9600 //  rata de transfer pe serial
 13  #define BAUD_PRESCALLER (((F_CPU / (BAUDRATE * 16UL))) - 1)  // formula pentru frecventa de transfer pe serial
 14  #define TIMP_0_LOGIC _delay_loop_2(3) // temporizare pentru zero logic
 15  #define TIMP_1_LOGIC _delay_loop_2(5) // temporizare pentru 1 logic
 16  #define SCLPORT PORTC   //SCL pentru comunicatia I2C se va face pe portul C
 17  #define SCLDDR  DDRC    //seteaza directia datelor pe portul C , INTRARE/IESIRE
 18  #define SCLPIN  PINC    // datele de pe SCL se citesc pe portul C
 19  #define SDAPORT PORTC   // SDA pentru I2C se face pe portul C
 20  #define SDADDR  DDRC    // seteaza directia datelor pentru SDA
 21  #define SDAPIN  PINC    //datele de pe SDA se citesc pe portul C
 22  #define SCL PC5     //PORTC.5 va fi SCL 
 23  #define SDA PC4     //PORTC.4 va fi SDA 
 24  #define SDA_0_LOGIC SDADDR|=((1<<SDA))
 25  #define SDA_1_LOGIC SDADDR&=(~(1<<SDA))
 26  #define SCL_0_LOGIC SCLDDR|=((1<<SCL)) 
 27  #define SCL_1_LOGIC SCLDDR&=(~(1<<SCL)) 
 28  #define BOOL uint8_t
 29  #define ADRESA_PENTRU_SCRIERE 0xA0 // adresa pentru scriere in memorie , 0xA0 sau 1010 0000 binar
 30  #define ADRESA_PENTRU_CITIRE 0xA1 // adresa pentru citire memorie , 0xA1 sau 1010 0001 binar 
 31  #define OPERATIUNE_REUSITA 1
 32  #define EROARE 0
 33  uint16_t adresa=0;
 34  char caracter;
 35  
 36  void initializare_I2C() // functie care initializeaza magistrala I2C    
 37  {
 38      SDAPORT&=(1<<SDA);
 39      SCLPORT&=(1<<SCL);
 40      SDA_1_LOGIC;
 41      SCL_1_LOGIC;    
 42  }
 43  
 44  void Start_I2C() // functie care genereaza o conditie de START pe magistrala 
 45  {
 46      SCL_1_LOGIC;
 47      TIMP_1_LOGIC;   
 48      SDA_0_LOGIC;
 49      TIMP_1_LOGIC;
 50  }
 51  
 52  void Stop_I2C() // functie care genereaza  STOP pe magistrala
 53  {
 54      SDA_0_LOGIC;
 55      TIMP_1_LOGIC;
 56      SCL_1_LOGIC;
 57      TIMP_0_LOGIC;
 58      SDA_1_LOGIC;
 59      TIMP_1_LOGIC;
 60  }
 61  
 62  uint8_t Scrie_un_byte(uint8_t data) // functie care scrie opt biti (un byte) si returneaza ACK=1 daca memoria raspunde
 63  {                                   // sau ACK=0 daca memoria nu raspunde 
 64      uint8_t i;  
 65      for(i=0;i<8;i++)
 66      {
 67          SCL_0_LOGIC;
 68          TIMP_0_LOGIC;       
 69          if(data & 0x80)
 70          SDA_1_LOGIC;
 71          else
 72          SDA_0_LOGIC;        
 73          TIMP_1_LOGIC;       
 74          SCL_1_LOGIC;
 75          TIMP_1_LOGIC;       
 76          while((SCLPIN & (1<<SCL))==0);      
 77          data=data<<1;
 78      }   
 79      //al noualea bit (ACK)
 80      SCL_0_LOGIC;
 81      TIMP_0_LOGIC;   
 82      SDA_1_LOGIC;
 83      TIMP_1_LOGIC;   
 84      SCL_1_LOGIC;
 85      TIMP_1_LOGIC;   
 86      uint8_t ack=!(SDAPIN & (1<<SDA));   
 87      SCL_0_LOGIC;
 88      TIMP_1_LOGIC;   
 89      return ack; 
 90  }
 91  
 92  uint8_t Citeste_un_byte(uint8_t ack)
 93  {
 94      uint8_t data=0x00;
 95      uint8_t i;  
 96      for(i=0;i<8;i++) // citeste in bucla cei 8 biti ai unui byte
 97      {       
 98          SCL_0_LOGIC;
 99          TIMP_1_LOGIC;
100          SCL_1_LOGIC;
101          TIMP_1_LOGIC;       
102          while((SCLPIN & (1<<SCL))==0);      
103          if(SDAPIN &(1<<SDA))
104          data|=(0x80>>i);        
105      }   
106      SCL_0_LOGIC;
107      TIMP_0_LOGIC;                           
108      if(ack)            //verifica ACK-ul de la memorie
109      {
110          SDA_0_LOGIC;
111      }
112      else
113      {
114          SDA_1_LOGIC;
115      }
116      TIMP_1_LOGIC;   
117      SCL_1_LOGIC;
118      TIMP_1_LOGIC;   
119      SCL_0_LOGIC;
120      TIMP_1_LOGIC;   
121      return data;    //returneaza byte-ul citit
122  }
123  
124  BOOL Scrie24c16(uint16_t address,uint8_t data) // functie care scrie valoarea din variabila <data> la adresa <adress> din memorie
125  {
126      Start_I2C();
127      if(!Scrie_un_byte(ADRESA_PENTRU_SCRIERE)) // daca memoria nu raspunde cand este apelata(semnul ! este de negatie) la adresa 10100000 (A0)
128      {
129          Stop_I2C(); //genereaza un stop pe magistrala ;altfel, inseamna ca ACK-ul a fost generat
130          //eroare
131          return EROARE; // si returneaza un zero (EROARE)
132      }
133      if(!Scrie_un_byte(address)) //daca memoria nu raspunde cu un ACK dupa receptia byte-ului care contine adresa de scriere <adress>
134      {
135          Stop_I2C(); // genereaza un STOP , elibereaza magistrala ; altfel, inseamna ca ACK-ul a fost generat
136          //I2C i/o error
137          return EROARE; // si returneaza un zero (EROARE)
138      }
139      //urmeaza scrierea byte-ului din variabila <data> la adresa <adress>
140      if(!Scrie_un_byte(data)) // daca memoria nu returneaza ACK dupa scrierea celor 8 biti la adresa <adress>
141      {
142          Stop_I2C(); // genereaza un STOP , elibereaza magistrala ; altfel, inseamna ca ACK-ul a fost generat ,deci byte scris cu succes
143          return EROARE; // si returneaza un zero (EROARE)
144      }
145      Stop_I2C(); // elibereaza magistrala I2C
146      _delay_ms(5);
147      return OPERATIUNE_REUSITA; // returneazaun 1 logic daca totul a decurs corect pana la capat (OPERATIUNE_REUSITA=1)
148  }
149  
150  BOOL Citeste24c16(uint16_t address,uint8_t *data)
151  {
152      Start_I2C();
153      if(!Scrie_un_byte(ADRESA_PENTRU_SCRIERE))
154      {
155          Stop_I2C();
156          return EROARE;
157      }
158      if(!Scrie_un_byte(address))
159      {
160          Stop_I2C();
161          return EROARE;
162      }
163      Start_I2C();
164      if(!Scrie_un_byte(ADRESA_PENTRU_CITIRE))
165      {
166          Stop_I2C();
167          return EROARE;
168      }
169      *data=Citeste_un_byte(0);
170      Stop_I2C();
171      return OPERATIUNE_REUSITA;
172  }
173  
174  void Wait() // temporizare
175  {
176      uint8_t i;
177      for(i=0;i<20;i++)
178          _delay_loop_2(0);
179  }
180  
181  void USART_init(void);            // Declarare functie care initializeaza comunicatia seriala
182  void USART_send( unsigned char caracter);    //Declarare functie care transmite caractere pe portul seerial
183  void USART_putstring(char* StringPtr);    // Declarare functie care transmite siruri de caractere pe portul serial
184  
185  char USARTReadChar() // Functie care citeste caractere sosite pe portul serial
186  {
187      while(!(UCSR0A & (1<<RXC0))) //asteapta sosirea unui caracter
188      {
189          //nu face nimic in timpul asteptarii
190      }
191      //Acum a sosit un caracter (byte) , a carui valoare se pote citi din UDR0
192      return UDR0;
193  }
194  
195  void USARTWriteChar(char caracter)
196  {
197      // Asteapta pana cand bufferul pentru transmisie UDR0 este pregatit
198      while(!(UCSR0A & (1<<UDRE0)))
199      {
200          //nu face nimic in timpul asteptarii
201      }
202      //Acum este momentul pentru a scrie caracterul de transmis in UDR0
203      UDR0=caracter;
204  }
205  
206  int  main(void)
207  {   
208      _delay_ms(500);  // delay la pornire
209      initializare_I2C();
210       USART_init(); 
211       USART_putstring("Program scris de :");
212       USART_send('\r');
213       USART_send('\n');
214      USART_putstring("SIMPALEAN NICOLAE ");
215      USART_send('\r');
216      USART_send('\n');
217      USART_putstring("Tasta <x> initiaza citirea memoriei 24c16 ca fisier text , cu mesaj de eroare");
218      USART_send('\r');
219      USART_send('\n');
220      USART_putstring("Tasta <z> initiaza citirea memoriei 24c16 ca fisier text , fara mesaj de eroare");
221      USART_send('\r');
222      USART_send('\n');    
223      sei();  // activeaza intreruperile globale
224      while(1)
225      {
226          // bucla infinita       
227      }
228      return 0;
229  }
230  
231  void USART_init(void){                // Functie care initializeaza comunicatia seriala
232      UBRR0H = (uint8_t)(BAUD_PRESCALLER>>8);
233      UBRR0L = (uint8_t)(BAUD_PRESCALLER);
234      UCSR0B = (1<<RXEN0)|(1<<TXEN0)| (1 << RXCIE0);
235      UCSR0C = (3<<UCSZ00);
236  }
237  
238  void USART_send( unsigned char caracter){   // Functie care transmite caractere pe serial
239      while(!(UCSR0A & (1<<UDRE0)));
240      UDR0 = caracter;    
241  }
242  
243  void USART_putstring(char* StringPtr){  // Functie care trimite siruri de caractere pe serial
244      while(*StringPtr != 0x00){
245          USART_send(*StringPtr);
246      StringPtr++;}   
247  }
248  
249  ISR(USART_RX_vect) //intreruperi la sosirea unui caracter din PC , pe portul serial
250  {   
251      caracter=UDR0;  // pune in variabila <caracter> , caracterul sosit pe serial
252      if (caracter=='s') // daca , caracterul sosit pe serial este <s>
253      {   uint8_t valoare=0; // creaza o variabila , numar intreg cu valoare initiala zero
254          for (int adresa=0;adresa<256 ;adresa++) // bucla care se repetade 256 de ori; variabila <adresa> va avea valori de la 0 la 255
255          {           
256              if (!Scrie24c16(adresa,valoare)) // daca functia Scrie24c16 nu reuseste sa scrie un byte (nu primeste ACK de la memo)
257              {
258                  USART_putstring("Fac !! Nu gasesc memoria !!!"); //trimite textul din paranteza pe serial 
259                  break; // si intrerupe bucla 
260              }       
261              valoare++; // la fiecare repetare a buclei , creste valoarea variabilei <valoare> cu o unitate 
262          }       
263      }                   
264              if (caracter=='c') // daca ,caracterul sosit pe serial este <c>
265          {               
266              USART_send('\r'); // muta cursorul la inceputul unui rand nou
267              USART_send('\n');
268              uint8_t nr_de_valori_pe_rand=0; // creaza o variabila necesara pentru a afisa numarul dorit de valori hex pe rand (ex. 16)
269              for (int adresa=0;adresa<=256 ;adresa++)
270              {   uint8_t i; // creaza o variabila <i>, in care functia Citeste24c16 pune valoarea citita la fiecare repetare a buclei
271                   char buffer[4]; // creaza un buffer in care functia  itoa pune valoarea citita din memorie , transformata in hex
272                   char rand[100]; // creaza un buffer in care se memoreaza un rand intreg , inainte de trimitere pe serial pentru afisare
273                   _delay_ms(100); // delay intre citirile de adrese din memo (pentru a avea timp sa extrag memo din scoclu in timpul citirii)
274              if (!Citeste24c16(adresa,&i)) // daca funcita de citire nu reuseste (nu primeste ACK de la memo)
275              {
276                  USART_putstring("Fac !! Nu gasesc memoria !!!"); // afiseaza textul din paranteza
277                  break;
278              }               
279                  itoa (i,buffer,16); // iar daca functia de citire reuseste , atunci valoarea citita va fi prelucrata de functia itoa            
280                      if (nr_de_valori_pe_rand==0) // daca variabila <nr_de_valori_pe_rand > este zero ,se creaza un rand nou de valori
281                      {  
282                          if (i<16) // si valoarea citita este intre 0 si 15 , deci reprezentata cu un singur caracter
283                          {
284                              strcpy (rand, "0"); // pune cifra 0 inainte de valoarea citita pentru a afisa sub forma 00 01 02 si nu 0 1 2
285                              strcat (rand,buffer); // dupa cifra 0 pune valoarea citita din buffer
286                              strcat (rand , " "); // pune o pauza intre valorile citite
287                          } 
288                          else // iar daca nu este intre 0 si 15 
289                          {
290                              strcpy (rand,buffer); // adauga in buffer valoarea citita 
291                              strcat (rand , " "); // pune o pauza intre valori
292                          }    
293                      } 
294                      else // daca valoarea citita nu trebuie afisata in prima pozitie a unui rand nou
295                      {
296                          if (i<16) // daca valoarea citita este intre 0 si 15
297                          {   strcat (rand, "0"); // pune un 0 in fata valorii citite
298                              strcat (rand,buffer); // pune valoarea citita
299                              strcat (rand , " "); // pune o pauza intre valorile citite
300                          } 
301                          else // iar daca valoarea este mai mare decat 15 , nu mai este nevoie de un 0 in fata ,acestea avand deja 2 cifre
302                          {
303                              strcat (rand,buffer); // pune in buffer-ul <rand> valoarea citita de functia itoa ,converita in hex 
304                              strcat (rand , " ");// pune o pauza intre valori
305                          }                                       
306                      }                   
307                      nr_de_valori_pe_rand++; // incrementeaza valoarea cu 1 , de la 0 la 15          
308                  if (nr_de_valori_pe_rand>15) // cand se citestea 16-a valoare se executa urmatoarele:
309                  {
310                      USART_putstring(rand); // trimite pe serial randul complet de valori
311                      USART_send('\r'); //muta cursorul pe urmatorul rand
312                      USART_send('\n');
313                      nr_de_valori_pe_rand=0; // reseteaza variabila pentru inceperea unui rand nou la citirea urmatoarei adrese din memorie
314                      _delay_ms(30);
315                  }
316           }
317      }
318      
319          if (caracter=='z') // daca ,caracterul  este <z> , citeste 256 de adrese , chiar daca memoria nu raspunde cu ACK (defecta sau lipsa) 
320              {
321                  USART_send('\r');
322                  USART_send('\n');
323                  uint8_t nr_de_valori_pe_rand=0;
324                  for (int adresa=0;adresa<=256 ;adresa++)
325                  {   uint8_t i;
326                      char buffer[4];
327                      char rand[100];
328                      Citeste24c16(adresa,&i);
329                      itoa (i,buffer,16);
330                      if (nr_de_valori_pe_rand==0)
331                      {
332                          if (i<16)
333                          {
334                              strcpy (rand, "0");
335                              strcat (rand,buffer);
336                              strcat (rand , " ");
337                          }
338                          else
339                          {
340                              strcpy (rand,buffer);
341                              strcat (rand , " ");
342                          }
343                      }
344                      else
345                      {
346                          if (i<16)
347                          {   strcat (rand, "0");
348                              strcat (rand,buffer);
349                              strcat (rand , " ");
350                          }
351                          else
352                          {
353                              strcat (rand,buffer);
354                              strcat (rand , " ");
355                          }
356                      }
357                      nr_de_valori_pe_rand++;
358                      if (nr_de_valori_pe_rand>15)
359                      {USART_putstring(rand);
360                          USART_send('\r');
361                          USART_send('\n');
362                          nr_de_valori_pe_rand=0;
363                          _delay_ms(5);
364                      }
365               }
366          }       
367  }