// Ejemplo simple que muestra el funcionamiento del puerto I2C, RS232, teclado y LCD. // Envia la entrada del teclado a la eeprom (PCF8582) y al pulsar la tecla 0xF los lee. // Fernando Pardo 2005 // MPLAB C18 // La parte de la EEPROM I2C no funciona #include #include #include #include #include "lcd18.h" #pragma romdata CONFIG const rom unsigned char _configuration[14] = {0x00,0x22,0x0F,0x0E,0x00,0x01,0x81,0x00,0x0F,0xC0,0x0F,0xE0,0x0F,0x40}; #pragma romdata #define ESCLAVO 0b10100000 #define ESCLAVO_R 0b10100001 unsigned char Tecla,TeclaRem; unsigned char Temp,Temp1,Temp2; unsigned char Pulsada; unsigned char dir; unsigned char num; void Lee_Tecla(void) { TRISB=0b11110000; EnablePullups(); PORTB=0; Temp1=(PORTB>>4); Temp=0; while ((Temp1 & 0x01)) // cuenta hasta que llegue a un bit set (not set) { Temp1>>=1; Temp++; } if (Temp<4) // se ha pulsado { Temp2=Temp; // Guardo columna TRISB=0b00001111; // ahora la fila EnablePullups(); PORTB=0; Temp1=PORTB&0x0F; // parte alta a cero Temp=0; while ((Temp1 & 0x01)) // cuenta hasta que llegue a un bit set { Temp1>>=1; Temp++; } if (Temp<4) // Fila correcta { Temp1=Temp; Tecla=(Temp2<<2)+Temp1; } else Tecla=0xFF; } else Tecla=0xFF; } 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); /*// SPBRG=25; // 9600 baudios alta velocidad, 4MHz SPBRG=38; // 9600 baudios alta velocidad, 6MHz TXSTA=10100100b; // Asincrono, alta velocidad, reloj interno RCSTA=10010000b; // Habilita RS232, 8 bits, -, recepcion continua, no errores // set_tris_c(10111111b); // RC6/TX de salida, resto de entrada TRISC=(TRISC & 10111111b) | 10000000b; */ } void RS_Envia(unsigned char caracter) { while (BusyUSART()); // espera a que este libre WriteUSART(caracter); } unsigned char I2C_Busy(void) { return (SSPSTATbits.R_W || SSPCON2bits.ACKEN || SSPCON2bits.RCEN || SSPCON2bits.PEN || SSPCON2bits.RSEN || SSPCON2bits.SEN); } void I2C_Ini(void) { TRISC=0xFF; SSPADD=14; // divisor del reloj master mode (14 para 100KHz,6Mhz) OpenI2C(MASTER,SLEW_OFF); // SSPADD=9; // divisor del reloj master mode (9 para 100KHz,4MHz) } void I2C_Start(void) { StartI2C(); } void I2C_Stop(void) { StopI2C(); } void I2C_Envia(unsigned char dato) { //IdleI2C(); // espera que este libre while (I2C_Busy()); WriteI2C(dato); } unsigned char I2C_Recibe(void) { //IdleI2C(); //while (DataRdyI2C()==0); //return(ReadI2C()); while (I2C_Busy()); //PIR1=PIR1 & 0b11110111; // IdleI2C(); //set_bit(SSPCON2,3); // Habilita la recepcion //SSPCON2=SSPCON2 | 0b00001000; SSPSTATbits.BF==0; SSPCON2bits.RCEN=1; while (SSPSTATbits.BF==0); // while ((PIR1 & 0b00001000)==0); // Espera que termine //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(unsigned 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) { LCD_Prepara(); LCD_Ini(); LCD_Comando(0b00111100); // 8 bits, 2 lineas, 5x10 font LCD_Comando(0b00001111); // Disp On, Cursor On, Blink On PORTC=0; Pulsada=0; RS_Ini(); I2C_Ini(); while (1) { dir=0; Tecla=0; while (Tecla!=0xF) { if (DataRdyUSART()) { TeclaRem=ReadUSART(); //RCREG; //RS_Recibe(); LCD_Dato(TeclaRem); } Lee_Tecla(); if (Tecla<16) { if (!Pulsada) { Pulsada=1; if (Tecla<10) { LCD_Dato(Tecla+'0'); RS_Envia(Tecla+'0'); } else { LCD_Dato(Tecla+55); // 55='A'-10 RS_Envia(Tecla+55); } I2C_Start(); I2C_Envia(ESCLAVO); // Envia la direccion del esclavo I2C_Envia(dir); // Envia Direccion I2C_Envia(Tecla); // Envia Tecla I2C_Stop(); dir++; } } else { if (Pulsada) { Pulsada=0; } } Delay10KTCYx(2); // Para evitar rebotes } LCD_Comando(0b11000000); // Segunda linea del LCD dir=0; // ahora se dispone a leer lo escrito I2C_Ini(); I2C_Start(); I2C_Envia(ESCLAVO); // Envia la direccion del esclavo I2C_Envia(dir); // Envia Direccion a la eeprom I2C_Stop(); I2C_Start(); I2C_Envia(ESCLAVO_R); // Envia la direccion del esclavo para LEER Tecla=0; dir=0; while ((Tecla!=0xF) && (dir<4)) { Tecla=ReadI2C();//I2C_Recibe(); // Lee Tecla num=Tecla>>4; if (num<10) LCD_Dato(num+'0'); else LCD_Dato(num+55); // 55='A'-10 num=Tecla&0x0F;; if (num<10) LCD_Dato(num+'0'); else LCD_Dato(num+55); // 55='A'-10 LCD_Dato('-'); //if (Tecla<10) LCD_Dato(Tecla+'0'); //else LCD_Dato(Tecla+55); // 55='A'-10 if (Tecla==0xF) I2C_Ack(1); // _reconocimiento=1 else I2C_Ack(0); // _reconocimiento=0 dir++; } I2C_Stop(); LCD_Comando(0b00000010); // A home sin borrar } }