/* 24LC256.C ** ** Illustrates an interface with a 24LC256 (32K X 8) I2C EEPROM. ** ** Assumes device address (A2, A1, A0) is strapped for 0x0. ** ** Writes 10 values to memory locations beginning at memory address 0x0700. ** Reads them back and displays on the local console. ** ** Flashlite V25 24LC256 ** ** SDA P2.0 ---------------- term 5 on 24lc256 ** SCL P2.1 ---------------- term 6 on 24lc256 ** ** Note that as the Flashlite V25 has the capability to save data to its ** own flash memory by opening a file, interfacing with an external EEPROM ** probably is none too practical. However, it is a simple example of an ** implementation of I2C routines. ** ** copyright, Peter H. Anderson, Baltimore, MD, Sept, '00 */ #include <stdio.h> #include <dos.h> #define SEG 0xf000 #define P2_OFFSET 0xff10 #define PM2_OFFSET 0xff11 #define PMC2_OFFSET 0xff12 typedef unsigned char byte; void random_write(byte dev_adr, unsigned int mem_adr, byte dat); byte random_read(byte dev_adr, unsigned int mem_adr); /* standard I2C routines */ byte i2c_in_byte(void); void i2c_out_byte(byte o_byte); void i2c_nack(void); void i2c_ack(void); void i2c_start(void); void i2c_stop(void); void i2c_high_sda(void); void i2c_low_sda(void); void i2c_high_scl(void); void i2c_low_scl(void); byte far *p2, *pm2, *pmc2; /* note global */ byte dirs2, outs2; void main(void) { byte dat; unsigned int mem_adr, n; p2 = MK_FP(SEG, P2_OFFSET); pm2 = MK_FP(SEG, PM2_OFFSET); pmc2 = MK_FP(SEG, PMC2_OFFSET); dirs2 = 0xff; *pmc2 = 0x00; /* not special purpose */ *pm2 = dirs2; /* configure as all inputs */ while(1) { mem_adr = 0x0700; for(n=0; n<10; n++, mem_adr++) { dat = 0xfe - n; random_write(0x00, mem_adr, dat); } mem_adr = 0x0700; for(n=0; n<10; n++, mem_adr++) { dat = random_read(0x00, mem_adr); printf("%x\n", dat); delay(100); } printf("..\n"); } } void random_write(byte dev_adr, unsigned int mem_adr, byte dat) { i2c_start(); i2c_out_byte(0xa0 | (dev_adr << 1)); i2c_nack(); i2c_out_byte((mem_adr >> 8) & 0xff); i2c_nack(); i2c_out_byte(mem_adr & 0xff); i2c_nack(); i2c_out_byte(dat); i2c_nack(); i2c_stop(); delay(25); /* allow for the programming of the eeprom */ } byte random_read(byte dev_adr, unsigned int mem_adr) { byte y; i2c_start(); i2c_out_byte(0xa0 | (dev_adr << 1)); i2c_nack(); i2c_out_byte((mem_adr >> 8) & 0xff); i2c_nack(); i2c_out_byte(mem_adr & 0xff); i2c_nack(); i2c_start(); i2c_out_byte(0xa1 | (dev_adr << 1)); i2c_nack(); y=i2c_in_byte(); /* no ack prior to stop */ i2c_stop(); return(y); } byte i2c_in_byte(void) { byte i_byte, n; i2c_high_sda(); for (n=0; n<8; n++) { i2c_high_scl(); if (*(p2) & 0x01) { i_byte = (i_byte << 1) | 0x01; /* msbit first */ } else { i_byte = i_byte << 1; } i2c_low_scl(); } return(i_byte); } void i2c_out_byte(byte o_byte) { byte n; for(n=0; n<8; n++) { if(o_byte&0x80) { i2c_high_sda(); } else { i2c_low_sda(); } i2c_high_scl(); i2c_low_scl(); o_byte = o_byte << 1; } i2c_high_sda(); } void i2c_nack(void) { i2c_high_sda(); /* data at one */ i2c_high_scl(); /* clock pulse */ i2c_low_scl(); } void i2c_ack(void) { i2c_low_sda(); /* bring data low and clock */ i2c_high_scl(); i2c_low_scl(); i2c_high_sda(); } void i2c_start(void) { i2c_low_scl(); i2c_high_sda(); i2c_high_scl(); /* bring SDA low while SCL is high */ i2c_low_sda(); i2c_low_scl(); } void i2c_stop(void) { i2c_low_scl(); i2c_low_sda(); i2c_high_scl(); i2c_high_sda(); /* bring SDA high while SCL is high */ /* idle is SDA high and SCL high */ } void i2c_high_sda(void) { dirs2 = dirs2 | 0x01; *pm2 = dirs2; #ifdef D /* used for debugging */ printf("SDA_HIGH %x\n", dirs2); delay(500); #endif } void i2c_low_sda(void) { outs2 = outs2 & (~0x01); /* zero the output pin */ *p2 = outs2; dirs2 = dirs2 & (~0x01); /* and output */ *pm2 = dirs2; #ifdef D printf("SDA_LOW %x\n", dirs2); delay(500); #endif } void i2c_high_scl(void) { dirs2 = dirs2 | 0x02; /* bring SCL to high impedance */ *pm2 = dirs2; #ifdef D printf("SCL_HIGH %x\n", dirs2); delay(500); #endif } void i2c_low_scl(void) { outs2 = outs2 & (~0x02); *p2 = outs2; /* zero the output pin */ dirs2 = dirs2 & (~0x02); /* and output */ *pm2 = dirs2; #ifdef D printf("SCL_LOW %x\n", dirs2); delay(500); #endif }