O circuito no simulador proteus:
configurando os fuses:
O código fonte :
1: //************************************************************************
2: // usando o protocolo I2C (
3: // Version : 1.0
4: // microcontrolador : AVR ATMega8
5: // Autor : Aguivone (fiz só uma adaptação )
6: // descrição : embora ele seja chamado de two wire interface(TWI) só difere do I2C
7: // pelo numero de endereços (dispositivos) na linha de comunicação.
8: // data : 08/06/11.
9: //
10: //************************************************************************
11: #include <inttypes.h>
12: #include <avr/io.h>
13: #include <util/twi.h> /* header que contem algumas macros utilizadas */
14:
15: #define F_CPU 4000000L /*frequencia em hz , valor do cristal*/
16:
17: /*
18: * I2C endereços nas 24Cxx EEPROM:
19: *
20: * 1 0 1 0 E2 E1 E0 R/~W 24C01/24C02
21: * 1 0 1 0 E2 E1 A8 R/~W 24C04
22: * 1 0 1 0 E2 A9 A8 R/~W 24C08
23: * 1 0 1 0 A10 A9 A8 R/~W 24C16
24: assim para escrever por exemplo na memoria 24C16 deve se colocar 1010 + o endereço do banco de memoria que vai acessar +sinaliza se é escrita ou leitura
25:
26: */
27:
28: #define ENDE_ESCRITA 0xA0 /* E2 E1 E0 = 0 0 0 banco zero */
29: #define PAGE_SIZE 8 // no maximo 8 bytes por linha podem ser escrito(1pagina = 8bytes)
30:
31: uint8_t twst;
32:
33: void I2C_inicializar(void)//configura comunicação
34: {
35: /* 100 kHz clock do barramento I2C, TWPS = 0 => prescaler = 1 */
36: #if defined(TWPS0)/* has prescaler (mega128 & newer) */
37: {
38: TWSR = 0;
39: }
40: #endif
41: #if F_CPU < 3600000UL
42: TWBR = 10; /* menor valor TWBR */
43: #else
44: TWBR = (F_CPU / 100000UL - 16) / 2; //se a frequencia do clock for maior que 3,6Mhz
45: #endif
46: }
47:
48:
49: int ler_bytes(uint16_t eeaddr, int len, uint8_t *buf)
50: {
51: uint8_t sla, twcr, n = 0;
52: int rv = 0;
53:
54: /* busca o endereço de memoria e seleciona qual banco de memoria vai usar */
55: sla = ENDE_ESCRITA | (((eeaddr >> 8) & 0x07) << 1);
56: restart:
57: if (n++ >= 200)//numero maximo de tentativas
58: return -1;
59: begin:
60:
61: TWCR = _BV(TWINT) | _BV(TWSTA) | _BV(TWEN); /* inicio de transmissao*/
62: while ((TWCR & _BV(TWINT)) == 0) ; /* espera interrupção */
63: switch ((twst = TW_STATUS))
64: {
65: case TW_REP_START: /* OK,pula para proxima etapa*/
66: case TW_START:
67: break;
68:
69: case TW_MT_ARB_LOST: /* informação perdida*/
70: goto begin;
71:
72: default:
73: return -1; /* retorna erro */
74:
75: }
76:
77: /* endeço mais bit de escrita SLA+W */
78: TWDR = sla | TW_WRITE;
79: TWCR = _BV(TWINT) | _BV(TWEN); /* inicio de transmissao*/
80: while ((TWCR & _BV(TWINT)) == 0) ; /* espera interrupção */
81: switch ((twst = TW_STATUS))
82: {
83: case TW_MT_SLA_ACK:
84: break;
85:
86: case TW_MT_SLA_NACK: /*sem resposta manda reiniciar*/
87: goto restart;
88:
89: case TW_MT_ARB_LOST: /* re-arbitrate */
90: goto begin;
91:
92: default:
93: goto error;
94: }
95:
96: TWDR = eeaddr; /* coloca endereço*/
97: TWCR = _BV(TWINT) | _BV(TWEN); /* limpa interrupção */
98: while ((TWCR & _BV(TWINT)) == 0) ; /* espera para transmitir */
99: switch ((twst = TW_STATUS))
100: {
101: case TW_MT_DATA_ACK:
102: break;
103:
104: case TW_MT_DATA_NACK://se não receber dados aborta transmissao
105: goto quit;
106:
107: case TW_MT_ARB_LOST:
108: goto begin;
109:
110: default:
111: goto error;
112: }
113:
114: /*
115: * modo master recebe
116: */
117: TWCR = _BV(TWINT) | _BV(TWSTA) | _BV(TWEN); /*limpa interrupções*/
118: while ((TWCR & _BV(TWINT)) == 0) ; /* espera para inicia transmissaõ*/
119: switch ((twst = TW_STATUS))
120: {
121: case TW_START: /* OK,vai para proxima etapa*/
122: case TW_REP_START:
123: break;
124:
125: case TW_MT_ARB_LOST:
126: goto begin;
127:
128: default:
129: goto error;
130: }
131:
132: /* send SLA+R */
133: TWDR = sla | TW_READ;
134: TWCR = _BV(TWINT) | _BV(TWEN); /* limpa interrupções */
135: while ((TWCR & _BV(TWINT)) == 0) ; /*espera para enviar dados */
136: switch ((twst = TW_STATUS))
137: {
138: case TW_MR_SLA_ACK:
139: break;
140:
141: case TW_MR_SLA_NACK:
142: goto quit;
143:
144: case TW_MR_ARB_LOST:
145: goto begin;
146:
147: default:
148: goto error;
149: }
150:
151: for (twcr = _BV(TWINT) | _BV(TWEN) | _BV(TWEA) /* Note [13] */;
152: len > 0;
153: len--)
154: {
155: if (len == 1)
156: twcr = _BV(TWINT) | _BV(TWEN); /* envia NACK*/
157: TWCR = twcr; /* limpa interrupções */
158: while ((TWCR & _BV(TWINT)) == 0) ; /* espera para enviar dados */
159: switch ((twst = TW_STATUS))
160: {
161: case TW_MR_DATA_NACK:
162: len = 0; /* fim do loop houve falha na resposta*/
163: case TW_MR_DATA_ACK:
164: *buf++ = TWDR; //pega dados da memoria
165: rv++;
166: break;
167:
168: default:
169: goto error;
170: }
171: }
172: quit:
173:
174: TWCR = _BV(TWINT) | _BV(TWSTO) | _BV(TWEN); /* envia stop bit */
175:
176: return rv;
177: error:
178: rv = -1;
179: goto quit;
180: }
181:
182: ///////////////////////////////////função que escreve 1 pagina(8 bytes)///////////////
183:
184: int escreve_pagina(uint16_t endereco, int taman, char *dados)
185: {
186: uint8_t sla, n = 0;
187: int rv = 0;
188: uint16_t fim_ende;
189:
190: if (endereco + taman < (endereco | (PAGE_SIZE - 1)))//verifica se cabe na pagina atual
191: fim_ende = endereco + taman;
192: else
193: fim_ende = (endereco | (PAGE_SIZE - 1)) + 1;
194: taman = fim_ende - endereco;
195:
196: /* pega os bits altos da memoria */
197: sla = ENDE_ESCRITA | (((endereco >> 8) & 0x07) << 1);
198:
199: restart://rotina de reinicio
200: if (n++ >= 200)//numero de interações
201: return -1;
202: begin:
203: TWCR = _BV(TWINT) | _BV(TWSTA) | _BV(TWEN); /* limpa interrupções */
204: while ((TWCR & _BV(TWINT)) == 0) ; /* espera pra enviar*/
205: switch ((twst = TW_STATUS))
206: {
207: case TW_REP_START: /* OK, vai para proxima etapa */
208: case TW_START:
209: break;
210:
211: case TW_MT_ARB_LOST:
212: goto begin;
213:
214: default:
215: return -1; /* inicio de transmissão falhou*/
216: /* não fará uma condição de finalização*/
217: }
218:
219: /* send SLA+W */
220: TWDR = sla | TW_WRITE;//coloca os 8 bits alto do endereço
221: TWCR = _BV(TWINT) | _BV(TWEN); /* limpa interrupções para iniciar uma transmissão*/
222: while ((TWCR & _BV(TWINT)) == 0) ; /* espera terminar transmissão */
223: switch ((twst = TW_STATUS))
224: {
225: case TW_MT_SLA_ACK:
226: break;
227:
228: case TW_MT_SLA_NACK: /* ainda está escrevendo reinicia*/
229: goto restart;
230:
231: case TW_MT_ARB_LOST: /* tentar novamente*/
232: goto begin;
233:
234: default:
235: goto error; /* pede fim de transmissão */
236: }
237:
238: TWDR = endereco; /*copia os 8 bits baixo do endereço*/
239: TWCR = _BV(TWINT) | _BV(TWEN); /* limpa interrupções para iniciar uma transmissão*/
240: while ((TWCR & _BV(TWINT)) == 0) ; /* espera terminar transmissão */
241: switch ((twst = TW_STATUS))
242: {
243: case TW_MT_DATA_ACK:
244: break;
245:
246: case TW_MT_DATA_NACK:
247: goto quit;
248:
249: case TW_MT_ARB_LOST:
250: goto begin;
251:
252: default:
253: goto error; /* pede fim de transmissão */
254: }
255:
256: for (; taman > 0; taman--)
257: {
258: TWDR = *dados++;
259: TWCR = _BV(TWINT) | _BV(TWEN); /* limpa interrupções para iniciar uma transmissão*/
260: while ((TWCR & _BV(TWINT)) == 0) ; /* espera terminar transmissão */
261: switch ((twst = TW_STATUS))
262: {
263: case TW_MT_DATA_NACK:
264: goto error; /* indica que local de memoria é protegido */
265:
266: case TW_MT_DATA_ACK:
267: rv++;
268: break;
269:
270: default:
271: goto error;
272: }
273: }
274: quit: ///rotina para sair
275: TWCR = _BV(TWINT) | _BV(TWSTO) | _BV(TWEN); /* finaliza transmissão*/
276:
277: return rv;//retorna o numero de bytes escrito
278:
279: error:
280: rv = -1;
281: goto quit;
282: }
283: ////////////////////////////escreve uma frase //////////////////////////////////////////////////////////////////////////
284: ///////repete escrita até que todos os caracteres sejam escritos ou a função retorne um erro
285: int escreve_frase(uint16_t ende, int tamanho, char *frase)//endereço inicial ,quantidade de caracteres , string(frase)
286: {
287: int ret_valor, total=0;
288:
289: do
290: {
291: ret_valor = escreve_pagina(ende , tamanho, frase);
292: if (ret_valor == -1)
293: {
294: return -1;///se erro retorna -1
295: }
296: ende += ret_valor;
297: tamanho -= ret_valor;
298: frase += ret_valor;
299: total += ret_valor;
300: }while (tamanho > 0);
301:
302: return total;//retorna a quantidade de caracteres escritos
303: }
304:
305:
306: int main(void)
307: {
308: int valor_retornado;
309: uint8_t frase_lida[16];
310: DDRD = 0XFF;
311: PORTD = 0X00;
312:
313: I2C_inicializar();
314: valor_retornado = escreve_frase(450,50, "TESTANDO ENVIO DE DADOS");// local a ser escrito(endereço inicial) /tamanho da frase(numero de caracteres/ frase (string)
315: valor_retornado = escreve_frase(23,1,"X");//escreve um caracter
316: if(valor_retornado<0)
317: {
318: //aqui deve colocar o que fazer se tiver uma falha de escrita
319: }
320: else
321: {
322: //aqui deve colocar o que fazer se não tiver nenhuma falha de escrita
323:
324: }
325: //para ler bytes da memoria faça
326: valor_retornado = ler_bytes (1, 15, frase_lida);//local inicial de leitura / quantidade de caracteres a ler / bytes lido
327: if(valor_retornado<0)
328: {
329: //aqui deve colocar o que fazer se tiver uma falha de leitura
330: PORTD = 0X0F;
331: }
332: else
333: {
334: //aqui deve colocar o que fazer se não tiver nenhuma falha de leitura
335: PORTD = 0X05;
336:
337: }
338:
339: }
Muito bom, ajudou bastante no projeto que estou trabalhando.
ResponderExcluirOlá, primeiramente quero agradecer ao criado do blog, pelo, desempenho e dedicação no compartilhamento de conhecimento. Assim, sim, seremos um país melhor(Fica a dica para todos).
ResponderExcluirMinha dúvida é o seguinte: no seu esquema você está usando as portas 28 e 27, tem como eu usar outras, ou é fixa essas portas?(Desculpe minha ignorância, sou novato).\
Obrigado.
Max
Sim é fixa pois para o I2C funcionar é preciso de um hardware especifico(registrador de deslocamento), mas talvez existam outras formas,mas como o dispositivo já com tudo pronto para estes pinos então "por que reinventar a roda?" obrigado por visitar o site, e sempre que puder ou quiser compartilhar algo é só falar,que dai posto seu arquivo e coloco seu nome.
ExcluirOpa amigo, blz.
ResponderExcluirCara, sou leigo em AVR, porem gostaria de gravar algumas informações no uC, entretando não entendi a diferença entre IC2 e EPROMM, ou é necessário IC2 para gravar na EPROMM?
Grato.
neste tópico é abordado a comunicação i2C para gravar neste tipo de memoria externa(não tem nada a ver com a eeprom do microcontrolador),em outras postagens aqui mesmo no blog tem um exemplo de gravar na eeprom do avr,vê isso:
Excluir////////////////////////////////////////////////////////////////////////funçoes da eeprom
unsigned char ler_eeprom(int ende)
{
/* espera completar alguma escrita */
while(EECR & (1<<EEWE));
EEAR = ende;
//pega dados que estão na posição 5 da eeprom
/* inicia leitura da eeprom */
EECR |= (1<<EERE);
/* retorna dados da memoria */
return EEDR;
}
////////////////////////////////////////////////////////////////////////
void escr_eeprom(int ende,char valor)
{
cli(); //desabilita interrupções
/* espera completar alguma escrita */
while(EECR & (1<<EEWE)) ;
/* lê o endereço 10 */
EEAR = ende; // endereço
EEDR = valor;// dados
/*habilita escrita de eeprom */
EECR |= (1<<EEMWE);
/*inicia escrita na eeprom, escreve 1 em EEMWE*/
EECR |= (1<<EEWE);
sei();//Habilita interrupções
}
para usar faz se assim:
escr_eeprom(5,'P');//escreve na posição 5 o caracter 'P'
variavel = ler_eeprom(5);// lê a memoria no endereço 5 da eeprom
Este comentário foi removido pelo autor.
ResponderExcluir