jueves, 25 de octubre de 2012

sdcc easypic2 i2c

i2c.h
#include <pic16f877a.h>
/*
****************************************
*    FUNCIONES DE BAJO NIVEL DEL I2C   * 
****************************************
*/

// Envia Ack
// SDA = 0 
void i2c_SendAck()
{
  ACKDT = 0;  // Establece un ACK
  ACKEN = 1;  // Lo envia
}


// Envia Nack para finalizar la recepecion
// SDA = 1
void i2c_SendNack()
{
  ACKDT = 1;  // Establece un NACK
  ACKEN = 1;  // Lo envia
}


// verifica ACK
// Mira si en el 9 pulso de reloj (SCL en estado a 1) la señal SDA está a 0
unsigned char i2c_CheckACK()
{
  if ( ACKSTAT == 0 ) {
    return 0;   // correcto (lo he recibido )
  } else { 
    return 1; // incorrecto (no lo he recibido)
  }
}


// Envia la condicion de STOP
// Libera el BUS I2C, SDA y SCL a nivel alto
// SDA=1 cuando SCL=1. 
void i2c_SendStop() {
  PEN = 1;    // send stop bit
}


// Envia la condicion de START
// Inicializa el Bus I2C, SCL y SDA a nivel bajo
// Estando SCL=1 pone SDA=0, luego pone SCL=0
void i2c_SendStart()
{
  SEN = 1;     // send start bit
}

// Espera a que el I2C reciba algun evento
void i2c_WaitMSSP() 
{
  while (SSPIF == 0);  // Espera evento
  SSPIF=0;             // Limpia FLAG
}


// Espera a que el I2C reciba algun evento
unsigned char i2c_MSSP_Status()
{
  return SSPIF; 
}




// Repeated start from master
// Queremos transmitir más datos pero sin dejar el BUS, es decir
// sin mandar previamente un STOP. O por ejemplo si queremos mandar un STOP y seguidamente un
// START para que ningún otro dispositivo ocupe la línea usaremos esto.
void i2c_SendRStart() {
  RSEN=1;
}


// Leer Byte por el I2C
// Devuelve byte leido
unsigned char i2c_ReadByte() {
  RCEN=1;        // Activar el RCEN

  i2c_WaitMSSP();
  return SSPBUF;
}




// Envia un Dato por el Bus I2C
// Entrada el dato a enviar
void i2c_SendByte(unsigned char dato) {
  SSPBUF=dato;
}



// Fallo en el I2C
void i2c_fail() {
  i2c_SendStop();
  i2c_WaitMSSP();
}



/*
**************************************
*   FUNCIONES DE ALTO NIVEL del I2C  *
**************************************
*/


/* Configurar I2C
  Configuramos el I2C como Master
  y a una velocidad de 1Mhz
*/

void i2c_configure()
{
  // configuramos SCL y SDA como pines de entrada
  TRISC=TRISC | 0x18;  // 1 entrada / 0 salida  
  
  SSPSTAT=0x0;  
  SSPSTAT=SSPSTAT | 0x80;  // SMP=1 Slew rate disable for 100Kh  @@@
                           // CKE=0 (modo maestro I2C) y UA=0 (7 bits)

  SSPCON=0x08;       // I2C master mode (uso la formula del reloj con SSPAD)  
  SSPCON=SSPCON | 0x20;  // enable I2C  SSPEN=1

  SSPCON2=0x00;   // no se usa por ahora
  // velocidad = FOSC / ( 4 * (sspad + 1) )
  // Fosc=20Mhz

  SSPADD=49;  // 49->100Khz  @@@
  //SSPADD=24; // 24 -> 400khz   @@@

  // Limpia Flags de eventos
  SSPIF=0;  //Limpia flag de eventos SSP 
}



// manda un byte al dispositivo i2c
unsigned char i2c_write_byte(unsigned char address, unsigned char reg,
                             unsigned char dato)
{
  // 1º Envia Bit de Start
  i2c_SendStart();
  i2c_WaitMSSP();  

  // 2º Envio la direccion del modulo
  i2c_SendByte(address);
  i2c_WaitMSSP();
  if (i2c_CheckACK()!=0) {
    i2c_fail();
    return 0;  // Ha habido un error, salgo de la rutina
  }

  // 3º mando el registro sobre el que voy a actuar
  i2c_SendByte(reg);
  i2c_WaitMSSP(); 
  if (i2c_CheckACK()!=0) {
    i2c_fail();
    return 0;   // Ha habido un error, salgo de la rutina
  }

  // 4º mando el dato 
  i2c_SendByte(dato); 
  i2c_WaitMSSP();
  if (i2c_CheckACK()!=0) {
    i2c_fail();
    return 0;    // Ha habido un error, salgo de la rutina
  }

  // 6º termino el envio
  i2c_SendStop();
  i2c_WaitMSSP();

  return 1;  // Byte mandado correctamente
}


// Lee 1 byte1  del dispositivo i2c
// El dato leido lo devuelve por el parametro dato
unsigned char i2c_read_byte(unsigned char address, unsigned char reg, 
                            unsigned char *dato)
{

  // 1º Envia Bit de Start
  i2c_SendStart();
  i2c_WaitMSSP();  

  // 2º Envio la direccion del modulo
  i2c_SendByte(address);
  i2c_WaitMSSP();  
  if (i2c_CheckACK()!=0) {
    i2c_fail();
    return 0;   // Ha habido un error, salgo de la rutina
  }

  // 3º mando el registro sobre el que voy a actuar
  i2c_SendByte(reg); 
  i2c_WaitMSSP();  
  if (i2c_CheckACK()!=0) {
    i2c_fail();
    return 0;   // Ha habido un error, salgo de la rutina
  }

  // 4º Repeated start
  i2c_SendRStart();
  i2c_WaitMSSP();  

  // 4º mando direccion indicando lectura
  i2c_SendByte(address+1);
  i2c_WaitMSSP();  
  if (i2c_CheckACK()!=0) {
    i2c_fail();
    return 0;   // Ha habido un error, salgo de la rutina
  }

  // 5º leo el byte 
  *dato=i2c_ReadByte(); 

  // 6º Mando NACK
  i2c_SendNack();
  i2c_WaitMSSP();  

  // Mando el Stop
  i2c_SendStop();
  i2c_WaitMSSP();  

  return 1;   // Lectura correcta

}

// Lee 2 bytes consecutivos  del dispositivo i2c
// El dato leido lo devuelve por el parametro dato
unsigned char i2c_read_word(unsigned char address, unsigned char reg, 
                            unsigned int *dato)
{
  unsigned char tmp_H, tmp_L;

  // 1º Envia Bit de Start
  i2c_SendStart();
  i2c_WaitMSSP();  
    
  // 2º Envio la direccion del modulo
  i2c_SendByte(address);
  i2c_WaitMSSP();  
  if (i2c_CheckACK()!=0) {
    i2c_fail();
    return 0;   // Ha habido un error, salgo de la rutina
  }

  // 3º mando el registro sobre el que voy a actuar
  i2c_SendByte(reg); 
  i2c_WaitMSSP();  
  if (i2c_CheckACK()!=0) {
    i2c_fail();
    return 0;   // Ha habido un error, salgo de la rutina
  }

  // 4º Repeated start
  i2c_SendRStart();
  i2c_WaitMSSP();  

  // 4º mando direccion indicando lectura
  i2c_SendByte(address+1);
  i2c_WaitMSSP();  
  if (i2c_CheckACK()!=0) {
    i2c_fail();
    return 0;   // Ha habido un error, salgo de la rutina
  }

  // 5º leo el 1 byte 
  tmp_H=i2c_ReadByte(); 
  
  // 6º Mando ACK
  i2c_SendAck();
  i2c_WaitMSSP();  
  
  // 7º leo el 2 byte 
  tmp_L=i2c_ReadByte(); 
  
  // 6º Mando NACK
  i2c_SendNack();
  i2c_WaitMSSP();  

  // Mando el Stop
  i2c_SendStop();
  i2c_WaitMSSP();  
  
  *dato=(tmp_H*256) + tmp_L;
  
  return 1;   // Lectura correcta
}

unsigned char LeerLM75(unsigned char address, unsigned char *datoh, unsigned char *datol)
{
  i2c_SendStart();
  i2c_WaitMSSP(); 

  i2c_SendByte(address);

  i2c_WaitMSSP();  
  if (i2c_CheckACK()!=0) {
    i2c_fail();
    return 0;   // Ha habido un error, salgo de la rutina
  }
 
  *datoh=i2c_ReadByte(); 
  
  i2c_SendAck();
  i2c_WaitMSSP(); 

  *datol=i2c_ReadByte();   

  //  Mando NACK
  i2c_SendNack();
  i2c_WaitMSSP();  

  // Mando el Stop
  i2c_SendStop();
  i2c_WaitMSSP();  

  return 1;
}

No hay comentarios:

IRC

#freenode->#usljujuy

Seguidores

Eventos n_n

Tira Ecol Nano,Bilo y Luca