#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; }
jueves, 25 de octubre de 2012
sdcc easypic2 i2c
Suscribirse a:
Enviar comentarios (Atom)
IRC
#freenode->#usljujuy
No hay comentarios:
Publicar un comentario