/****************************************************************/
/* */
/* Implementacion de prueba del modulo I2C en un dsPIC 802 */
/* */
/****************************************************************/
#include <p33fj128gp802.h>
//Constantes utiles para la interfaz de usuario
#define PUSH_BUTTON_1 PORTBbits.RB2
#define PUSH_BUTTON_2 PORTBbits.RB3
#define PUSH_BUTTON_1_TRIS TRISBbits.TRISB2
#define PUSH_BUTTON_2_TRIS TRISBbits.TRISB3
#define LED_1 LATAbits.LATA0
#define LED_2 LATAbits.LATA1
#define LED_3 LATBbits.LATB0
#define LED_4 LATBbits.LATB1
#define LED_1_TRIS TRISAbits.TRISA0
#define LED_2_TRIS TRISAbits.TRISA1
#define LED_3_TRIS TRISBbits.TRISB0
#define LED_4_TRIS TRISBbits.TRISB1
/////////////////////////////////////////////////
//constantes utiles para el I2C//////////////////
#define I2C_FREC 20000 //frecuencia de I2C deseada
#define I2C_10M 10000000
#define CLOCK_FREC 80000000
#define RBRG (CLOCK_FREC/I2C_FREC) - (CLOCK_FREC/I2C_10M) -1
/////////////////////////////////////////////////
unsigned char data1, data2;
void START( void ); //Genera un Start I2C
void IDLE( void ); //Espera fin trasmision
void PUTC( int dato ); //Pone un dato en el canal
unsigned char GETC( void );
void ACK( void ); //Genera un ACK I2C
void NACK( void ); //Genera un NACK I2C
void WACK( void ); //Espera un ACK I2C
void STOP( void ); //Genera un Stop I2C
void CONF( void ); //Configura el I2C
void HARD( void ); //Configura el Hardware en general
void RST( void );
void ESCRITURA( void );
void LECTURA( void );
_FOSCSEL(FNOSC_FRCPLL);
_FWDT(FWDTEN_OFF); // Disable Watchdog timer
_FPOR(ALTI2C_ON);
/*
Pueba para el DoXy, este es el main
*/
int main( void )
{
unsigned int i;
CONF();
HARD();
while( 13)
{
LED_2 ^= 1;
ESCRITURA();
for( i=0 ; i<6500 ; i++ ) ; //genero un retardo de no se cuanto tiempo
// LECTURA();
// for( i=0 ; i<16500 ; i++ ) ;
}
return 0;
}
void START( void )
{
I2C1CONbits.SEN = 1; //Generar el Start
while (I2C1CONbits.SEN); //Esperar el Start
}
void IDLE( void )
{
while (I2C1STATbits.TRSTAT); //estoy trasmitiendo
}
void PUTC( int dato ) //Pone un dato en el canal
{
I2C1TRN = dato; //cargar byte de trasmision
while (I2C1STATbits.TBF); //Bufer lleno, todavia trasmitiendo
}
unsigned char GETC( void )
{
I2C1CONbits.RCEN = 1; //Habilita la recepcion si soy Master
I2C1STATbits.I2COV = 0;
while( !I2C1STATbits.RBF );
return(I2C1RCV);
}
void ACK( void )//genera un ACK
{
I2C1CONbits.ACKDT = 0; //configura ACk
I2C1CONbits.ACKEN = 1; //genera condicion de ACK
while(I2C1CONbits.ACKEN); //espera a que se termine de enviar
}
void NACK( void )//genera un NACK
{
I2C1CONbits.ACKDT = 1; //configura NACK
I2C1CONbits.ACKEN = 1; //genera condicion de ACK
while(I2C1CONbits.ACKEN); //espera a que el ACK ternime de ocurrir
}
void WACK( void )//(Wait ACK)
{
while( I2C1STATbits.ACKSTAT ); //Espera el ACK
}
void STOP( void )
{
I2C1CONbits.PEN = 1; //Generar STOP
while (I2C1CONbits.PEN); //Y esperar q ocurra
}
void RST( void )
{
I2C1CONbits.RSEN = 1; //Generate Restart
while (I2C1CONbits.RSEN); //Wait for restart
}
void CONF( void )
{
I2C1BRG = RBRG;
I2C1ADD = 0x88 >> 1;
// I2C1CON = 0x0000;
// I2C1RCV = 0x0000;
// I2C1TRN = 0x0000;
// I2C1CON = 0x1200;
// I2C1CONbits.I2CEN = 1;
I2C1CON = 0x0000;
I2C1CONbits.IPMIEN = 0;
I2C1CONbits.A10M = 0 >> 2;
I2C1CONbits.DISSLW = 1;
I2C1CONbits.SMEN = 0;
I2C1CONbits.GCEN = 0;
I2C1CONbits.STREN = 0;
I2C1CONbits.I2CEN = 1;
IFS1bits.SI2C1IF = 0;
IEC1bits.SI2C1IE = 1;
}
void HARD( void )
{
//OSC
CLKDIVbits.PLLPRE = 0; // N1=2: PLL VCO Output Divider Select bits; 0 -> /2 (default)
PLLFBDbits.PLLDIV = 38; // M=40: PLL Feedback Divisor bits; 42 - 2 = 40 -> 40 x multiplier
CLKDIVbits.PLLPOST = 0; // (divisor is 2 more than the value)
// OSCTUN = 16; //por ocio... para ajustar el cristal
//PIN IO
LED_1_TRIS = 0;
LED_2_TRIS = 0;
LED_3_TRIS = 0;
LED_4_TRIS = 0;
LED_1 = 1;
LED_2 = 1;
LED_3 = 1;
LED_4 = 1;
AD1PCFGLbits.PCFG0 = 1;
AD1PCFGLbits.PCFG1 = 1;
AD1PCFGLbits.PCFG2 = 1;
AD1PCFGLbits.PCFG3 = 1;
AD1PCFGLbits.PCFG4 = 1;
AD1PCFGLbits.PCFG5 = 1;
PUSH_BUTTON_1_TRIS = 1;
PUSH_BUTTON_2_TRIS = 1;
}
void ESCRITURA()
{
START();
PUTC( 0b10101010 ); //control 1010 direccion 101 R/W' 0 para Write
IDLE(); //trasmito y espero el ACK
WACK();
PUTC( 0 ); //Direccion Alta
IDLE();
WACK();
PUTC( 0 ); //Direccion Baja
IDLE();
WACK();
PUTC( 0xAA ); //Dato 0
IDLE();
WACK();
PUTC( 0xBB ); //Dato 1
IDLE();
WACK();
PUTC( 0xCC ); //Dato 2
IDLE();
WACK();
STOP();
}
void LECTURA( void )
{
START();
PUTC( 0b10101010 ); //control 1010 direccion 101 R/W' 0 para Write
IDLE(); //trasmito y espero el ACK
PUTC( 0 ); //Direccion Alta
IDLE();
PUTC( 0 ); //Direccion Baja
IDLE();
RST();
PUTC( 0b10101011 ); //control 1010 direccion 101 R/W' 1 para Read
data1 = GETC();
data2 = GETC();
STOP();
}