This application note was written by Victoria Welch from code supplied by Brent Nelson.
Download the zipped file or copy / paste from below.
The zip file contains the following code and a schematic which may be useful to assemble a test circuit for this program.
'********************************************************************** ' Application Note: 16 Bit Addressing on the I2C Bus. ' (8 bit data transfers one byte at a time) '----------------------------------------------------- ' ' Program-ID.: I2C_EEPROM.bas. ' Date...... : 04 / 04 / 2002 ' Description: Example program for I2c EEprom write and read routines ' ' Author : Victoria Welch (vikki@oz.net). ' This program finally helped me get my 24LC64 EEPROM working. ' Many thanks Brent! I Converted the original program into an ' application note in the hope it helps others new to these devices. ' ' Brent Nelson (spock50@gte.net). ' Brent provided the orginal form of this program to the BASCOM list. ' ' Remarks: ' Setup for the AT90S2313 using portb.0 for SDA and Portb.1 for SCL. ' ' Uses onboard serial port. ' ' This program provides an example for writing to and reading from ' an I2C EEPROM device wired for device 0 (AO,A1 and A2 all pulled ' to Gnd). ' ' This has been tested with a Microchip 24LC65. ' '********************************************************************** $regfile = "2313def.dat" ' Change for your AVR. $crystal = 4000000 ' 4 MHz Crystal. $baud = 9600 ' Output at 9600 baud. '********************************************************************** '** Set up Data Direction Registers and ports - Do this before defining I2C pins! '** Read up on this in the data sheet, understanding is important! '********************************************************************** ' Port B Portb = &B0000_0000 ' Set All Port Pins Low Ddrb = &B1111_1100 ' Set Unused Pins As Outputs. Set I2C pins as inputs (tri-state- floating) ' Port D Portd = &B0000_0000 ' All low - with push-pull output Ddrd = &B1111_1111 ' with internal pullups. '********************************************************************** '** Define and initialize I2C pins ** '********************************************************************** Config Sda = Portb.0 ' I2C Data. Config Scl = Portb.1 ' I2C Clock. '********************************************************************** '** Declate subroutines ** '********************************************************************** ' ' This subroutine writes data to the I2C EEPROM. ' Declare Sub I2c_ram_write(address_desired As Word , Content As Byte) ' ' This subroutine reads data from the I2C EEPROM. ' Declare Sub I2c_ram_read(address_desired As Word) '********************************************************************** '** Define working variables and constants ** '********************************************************************** Dim I2c_eeprom_address_desired As Word ' I2C EEPROM address counter (provides for 65536 locations). Dim I2c_eeprom_address_high_byte As Byte ' High byte of EEPROM address. Dim I2c_eeprom_address_low_byte As Byte ' Low byte of EEPROM address. Dim Data_work_var As Byte ' Working variables. Dim Counter As Byte ' ' Change the 3 "AD" bits to reflect the I2C address of the device ' (corresponding to A0,A1 and A2).. ' FAM AD M Const Eeprom_chip_write_command = &B10100000 ' Family "A", Device/unit 1, write. Const Eeprom_chip_read_command = &B10100001 ' Family "A", Device/unit 1, Read. '********************************************************************** '** Actual work starts here. ** '********************************************************************** Main: Print "I2C EEPROM Test Program." ' Just a header for separation. ' ' First we write data to the EEPROM: 150 to 51 ' Counter = 100 ' Initialize loop counter. I2c_eeprom_address_desired = 0 ' We start writing at EEPROM address zero. Do Data_work_var = Counter + 50 ' Generate test data (=0<256). Call I2c_ram_write(i2c_eeprom_address_desired , Data_work_var) ' Write it to the EEPROM. Incr I2c_eeprom_address_desired ' Increment EEPROM address location desired. Decr Counter ' Decrement the loop counter. Loop Until Counter = 0 Print "All locations written to." ' Tell what is going on. ' ' Now we read that data back. If returned data is all 255s check your circuit. ' Counter = 100 ' initialize loop counter. I2c_eeprom_address_desired = 0 ' We start reading at EEPROM address zero. Do Call I2c_ram_read(i2c_eeprom_address_desired) ' Call sub to read from device. Print "Location: " ; Counter ; "=" ; Data_work_var ' Display data read from device. Incr I2c_eeprom_address_desired ' Increment address counter. Decr Counter ' Decrement loop counter. Waitms 250 ' A little delay to watch the numbers go by. Loop Until Counter = 0 Print "All locations read back, program ends." ' Tell what is going on. End ' Program ends. '********************************************************************** '** Define Subroutines ** '********************************************************************** Sub I2c_ram_write(address_desired As Word , Content As Byte) ' Writes data to the I2C EEPROM. I2c_eeprom_address_low_byte = Low(address_desired) ' Extract low byte of address to be written. I2c_eeprom_address_high_byte = High(address_desired) ' Extract high byte of addesss to be written. I2cstart ' Send I2C Start. I2cwbyte Eeprom_chip_write_command ' Select MicroChip EEPROM device type, address and write bit. I2cwbyte I2c_eeprom_address_high_byte ' Send high address to write to. I2cwbyte I2c_eeprom_address_low_byte ' Send low address to write to. I2cwbyte Content ' Send the data to be written. If Err = 0 Then ' check status of operation. Print "Write is good: Location: " ; Address_desired ' Report success. Else ' or Print "Write failed: Location: " ; Address_desired ' Report failure. End If I2cstop ' All we want to do is done. Waitms 10 ' Wait for write to finish up. End Sub Sub I2c_ram_read(address_desired As Word) ' Reads data from the I2C EEPROM. I2c_eeprom_address_low_byte = Low(address_desired) ' Extract low byte of address to be read. I2c_eeprom_address_high_byte = High(address_desired) ' Extract high byte of address to be read. I2cstart ' Send I2C Start.. I2cwbyte Eeprom_chip_write_command ' Select MicroChip EEPROM device type, address and write bit I2cwbyte I2c_eeprom_address_high_byte ' Send high byte of address to read from. I2cwbyte I2c_eeprom_address_low_byte ' Send low byte of address to read from. I2cstart ' Issue another start sequence. I2cwbyte Eeprom_chip_read_command ' Select MicroChip EEPROM device type, address and read bit I2crbyte Data_work_var , Nack ' Read data from desired location in chip. If Err = 0 Then ' Check status of operation. Print "Read is good: " ; ' Report success. Else ' or Print "Read failed: " ; ' Reeort failure.0 End If I2cstop ' All we want to do is done. End Sub