Página 1 de 1

i2c eeprom

MensagemEnviado: 26 Out 2006 17:34
por edusoppa
Ola pessoal,
Será que alguem tem um exemplo da utilizacao de uma eeprom por i2c em c keil...

Obrigado.

Eduardo.

MensagemEnviado: 27 Out 2006 06:17
por ftegon
Ola!

Como vovê não especificou qual eeprom serial, segue abaixo um exemplo.

Ate+

cpp code
/*********************************************************************/
/* PROGRAMA I2C.C Fabio Tegon 13/12/1999 */
/* */
/* Funcao: Ler/Escrever eeprom serial 24C04/08 */
/*********************************************************************/
/* Keil C51 , PLACA SBC80C535, 24C04 ATMEL */
/*********************************************************************/
/* Baseado em rotinas de Dmitry Obukhov, dso@usa.net */
/*********************************************************************/
#define SBC80535 1
#if SBC80535
#include <reg515.h>
#else
#include <at892051.h>
#endif

#include <stdlib.h>
#include <stdio.h>
#include <intrins.h>

#if SBC80535
sbit SCL = P5^0; /* serial clock */
sbit SDA = P5^1; /* serial endereco/dado */
#else
sbit SCL = P1^1;
sbit SDA = P1^0;
#endif

/* 0x02 eeprom 24C04 , 0x0E eeprom 24C08 */
#define PG 0x02


void delay5(void)
{
_nop_(); /* modificado para Keil C51 */
_nop_();
_nop_();
_nop_();
_nop_();
}
/*
This function is hardware depended (CPU speed)
For fast processors you can define a loop
This concrete function written for I8051 on 12MHz (NOP=1uS)
*/


void i2c_start_tx(void)
{
SCL=1;
SDA=1;
delay5();
SDA=0;
delay5();
SCL=0;
}

void i2c_send_ack(void)
{
SDA=1;
SCL=1;
delay5();
SCL=0;
}

unsigned char i2c_read_char(void)
{
unsigned char res=0;
unsigned char cnt;
for ( cnt=0;cnt<8;cnt++ )
{
SDA=1;
SCL=1;
delay5();
res<<=1;
if (SDA) { res |= 0x01; }
SCL=0;
delay5();
}
return res;
}


bit i2c_check_ack(void)
{
SDA=1;
SCL=1;
delay5();
if (SDA)
{
SCL=0;
return 1;
}
SCL=0;
return 0;
}


void i2c_write_char(unsigned char d)
{
unsigned char i;
for (i=0;i<8;i++)
{
SDA=(bit)(d & 0x80);
SCL=1;
delay5();
SCL=0;
d = d << 1;
}
i2c_send_ack();
}

void i2c_stop_tx(void)
{
SDA=0;
delay5();
SCL=1;
delay5();
SDA=1;
}

/* The following two functions are an entry points
* for the external calls */

void WR24C04(unsigned int index,unsigned char content)
{
unsigned char res;
res=(((unsigned char)(index>>7))& PG) | 0xA0;
i2c_start_tx();
//Send control word + page NUM
i2c_write_char(res);
i2c_write_char((unsigned char)(index&0x00FF));
i2c_write_char(content);
i2c_stop_tx();
}

unsigned char RD24C04(unsigned int index)
{
unsigned char res;
//Send control word + page NUM
res=(((unsigned char)(index>>7))& PG) | 0xA0;
i2c_start_tx();
i2c_write_char(res);
i2c_write_char((unsigned char)(index&0x00FF));
i2c_start_tx();
i2c_write_char(res+1);
res=i2c_read_char();
i2c_stop_tx();
return res;
}

void inic_serial()
{
#if SBC80535
EAL = 0;
#else
EA = 0;
#endif

PCON = PCON | 0x40; /* reseta bit SMOD no registro PCON */
/* bit SMOD = 0 sem dobrar a velocidade na serial */
SCON = 0x52; /* canal serial no modo 1 8bits 1stop sem paridade*/
TMOD = 0x20; /* timer 1, no modo 2, 8bits com auto-reload */
TH1 = 0xFD; /* setado para velocidade de 9600 bps */
#if SBC80535
EAL = 1;
#else
EA = 1; /* habilita escolha de interrupcoes */
#endif
TR1 = 1; /* liga timer 1 para clock do canal serial */
}

main() {

int i,endereco;
unsigned char dado;
inic_serial();



while(1) {
dado = 0xbb;
endereco = 100;

WR24C04(endereco,dado);
for(i=0;i < 10000; i++) {
P4 = 0x00;
delay5();
delay5();
delay5();
P4 = 0xFF;
delay5();
delay5();
delay5();
}

dado = 0;
dado = RD24C04(endereco);
printf("valor gravado %d\n",(int)dado);


};
}

MensagemEnviado: 27 Out 2006 14:08
por edusoppa
Ola amigo,
Olha eu ate consegui simular no proteus o codigo que eu fiz, mas quando eu gravo no 89s52 e tento ele soh mostra FF no port que eu estou mostrando a informacao.
Estou passando o meu codigo para voce ver se podeme ajudar. obrigado. ah eu estou usando uma 24c64..., mas no projeto final usarei uma 24c01.
cpp code
/***********************************
I2c.h
***********************************/

// I2C.H

// esta biblioteca é para o i2c generico, para todos os dispositivos
// que usem este tipo de protocolo!
// qualquer duvida verificar o progama at24c04.c

#include <intrins.h>

#define SCL P1_5 // se estes pinos não estiverem definidos no
// progama principal serão definidos este pinos
// como padrão

#define SDA P1_6


/* ******************************************************** */
/* ******************************************************** */
void i2c_delay(void)
{
_nop_ ();
_nop_ ();
_nop_ ();
_nop_ ();
_nop_ ();
_nop_ ();
_nop_ ();
_nop_ ();
_nop_ ();
_nop_ ();

}

void i2c_start(void)
{
/* Force defined state of SCL and SDA*/
SCL = 1; /* Release SCL */
SDA = 1; /* Release SDA */
i2c_delay(); /* Force 5µs-delay */

/* Generate START condition */
SDA = 0;
i2c_delay(); /* Force 5µs-delay */
SCL = 0;


}

void i2c_stop(void)
{

SDA = 0;
i2c_delay();
SCL = 1;
i2c_delay();
SDA = 1;
}
/*
void i2c_ack(void) // reconhecimento do mestre
{
// Generate ACK
SDA = 0;
SCL = 1; // Release SCL
while(SCL == 0); // Synchronize clock
i2c_delay(); // Force 5µs-delay
SCL = 0; // Force a clock cycle
}

void i2c_nack(void) // naõ reconhecimento do mestre
{
// Generate NACK
SDA = 1; // Release SDA
SCL = 1; // Release SCL
while(SCL == 0); // Synchronize clock
i2c_delay(); // Force 5µs-delay
SCL = 0; // Force a clock cycle
} */

unsigned char i2c_check(void) // ler o reconhecimento do escravo
{
unsigned char vbit=0;
SDA = 1; /* Release SDA */
i2c_delay();
SCL = 1; /* Release SCL */
i2c_delay(); /* Force 5µs-delay */
if (SDA) /* SDA is high */
{
vbit=1;
i2c_delay();
SCL = 0; /* Force a clock cycle */
i2c_delay();
return(vbit); /* No acknowledge from Slave */
}
else
{
vbit=0;
i2c_delay();
SCL = 0;
i2c_delay();
return(vbit); /* Acknowledge from Slave */
}
}

unsigned i2c_write(unsigned char value)
{
unsigned char counter = 0,reconhece; /* Bitcounter */

for ( counter = 0; counter < 8; counter++ )
{
SDA = ((value&128) >> 7); /* Set SDA to value of MSB */
i2c_delay();
SCL = 1; /* Release SCL */
i2c_delay(); /* Force 5µs-delay */
SCL = 0; /* Force a clock cycle */
value <<= 1; /* Prepare next bit for transmission */
}
reconhece=i2c_check();
return(reconhece);
}

unsigned char i2c_read(void)
{
unsigned char result = 0; /* Returnvalue with read I2C byte */
unsigned char counter = 0; /* Bitcounter */


for ( counter = 0; counter < 8; counter++ )
{
SDA = 1; /* Release SDA */
SCL = 1; /* Release SCL */
while(SCL == 0); /* Synchronize clock */
i2c_delay(); /* Force 5µs-delay */

result <<= 1; /* Shift left the result */

if (SDA) result |= 0x01; /* Set actual SDA state to LSB */
SCL = 0; /* Force a clock cycle */
i2c_delay(); /* Force 5µs-delay */
}

/* ACK or NACK from MASTER must be generated outside this routine */
return(result);
}


/********************************
Modulo.c
*******************************/

#include<regx52.h>
#include<i2c.h>

void escreve_memoria(int endereco,int dado)
{
bit erro =0;
i2c_start();
erro=i2c_write(0xA0);//comando para setar endereco
erro=i2c_write(endereco);//endereco
erro=i2c_write(dado);//dado
if(erro)
{
i2c_stop();
P3_7=1;
}
i2c_stop();
}

int le_memoria(int endereco)
{
int dado;
bit erro = 0;
i2c_start();
erro=i2c_write(0xA0);//comando para setar endereco
erro=i2c_write(endereco);//endereco
i2c_start();
erro=i2c_write(0xA1);//comando para ler dado da memoria.
if(erro)
{
i2c_stop();
P3_7=1;
}
dado=(int)i2c_read();
i2c_stop();
return(dado);
}

void pausa()
{
int i,j;
for(i=0;i<10000;i++)
for(j=0;j<50;j++);
}
void main()
{
int endereco,i;

bit erro;
P1=0;
P3=0;
P2=1;
endereco=1;
P1_7=0;
P2=0;
erro=0;
while(1)
{
if(P1_7 == 1)
{
while(P1_7==1);
//escrever informacao;
for(i=0;i<0x10;i++)
{
escreve_memoria(i,i);
pausa();
P1_1=~P1_1;
}
//ler informacao;
P2=0;
pausa();
pausa();
P2 = le_memoria(0x04);
pausa();
P1_1=~P1_1;
}
}
}

MensagemEnviado: 27 Out 2006 19:04
por ftegon
Ola!

Como você não especificou qual era a eeprom serial , postei um
código para 24C04 ou 24C08, já utilizo o mesmo há mais de 6 anos.

Quanto a usar o PROTEUS eu tenho pessimas experiencias com o mesmo
principalmente com displays gLCD (T6963C).

Para mim é um software em desenvolvimento (de grande futuro) mas
e ainda muito instavel e pouco confiavel.

Ao inves do PROTEUS , prefiro testar o hardware direto,
ou num protoboard ou numa placa de prototipos.

Se você tiver um analizador lógico , você podera monitorar as
formas de onda nos pinos da eeprom , isso ajuda muito.

O analisador pode ser um desses que utilizam a tela do PC para
display, do tipo bitscope (http://wwww.bitscope.com )pois o clock é relativamente baixo.

Não tenho nada para 24C01, utilizo somente 24C04 para cima
pois o custo de uma 24C01 é praticamente o mesmo
de uma 24C04, (que tem capacidade maior).

Para 24C32_64_128_256_512 as rotinas estão no link

http://www.taylorriver.com/content/view/130/2/#intro

O software é em C para o compilador da RAISONACE, mas
é compativel com o Keil.

OBS: Se você olhar detalhadamente os datasheets há diferenças
um tanto quanto significativas entre uma 24C01 e uma 24C64.

Se você for usar uma 24C01, desenvolva e teste o teu software com
uma 24C01 e não com uma 24C64.


Ate+

Fabio Tegon

to doido, to doido, to doido!

MensagemEnviado: 25 Nov 2006 13:01
por eyegold
Olá, Gostaria de saber se vc tem rotina em asm para a 24lc512, pois ja to doido, ja quebrei a cabeça e não consegui botar essa danada pra rodar.

MensagemEnviado: 25 Nov 2006 14:05
por ftegon
Ola!

Em asm para 24LC512 infelizmente não tenho.

Mas no site da atmel tem uma app. note chamada Interfacing AT24CXX serial eeproms with AT89CX051 microcontrolers, juntamente com o código fonte.

O fonte é generico (esta em asm) mas segundo a app. note tambem serve para a AT24C512 e AT24C512B.



a++

Fabio Tegon

MensagemEnviado: 25 Nov 2006 21:45
por Renie
Olá pessoALL!

Ha um tempo atrás (acho que já vai fazer aniversário, se não for o segundo!) disponibilizei no meu site um pequeno tutorial sobre I2C,
não tem rotinas nem exemplos, mas....

tem a noção, como funciona, se isso não ajuda, então não precisam de
ajuda, querem pronto! Acho que no ASM51, só conseguirá sem esforço de
um participante novato que ainda não leu mais que 10 post's!