TODOPIC

Microcontroladores PIC => Lenguaje C para microcontroladores PIC => Mensaje iniciado por: gonzalonalbandian en 01 de Julio de 2010, 12:42:41

Título: Ayuda con I2C para RTC ds1307 (Hi-Tech C18)
Publicado por: gonzalonalbandian en 01 de Julio de 2010, 12:42:41
Hola gente, como andan? Bueno les cuento que estoy intentando acoplar este RTC a un pic 18f452 para mostrar la hora en un lcd. El problema es que no termino de entender bien la rutina I2C que tiene mi compilador de ejemplo. Dcho sea de paso, es Hi-Tech C18.

El RTC ds1307 almacena los segundos, minutos, horas, dias, etc...cada uno en un registro de 8 bits. Cuando comienzo con la lectura, el RTC envia el primer dato (los segundos) y por cada lectura que haga, envia el proximo registro o al menos eso creo que hace.

Esto me complica la lectura. Yo desearia por especificar que registro leer del RTC para asi asignar a la lectura de los segundos a su direccion en memoria en el RTC.

Bueno espero haberme explicado mas o menos. Cualquier ejemplo de i2c en Hi-Tech es bienvenido.

Abajo les pongo el codigo que tengo por ahora.
PD: no se bien para que sirve I2C_MORE y I2C_LAST

Código: [Seleccionar]
void reloj (void)
{


char seg1[2], min1[2], hrs1[2], dia1[2], mes1[2], ano1[4];
unsigned int seg, min, hrs, dia, mes, ano;


#ifdef I2C_MODULE
SSPMode(MASTER_MODE);
SSPEN = 1;
CKP = 1;
#else
SCL_DIR = I2C_OUTPUT;
SDA_DIR = I2C_OUTPUT;
SDA = 0;
SCL = 0;
#endif



i2c_ReadFrom(0xD1);

seg = i2c_GetByte(I2C_MORE);
min = i2c_GetByte(I2C_MORE);
hrs = i2c_GetByte(I2C_MORE);
dia = i2c_GetByte(I2C_MORE);
i2c_GetByte(I2C_MORE); //no se que es este (date)
mes = i2c_GetByte(I2C_MORE);
ano = i2c_GetByte(I2C_LAST);
i2c_Stop();


sprintf(seg1,"%2x", seg);
//~ sprintf(min1,"%2x", min); Cuando dejo todos estos sin comentar, en la simulacion no hay resultados
//~ sprintf(hrs1,"%2x", hrs);
//~ sprintf(dia1,"%2x", dia);
//~ sprintf(mes1,"%2x", mes);
//~ sprintf(ano1,"%4x", ano);


lcd_puts(seg1);
DelayS(1);
//lcd_puts(min1);
//~ lcd_puts(hrs1);
//~ lcd_puts(dia1);
//~ lcd_puts(mes1);
//~ lcd_puts(ano1);
DelayS(1);

lcd_clear();




}

i2c.c

Código: [Seleccionar]
/*
 * Get a byte from the slave and acknowledges the transfer
 *   - returns true on I2C_ERROR or byte
 */

int
i2c_GetByte(unsigned char more)
{
int byte;

if((byte = i2c_ReadByte()) == I2C_ERROR)
return I2C_ERROR;

i2c_SendAcknowledge(more);

return byte;
}

/*
 * Send an array of bytes to the slave and acknowledges the transfer
 *   - returns number of bytes not successfully transmitted
 */

int
i2c_PutString(const unsigned char *str, unsigned char length)
{
signed char error;

while(length)
{
if((error = i2c_PutByte(*str)) == I2C_ERROR)
return -(int)length; /* bus error */
else
if(error)
return (int)length; /* non acknowledge */
str++;
length--;
}

return FALSE; /* everything OK */
}

/*
 * Reads number bytes from the slave, stores them at str and acknowledges the transfer
 *   - returns number of bytes not successfully read in
 */

unsigned char
i2c_GetString(unsigned char *str, unsigned char number)
{
int byte;

while(number)
{
if((byte = i2c_GetByte(number-1)) == I2C_ERROR)
return number; /* bus error */
else
*str = (unsigned char)byte;
str++;
number--;
}

return FALSE; /* everything OK */
}

/*
 * Opens communication with a device at address. mode
 * indicates I2C_READ or I2C_WRITE.
 *   - returns TRUE if address is not acknowledged
 */

unsigned char
i2c_Open(unsigned char address, unsigned char mode)
{
i2c_Start();
i2c_SendAddress(address, mode);
        if(i2c_ReadAcknowledge())
return TRUE;

return FALSE;
}

/*
 * wait for the clock line to be released by slow slaves
 *   - returns TRUE if SCL was not released after the
 *     time out period.
 *   - returns FALSE if and when SCL released
 */

unsigned char
i2c_WaitForSCL(void)
{
/* SCL_DIR should be input here */

if(!SCL)
{
DelayUs(I2C_TM_SCL_TMO);
/* if the clock is still low -> bus error */
if(!SCL)
return TRUE;
}
return FALSE;
}
void
i2c_Free()
{
unsigned char ucI;

SDA_DIR=I2C_INPUT;
for(ucI=0;ucI!=9;ucI++)
{
                SCL_HIGH();
DelayUs(5);
                SCL_LOW();
DelayUs(5);
}
}

unsigned char i2c_read(unsigned char ucAdr)
{
unsigned char ucDat;

if (i2c_ReadFrom(ucAdr)==0)
{
ucDat=i2c_GetByte(I2C_MORE);
i2c_Stop();

}

return(ucDat);
}


i2c.h

Código: [Seleccionar]
#ifndef _I2C_H_
#define _I2C_H_

/*
 * SDA (data) and SCL (clock) bits
 *
 * Special note!!!
 *
 * If the clock and data lines are in the same port, you will need
 * to beware of the Read/Modify/Write issue in the PIC - since
 * a bit set or clear on any one bit in a port will read and write
 * back all other bits, any bits configured as input which
 */


/* Uncomment the next line to use the PIC's SSP Module*/
#define I2C_MODULE 1

#ifdef I2C_MODULE
/* I2C module uses PORT C */
#define SCL             RC3             /* clock on port C bit 2 */
#define SCL_DIR         TRISC3
#define SDA     RC4                     /* data on port C bit 1 */
#define SDA_DIR         TRISC4
#define I2CTRIS TRISC
#define MASTER_MODE     0B1011          /* I2C firmware controlled Master Mode (slave idle) */
#define SSPMode(val)   SSPCON1 &=0xF0; SSPCON1 |=(val & 0xf)

#else
/* Change port as required - defaults to port b */
#define SCL RB2 /* clock on port B bit 2 */
#define SCL_DIR TRISB2

#define SDA             RB1             /* data on port B bit 1 */
#define SDA_DIR TRISB1
#define I2CTRIS TRISB

#endif

#define M_SDA_INP 0x02
#define M_SDA_OUT   0xFD
#define M_SCL_INP   0x04
#define M_SCL_OUT 0xFB

#define I2C_INPUT 1 /* data direction input */
#define I2C_OUTPUT 0 /* data direction output */

#define I2C_READ 0x01 /* read bit used with address */
#define I2C_WRITE 0x00 /* write bit used with address */

#define FALSE 0
#define TRUE !FALSE

#define I2C_ERROR (-1)
#define I2C_LAST FALSE /* SendAck: no more bytes to send */
#define I2C_MORE TRUE /* SendAck: more bytes to send */

#define i2c_Start() i2c_Restart()
#define i2c_WriteTo(address) i2c_Open((address), I2C_WRITE)
#define i2c_ReadFrom(address) i2c_Open((address), I2C_READ)

#ifdef I2C_MODULE
#define SCL_HIGH() SCL_DIR = I2C_INPUT
#define SCL_LOW()  SCL_DIR = I2C_OUTPUT
#define SDA_HIGH() SDA_DIR = I2C_INPUT
#define SDA_LOW()  SDA_DIR = I2C_OUTPUT
#else
#define SCL_HIGH() SCL = 1; SCL_DIR = I2C_OUTPUT
#define SCL_LOW()  SCL = 0; SCL_DIR = I2C_OUTPUT
#define SDA_HIGH() SDA = 1; SDA_DIR = I2C_OUTPUT
#define SDA_LOW()  SDA = 0; SDA_DIR = I2C_OUTPUT
#endif

/*
 * Timings for the i2c bus. Times are rounded up to the nearest
 * micro second.
 */

#define I2C_TM_BUS_FREE 5
#define I2C_TM_START_SU 5
#define I2C_TM_START_HD 4
#define I2C_TM_SCL_LOW 5
#define I2C_TM_SCL_HIGH 4
#define I2C_TM_DATA_SU 1
#define I2C_TM_DATA_HD          0
#define I2C_TM_SCL_TO_DATA 4 /* SCL low to data valid */
#define I2C_TM_STOP_SU 4
#define I2C_TM_SCL_TMO 10 /* clock time out */

extern signed char i2c_ReadAcknowledge(void);
extern unsigned char i2c_SendAddress(unsigned char, unsigned char);
extern unsigned char i2c_SendByte(unsigned char);
extern int i2c_ReadByte(void);
extern void i2c_Restart(void);
extern void i2c_Stop(void);
extern void i2c_SendAcknowledge(unsigned char);
extern signed char i2c_PutByte(unsigned char);
extern int i2c_GetByte(unsigned char);
extern unsigned char i2c_Open(unsigned char, unsigned char);
extern unsigned char i2c_GetString(unsigned char *, unsigned char);
extern int i2c_PutString(const unsigned char *, unsigned char);
extern unsigned char i2c_WaitForSCL(void);
extern void i2c_Free();
#endif /* _I2C_H_ */