TODOPIC
Microcontroladores PIC => Lenguaje C para microcontroladores PIC => Mensaje iniciado por: mauro_picotto_dj en 24 de Mayo de 2005, 10:50:00
-
Hola amigos del foro tengo un problema en un programa de escritura y lectura de una memoria EEPROM por medio de I2C. Estoy trabajando en mplab con c18. el algoritmo es el siguiente:
archivo .h:
#ifndef __EEI2CPIC_H
#define __EEI2CPIC_H
#define Page_Lenght 8
#define EE_CMD 0xA4
#define PARAM_SCLASS auto
#define MEM_MODEL far
void Initialize_I2C_Master(void);
//unsigned char EEByteWrite( unsigned char control, unsigned char address, unsigned char data );
unsigned int EERandomRead( unsigned char control, unsigned char address );
void OpenI2C( unsigned char sync_mode, unsigned char slew );
void I2C_Done(void);
#endif
El archivo .c es:
#include <p18f452.h>
#include <i2c.h>
#include "EEi2cpic.h"
unsigned int read_value;
void main(void)
{
//inicialización de puertos y modo master del pic
Initialize_I2C_Master();
TRISD=0x00;
//EEByteWrite(0xA0, 0x01, 0xAB);
read_value=EERandomRead(0xA0,0x01);
for(;
{
PORTD=read_value;
}
}
/*unsigned char EEByteWrite( unsigned char control, unsigned char address, unsigned char data )
{
IdleI2C(); // ensure module is idle
StartI2C(); // initiate START condition
while ( SSPCON2bits.SEN ); // wait until start condition is over
if ( PIR2bits.BCLIF ) // test for bus collision
{
return ( -1 ); // return with Bus Collision error
}
else // start condition successful
{
if ( WriteI2C( control ) ) // write byte - R/W bit should be 0
{
return ( -3 ); // set error for write collision
}
IdleI2C(); // ensure module is idle
if ( !SSPCON2bits.ACKSTAT ) // test for ACK condition received
{
if ( WriteI2C( address ) ) // write word address for EEPROM
{
return ( -3 ); // set error for write collision
}
IdleI2C(); // ensure module is idle
if ( !SSPCON2bits.ACKSTAT ) // test for ACK condition received
{
if ( WriteI2C( data ) ) // data byte for EEPROM
{
return ( -3 ); // set error for write collision
}
}
else
{
return ( -2 ); // return with Not Ack error condition
}
}
else
{
return ( -2 ); // return with Not Ack error condition
}
}
IdleI2C(); // ensure module is idle
StopI2C(); // send STOP condition
while ( SSPCON2bits.PEN ); // wait until stop condition is over
if ( PIR2bits.BCLIF ) // test for bus collision
{
return ( -1 ); // return with Bus Collision error
}
return ( 0 ); // return with no error
}*/
unsigned int EERandomRead( unsigned char control, unsigned char address )
{
SSPCON2bits.SEN=1;
I2C_Done();
while ( SSPCON2bits.SEN ); // wait until start condition is over
WriteI2C( control ); // write 1 byte
IdleI2C(); // ensure module is idle
while(SSPCON2bits.ACKSTAT); // test for ACK condition, if received
WriteI2C( address ); // WRITE word address for EEPROM
IdleI2C(); // ensure module is idle
while(SSPCON2bits.ACKSTAT); // test for ACK condition, if received
StopI2C(); // send STOP condition
while ( SSPCON2bits.PEN ); // wait until stop condition is over
SSPCON2bits.SEN=1;
I2C_Done();
while ( SSPCON2bits.SEN ); // wait until start condition is over
WriteI2C( control+1 ); // write 1 byte - R/W bit should be 1
IdleI2C(); // ensure module is idle
while(SSPCON2bits.ACKSTAT);// test for ACK condition, if received
SSPCON2bits.RCEN = 1; // enable master for 1 byte reception
while ( SSPCON2bits.RCEN ); // check that receive sequence is over
NotAckI2C(); // send ACK condition
while ( SSPCON2bits.ACKEN ); // wait until ACK sequence is over
StopI2C(); // send STOP condition
while ( SSPCON2bits.PEN ); // wait until stop condition is over
return ( (unsigned int) SSPBUF ); // return with data
}
void OpenI2C( unsigned char sync_mode, unsigned char slew )
{
SSPSTAT &= 0x3F; // power on state
SSPCON1 = 0x00; // power on state
SSPCON2 = 0x00; // power on state
SSPCON1 |= sync_mode; // select serial mode
SSPSTAT |= slew; // slew rate on/off
#if defined(__18F2455) || defined(__18F2550) ||
defined(__18F4455) || defined(__18F4550)
DDRBbits.RB1 = 1; // Set SCL (PORTB,1) pin to input
DDRBbits.RB0 = 1; // Set SDA (PORTB,0) pin to input
#else
DDRCbits.RC3 = 1; // Set SCL (PORTC,3) pin to input
DDRCbits.RC4 = 1; // Set SDA (PORTC,4) pin to input
#endif
SSPCON1 |= SSPENB; // enable synchronous serial port
}
//Se asginará polling a la respuesta de la EEPROM
//ACK = regreso
//ACK = 1 envia reinicio y se revisa el ciclo
/*void EEPROM_ACK(unsigned char ctrl)
{
unsigned char i;
IdleI2C();
for (i=0;i<240;i++);
StartI2C();
I2C_Done();
WriteI2C(ctrl);
I2C_Done();
while(SSPCON2bits.ACKSTAT);
{
for (i=0;i<250;i++);
RestartI2C();
while ( SSPCON2bits.RSEN );
WriteI2C( ctrl );
IdleI2C();
}
StopI2C();
I2C_Done();
}*/
// Observar que se completó la acción I2C
void I2C_Done(void)
{
while(!PIR1bits.SSPIF);
PIR1bits.SSPIF=0;
}
//Inicialización MODO MASTER con 7 bits de dirección
//velocidad del reloj:100khz a 10MHZ
void Initialize_I2C_Master(void)
{
OpenI2C(MASTER,SLEW_ON);
SSPADD=0x19;
}
Estoy haciendo lo siguiente: primero utilizo la rutina de escritura compilo y escribo la memoria con AB en la dirección 0x01. Utilizo el pic 18f452 y la memoria 24LC04B y simulo en proteus. Luego puedo leer el dato compilando solamente la rutina de lectura. ¿Como podría modificar el código para que me escriba el dato y me lea después lo que escribi? Creo que el problema está en la trama o datos que van en el bus y reinician la transmisión de la memoria 24LC04B.