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 }