// Ejemplo simple que muestra el funcionamiento del puerto I2C. // Manda un diente de sierra por la salida analogica del conversor del I2C (PCF8591) // Fernando Pardo 2005 // MPLAB C18 #include #include #include // no funciona para el 2550 pues usa RB0 y RB1 #pragma romdata CONFIG const rom unsigned char _configuration[14] = {0x00,0x0C,0x1F,0x1E,0x00,0x83,0x81,0x00,0x0F,0xC0,0x0F,0xE0,0x0F,0x40}; #pragma romdata #define ESCLAVO_ANA 0b10010000 #define ESCLAVO_DIG 0b10100000 unsigned char i,dir,num; void RS_Ini(void) { OpenUSART(USART_TX_INT_OFF & USART_RX_INT_OFF & USART_ASYNCH_MODE & USART_EIGHT_BIT & USART_CONT_RX & USART_BRGH_HIGH, 38); } void RS_Envia(char caracter) { while (BusyUSART()); // espera a que este libre WriteUSART(caracter); } void I2C_Ini(void) { OpenI2C(MASTER,SLEW_OFF); SSPADD=14; /* // set_tris_c(0x11111111b); // Todo inputs // TRISC=(TRISC | 00110000b); TRISB=0xFC; SSPSTAT=0b10000000; // Slew rate disables (100 KHz) // SSPADD=9; // divisor del reloj master mode (9 para 100KHz,4MHz) SSPADD=14; // divisor del reloj master mode (14 para 100KHz,6Mhz) SSPCON1=0b00101000; // I2C enabled, 7 bits direc, master */ } void I2C_Start(void) { StartI2C(); /* //clear_bit(PIR1,3); // Limpia bit de int de SSP PIR1=PIR1 & 0b11110111; //set_bit(SSPCON2,0); // Envia Start SSPCON2=SSPCON2 | 0b00000001; while (SSPCON2 & 0b00000001); // Mira que acabe el Start */ } void I2C_Stop(void) { StopI2C(); // clear_bit(PIR1,3); // Limpia bit de int de SSP /* PIR1=PIR1 & 0b11110111; // set_bit(SSPCON2,2); // Envia Stop SSPCON2=SSPCON2 | 0b00000100; while (SSPCON2 & 0b00000100); // Mira que acabe el Stop */ } void I2C_Envia(char dato) { IdleI2C(); // espera que este libre WriteI2C(dato); /* // clear_bit(PIR1,3); // Limpia bit de int de SSP PIR1=PIR1 & 0b11110111; SSPBUF=dato; // Envia el dato while ((PIR1 & 0b00001000)==0); // Espera que termine */ } unsigned char I2C_Recibe(void) { RS_Envia('a'); IdleI2C(); RS_Envia('b'); //while (DataRdyI2C()==0); // return(ReadI2C()); // clear_bit(PIR1,3); // Limpia bit de int de SSP PIR1=PIR1 & 0b11110111; // IdleI2C(); //set_bit(SSPCON2,3); // Habilita la recepcion SSPCON2=SSPCON2 | 0b00001000; while ((PIR1 & 0b00001000)==0); // Espera que termine RS_Envia('c'); //while ((PIR1 & 00001000b)==0); // Espera que se haya recibido todo //clear_bit(PIR1,3); // Limpia bit de int de SSP PIR1=PIR1 & 0b11110111; return(SSPBUF); // Lee Tecla } void I2C_Ack(char valor) { // if (valor) AckI2C(); // else NotAckI2C(); // clear_bit(PIR1,3); // Limpia bit de int de SSP PIR1=PIR1 & 0b11110111; //if (valor) set_bit(SSPCON2,5); // _reconocimiento=1 //else clear_bit(SSPCON2,5); // _reconocimiento=0 if (valor) SSPCON2=SSPCON2 | 0b00100000; else SSPCON2=SSPCON2 & 0b11011111; SSPCON2=SSPCON2 | 0b00010000; //set_bit(SSPCON2,4); // Envia reconocimiento //while ((PIR1 & 00001000b)==0); // Espera que termine while ((PIR1 & 0b00001000)==0); // Espera que termine } void main(void) { RS_Ini(); RS_Envia('A'); I2C_Ini(); // escribe y lee de la eeprom dir=0; /* // no consigo hacerlo funcionar for (i=0;i<4;i++) { RS_Envia(dir+'0'); I2C_Start(); I2C_Envia(ESCLAVO_DIG); // Envia la direccion del esclavo I2C_Envia(dir); // Envia Direccion I2C_Envia(dir%10); // Envia Tecla I2C_Stop(); dir++; } // leer es lo que no funciona, parece. dir=0; // ahora se dispone a leer lo escrito // RS_Envia('E'); I2C_Start(); //RS_Envia('E'); I2C_Envia(ESCLAVO_DIG); // Envia la direccion del esclavo //RS_Envia('E'); I2C_Envia(dir); // Envia Direccion a la eeprom //RS_Envia('E'); I2C_Stop(); //RS_Envia('E'); I2C_Start(); //RS_Envia('E'); I2C_Envia(ESCLAVO_DIG | 1); // Envia la direccion del esclavo para LEER //RS_Envia('E'); for (i=0;i<4;i++) { RS_Envia('E'); RS_Envia(I2C_Recibe()+'5'); // Lee Tecla RS_Envia('S'); I2C_Ack(0); // _reconocimiento=0 } I2C_Ack(1); // _reconocimiento=1 I2C_Stop(); */ // Y ahora la salida analogica (esto si que va) I2C_Start(); I2C_Envia(ESCLAVO_ANA); I2C_Envia(0b01000000); // Habilita el D/A del PCF8591 while (1) { //RS_Envia(i+'0'); I2C_Envia(i); i++; } }