//************************************************************ // I2C_EEPROM Check(CPU: dsPIC30F4013) // // Soft I2C // Used AT24C256 // // LCD unlook busy : not switch direction (write fixed) // // CPU dsPIC30F4013 // 7.37MHz Internal RC oscillator, 16x PLL enabled // Fcy=7.37MHzx16/4=29.48MHz, Tcy=33.92ns // // 2010/9/11: N.Ishii //************************************************************* #include // Divice configuration _FWDT(WDT_OFF); _FGS(CODE_PROT_OFF); _FOSC(CSW_FSCM_OFF & FRC_PLL16); //OSC, PLL Setting _FBORPOR(PBOR_OFF & PWRT_64 & MCLR_EN); // LCD Define: R/W_pin= GND (Fixed Write) #define LCD_DATA_WR_MODE LATFbits.LATF1 = 1 // RS_pin = 1 #define LCD_INST_WR_MODE LATFbits.LATF1 = 0 // RS_pin = 0 #define LCD_ENABLE_ON LATFbits.LATF0 = 1 #define LCD_ENABLE_OFF LATFbits.LATF0 = 0 #define LCD_DATA_BIT4 LATBbits.LATB9 #define LCD_DATA_BIT5 LATBbits.LATB10 #define LCD_DATA_BIT6 LATBbits.LATB11 #define LCD_DATA_BIT7 LATBbits.LATB12 //--------------------------------------------------------------------------------------------- // LCD Instraction Code #define FOUR_BIT_FONT5x7dot 0x28 // + TWO_LINE(1/16Duty), SEG1_50_SEG51_100, COM1_COM16 #define DISP_ON_CURSOR_ON_BLINK_OFF 0x0e #define DISP_CLEAR_CURSOR_HOME 0x01 #define RAM_WR_AFTER_PLUS_1 0x06 // Entory mode set #define DDRAM_START_ADDRESS_SET 0x80 #define DISP_ON_CURSOR_OFF_BLINK_OFF 0x0c //--------------------------------------------------------------------------------------------- // I2C define #define EEPROM_SLVADRS_WR 0xa0 #define EEPROM_SLVADRS_RD 0xa1 #define SDA_OUT LATFbits.LATF2 #define SCL_OUT LATFbits.LATF3 #define SDA_IN PORTFbits.RF2 //--------------------------------------------------------------------------------------------- // For I2C unsigned char test_data[] = {0x55,0xaa}; // For TEST Data Table: 0x55-> 085Dec, 0xaa-> 170Dec unsigned char rec_data[16]; //------------------------------------------------------------------------- // Delay Subrutin void Waitx1ms(int x) // Td = 1mS * x { int i,j; for(i = 0 ; i < x ; ++i) { for(j = 0 ; j < 5000 ; ++j) asm("clrwdt"); //Td=1mS } } void Waitx1us(int x) // Td = 1uS * x { int i,j; for(i = 0 ; i < x ; ++i) { for(j = 0 ; j < 5 ; ++j) asm("clrwdt"); //Td=1uS } } //-------------------------------------------------------------------- void one_chr_wr(char chr_code) { LCD_DATA_WR_MODE; //RS_pin = 1: select data Reg // A Higher 4bit data out LCD_DATA_BIT7 = (unsigned int)((chr_code & 0x80)>>7); LCD_DATA_BIT6 = (unsigned int)((chr_code & 0x40)>>6); LCD_DATA_BIT5 = (unsigned int)((chr_code & 0x20)>>5); LCD_DATA_BIT4 = (unsigned int)((chr_code & 0x10)>>4); Waitx1us(1); LCD_ENABLE_ON; Waitx1us(1); LCD_ENABLE_OFF; // A Lower 4bit data out LCD_DATA_BIT7 = (unsigned int)((chr_code & 0x08)>>3); LCD_DATA_BIT6 = (unsigned int)((chr_code & 0x04)>>2); LCD_DATA_BIT5 = (unsigned int)((chr_code & 0x02)>>1); LCD_DATA_BIT4 = (unsigned int)(chr_code & 0x01); Waitx1us(1); LCD_ENABLE_ON; Waitx1us(1); LCD_ENABLE_OFF; Waitx1us(50); } void lcd_chr_wr(char *buffer) { while(*buffer != '\0') { one_chr_wr(*buffer); /* calling another function */ /* to write each char to the lcd module */ buffer++; } } void lcd_inst_wr(char inst_code) { LCD_INST_WR_MODE; //RS_pin = 0: select Instruction Reg // A Higher 4bit data out LCD_DATA_BIT7 = (unsigned int)((inst_code & 0x80)>>7); LCD_DATA_BIT6 = (unsigned int)((inst_code & 0x40)>>6); LCD_DATA_BIT5 = (unsigned int)((inst_code & 0x20)>>5); LCD_DATA_BIT4 = (unsigned int)((inst_code & 0x10)>>4); Waitx1us(1); LCD_ENABLE_ON; Waitx1us(1); LCD_ENABLE_OFF; // A Lower 4bit data out LCD_DATA_BIT7 = (unsigned int)((inst_code & 0x08)>>3); LCD_DATA_BIT6 = (unsigned int)((inst_code & 0x04)>>2); LCD_DATA_BIT5 = (unsigned int)((inst_code & 0x02)>>1); LCD_DATA_BIT4 = (unsigned int)(inst_code & 0x01); Waitx1us(1); LCD_ENABLE_ON; Waitx1us(1); LCD_ENABLE_OFF; if ((inst_code & 0x03) != 0) Waitx1ms(20); // inst_code is Clear(0x01) or Cursor Home(0x02) Then Wait 20mS else Waitx1us(50); // other code Then Wait 50uS } void lcd_init(void) { // Allow a delay(minimum of 15ms) Waitx1ms(20); //------ 1st step: port_output regster set -------------- // Initialize the data port/control pins to zero LCD_DATA_BIT7 = 0; LCD_DATA_BIT6 = 0; LCD_DATA_BIT5 = 0; LCD_DATA_BIT4 = 0; LCD_INST_WR_MODE; //RS_pin = 0 LCD_ENABLE_OFF; //E_pin = 0 //-------------------------------------------------------- // dsPIC30F4013 //------- 2nd step: port_mode regster set --------------- // Configure the data pins as output TRISBbits.TRISB9 =0; // RB9 is LCD DB4 OUTPUT TRISBbits.TRISB10 =0; // RB10 is LCD DB5 OUTPUT TRISBbits.TRISB11 =0; // RB11 is LCD DB6 OUTPUT TRISBbits.TRISB12 =0; // RB12 is LCD DB7 OUTPUT // Make all control pins as outputs TRISFbits.TRISF0 =0; // RF0 is LCD Enable OUTPUT TRISFbits.TRISF1 =0; // RF1 is LCD RS OUTPUT //------------------------------------------------------- // Initialize stage 1: Set stage 1 only 8-bit Interface // Set Upper 4 Bit Data on RB9 - RB12 LCD_DATA_BIT7 = 0; LCD_DATA_BIT6 = 0; LCD_DATA_BIT5 = 1; LCD_DATA_BIT4 = 1; Waitx1us(1); LCD_ENABLE_ON; Waitx1us(1); LCD_ENABLE_OFF; Waitx1ms(5); // Initialize stage 2: Set stage 2 only 8-bit Interface LCD_DATA_BIT7 = 0; LCD_DATA_BIT6 = 0; LCD_DATA_BIT5 = 1; LCD_DATA_BIT4 = 1; Waitx1us(1); LCD_ENABLE_ON; Waitx1us(1); LCD_ENABLE_OFF; Waitx1ms(1); // Initialize stage 3: Set stage 3 only 8-bit Interface LCD_DATA_BIT7 = 0; LCD_DATA_BIT6 = 0; LCD_DATA_BIT5 = 1; LCD_DATA_BIT4 = 1; Waitx1us(1); LCD_ENABLE_ON; Waitx1us(1); LCD_ENABLE_OFF; Waitx1ms(1); // Initialize stage 4: 4-bit Interface LCD_DATA_BIT7 = 0; LCD_DATA_BIT6 = 0; LCD_DATA_BIT5 = 1; LCD_DATA_BIT4 = 0; Waitx1us(1); LCD_ENABLE_ON; Waitx1us(1); LCD_ENABLE_OFF; Waitx1ms(1); //----- Fixed LCD Setting------------ lcd_inst_wr(FOUR_BIT_FONT5x7dot); // Function Set lcd_inst_wr(DISP_ON_CURSOR_ON_BLINK_OFF); lcd_inst_wr(DISP_CLEAR_CURSOR_HOME); // Set DDRAM Address = 0 lcd_inst_wr(RAM_WR_AFTER_PLUS_1); // Entry mode Set } //------------------------------------------------------------------------- void variable_disp(unsigned char Vol, unsigned char loc) { // Vol: 0x00-0xff( 000-255 Disp) unsigned char i; unsigned char digit[3]; unsigned char ascii[3]; // Bin_to_pacdec digit[0] = Vol%10; digit[1] = (Vol/10)%10; digit[2] = (Vol/100)%10; /* digit[3] = (Vol/100)/10; */ // Decimal_to_ascii for (i = 0; i <= 2; ++i) {ascii[i] = digit[i] | 0x30;} // LCD Disp lcd_inst_wr(loc); one_chr_wr(ascii[2]); one_chr_wr(ascii[1]); one_chr_wr(ascii[0]); } //------------------------------------------------------------------------------ // Soft I2C Sub routine void i2c_write(unsigned char send_data) { unsigned char i; for (i = 0; i <= 7; ++i) { if (( send_data & 0x80) == 0) SDA_OUT = 0; else SDA_OUT = 1; Waitx1us(5); SCL_OUT = 1; Waitx1us(5); SCL_OUT = 0; send_data <<= 1; } } unsigned char i2c_read(void) { unsigned char i; unsigned char read_data; TRISFbits.TRISF2=1; // RF2 is SDA Input for (i = 0; i <= 7; ++i) { read_data <<= 1; read_data |= SDA_IN; Waitx1us(5); SCL_OUT = 1; Waitx1us(5); SCL_OUT = 0; } return(read_data); } void receive_ack(void) { TRISFbits.TRISF2=1; // RF2 is SDA Hi-Z(input) Waitx1us(5); SCL_OUT = 1; while(SDA_IN != 0); // Wait ACK Waitx1us(5); SCL_OUT = 0; TRISFbits.TRISF2=0; // RF2 is SDA output } //------------------------------------------------------------------------------------ void i2c_write_sr(unsigned int start_adrs, unsigned char len) { // start_adrs: 0x0000min - 0x7fffmax (EEPROM: 32768Bytes) unsigned char low_temp; unsigned char high_temp; low_temp = (char)(start_adrs & 0x00ff); high_temp = (char)((start_adrs >> 8) & 0x00ff); unsigned char i; // START Bus Event TRISFbits.TRISF3=0; // RF3 is SCL output TRISFbits.TRISF2=0; // RF2 is SDA output SCL_OUT = 1; SDA_OUT = 1; Waitx1us(5); SDA_OUT = 0; Waitx1us(5); SCL_OUT = 0; // Send Slave Address + Writebit i2c_write(EEPROM_SLVADRS_WR); // Receive ACK From EEPROM receive_ack(); // Send Write Top High Address Waitx1us(40); i2c_write(high_temp); // Receive ACK From EEPROM receive_ack(); // Send Write Top Low Address Waitx1us(40); i2c_write(low_temp); // Receive ACK From EEPROM receive_ack(); // Send EEPROM Write Data (Write Address Auto Incriment) for (i = 0; i != len; ++i) { Waitx1us(40); i2c_write(test_data[i]); // Receive ACK From RTC8564 receive_ack(); } // Stop Bus Event SDA_OUT = 0; Waitx1us(5); SCL_OUT = 1; Waitx1us(5); SDA_OUT = 1; TRISFbits.TRISF3=1; // RF3 is SCL Hi-Z TRISFbits.TRISF2=1; // RF2 is SDA Hi-Z Waitx1ms(10); } void i2c_read_sr(unsigned int start_adrs, unsigned char len) { unsigned char low_temp; unsigned char high_temp; low_temp = (char)(start_adrs & 0x00ff); high_temp = (char)((start_adrs >> 8) & 0x00ff); unsigned char i; // START Bus Event TRISFbits.TRISF3=0; // RF3 is SCL output TRISFbits.TRISF2=0; // RF2 is SDA output SCL_OUT = 1; SDA_OUT = 1; Waitx1us(5); SDA_OUT = 0; Waitx1us(5); SCL_OUT = 0; // Send Slave Address + Writebit i2c_write(EEPROM_SLVADRS_WR); // Receive ACK From EEPROM receive_ack(); // Send Read Start High Address Waitx1us(40); i2c_write(high_temp); // Receive ACK From EEPROM receive_ack(); // Send Read Start Low Address Waitx1us(40); i2c_write(low_temp); // Receive ACK From EEPROM receive_ack(); // RESTART Bus Event Waitx1us(40); SDA_OUT = 1; Waitx1us(5); SCL_OUT = 1; Waitx1us(5); SDA_OUT = 0; Waitx1us(5); SCL_OUT = 0; // Send Slave Address + Readbit i2c_write(EEPROM_SLVADRS_RD); // Receive ACK From EEPROM receive_ack(); // Receive EEPROM Read Data (Read Address Auto Incriment) for (i = 0; i != len; ++i) { Waitx1us(40); rec_data[i] = i2c_read(); // Send ACK From PIC if (i != len - 1) { TRISFbits.TRISF2=0; // RF2 is SDA output SDA_OUT = 0; Waitx1us(5); SCL_OUT = 1; Waitx1us(5); SCL_OUT = 0; } } // Send NACK From PIC: End of Rx TRISFbits.TRISF2=0; // RF2 is SDA output SDA_OUT = 1; Waitx1us(5); SCL_OUT = 1; Waitx1us(5); SCL_OUT = 0; // Stop Bus Event SDA_OUT = 0; Waitx1us(5); SCL_OUT = 1; Waitx1us(5); SDA_OUT = 1; TRISFbits.TRISF3=1; // RF3 is SCL Hi-Z TRISFbits.TRISF2=1; // RF2 is SDA Hi-Z } //--------------------------------------------------------------------------------------------- // Main routine int main(void) { // Set ADPCFG: RB1 Port is All Digital Pin ADPCFG = 0xFFFF; TRISDbits.TRISD0=0; // RD0 is LED output used debug PORTDbits.RD0 = 1; // Red LED OFF // Initialize I2C Port TRISFbits.TRISF3=1; // RF3 is SCL Hi-Z TRISFbits.TRISF2=1; // RF2 is SDA Hi-Z // Initialize LCD lcd_init(); lcd_inst_wr(DISP_ON_CURSOR_OFF_BLINK_OFF); Waitx1ms(10); i2c_write_sr(0x1234,2); i2c_read_sr(0x1234,2); variable_disp(rec_data[0],0x80); variable_disp(rec_data[1],0xc0); PORTDbits.RD0 = 0; // Red LED ON while(1) { ; } }