Tuto. 9 - I2C Eeprom

PIC tutorial 9 - I2C Eeprom

Print
Category: PIC Tutorials
Published Date Written by Francois

Tutorial 9

Fig. 1 Board 4 with I2C Eeprom and hexa display

Description:

This tutorial is very similar to the previous one, which covered Microwire  eeprom. The difference is that the memory chip used here has an I2C interface, instead of Microwire. The tutorial will write a byte at a given address in memory, and read it back regularly to display it on an hexadecimal 2 digit display.

You will need a processor board, a power supply, the I2C Eeprom board and the hexa display board.

You can download the files for this tutorial in the zip file pic_tutorial9.zip.

The boards can be powered by one of the PSU boards (powered from USB port), or between 1.8 and 5V, depending on the memory chip used.

Requirements:

Processor boardAny board (board 4 in example)

Extension(s)I2C Eeprom 24Cxx

 Hexa display

Power supplyPSU 1, 2 or 3. Depends on board used.

LanguageCCS C

ProgrammerPicKIT 2


Program:

#define board_id 4 // define processor board used

#define Chip_24Cxx 2464 // define memory chip used
#include "../lib/Boards/mainboard.c" // load processor board library
#include "../lib/Memory/24Cxx.c" // load I2C eeprom memory

#priority RTCC

BYTE cmpt1,a;

#int_rtcc void Timer0Interrupt ( void ) {
  if (cmpt1 != 0) cmpt1--;
}

void main() {
  boot_up();
  cmpt1 = 0;
  setup_timer_0 ( RTCC_DIV_256 | RTCC_8_BIT );
  enable_interrupts ( INT_RTCC ); // enable Timer0 interrupt
  enable_interrupts ( GLOBAL ); // enable all interrupts
  write_24Cxx(7,0xa7); // writes a7 to address 7 (10100111)
  while (TRUE) {
    if (cmpt1 == 0) {
      a = read_24Cxx(7);
      #if ((board_id == 1) || (board_id == 2)) // output on port b for board 1 or 2
        output_a(a);
      #else
        output_b(a);
      #endif
      cmpt1=100;
    }
  }
}

The program defines the processor board used and the type of memory chip fitted on the I2C eeprom board (24C64 in the example). It can be defined from 2402 up to 24256.

We then loads the libraries for the processor and I2C eeprom. The generic I2C library was already covered in tutorial 4.

Once all libraries are loaded, we declare variables to hold the counter for timer 0 interrupts and the data read from the eeprom.

The interrupt for timer 0 is then declared. It just decrements the assigned counter if different than 0.

The processor board is then initialised. Timer 0 is setup as an 8 bit counter, with a prescaler of 256.
The interrupts are enabled and the address is written with a byte in the eeprom (address 7 with value of A7 in the example).
The main loop is then entered: we simply check the interrupt counter, and if 0, we read the same address in the eeprom. The byte is sent to port b where it is displayed on the hexa display. We reset the interrupt counter and loop again.

Now the I2C eeprom 24cxx library.

#ifndef _24Cxx_LIB
  #define _24Cxx_LIB
  #include "../lib/Common/I2C.c" // load generic I2C library
  #ifndef Chip_24Cxx // define a default memory chip if none already defined
    #define Chip_24Cxx 2464 // 2402, 2408, 2416, 2432, 2464, 24256 chip. Default to 2464
  #endif

  void write_24Cxx(WORD address, BYTE data) { // write a byte at address
    BYTE status; // byte to check memory chip has finished write process
    i2c_start();
    i2c_write(I2C_eeprom);
    #if (Chip_24Cxx > 2416) // if chip greater than 8Kbytes, send address as 2 bytes
      i2c_write(address>>8); // send MSB of 16 bits address
    #endif
    i2c_write(address);
    i2c_write(data); // then sends data to write to eeprom
    i2c_stop(); // start eeprom write cycle
    i2c_start();
    status=1; // wait for chip to finish write cycle
    while(status==1) { // status will return 0 when chip returns ack
      i2c_start();
      status=i2c_write(I2C_eeprom);
    }
    i2c_stop(); // ends I2C communication
  }

  BYTE read_24Cxx(WORD address) { // returns byte from address
    BYTE data;
    i2c_start(); // sends first address to read
    i2c_write(I2C_eeprom);
    #if (Chip_24Cxx > 2416) // address as 2 bytes for memory greater than 8Kb
      i2c_write(address>>8); // send MSB of 16 bits address
    #endif
    i2c_write(address);
    i2c_start(); // restart to go into read mode
    i2c_write(I2C_eeprom+1); // address chip in read mode
    data=i2c_read(0); // reads byte
    i2c_stop();
    return(data);
  }
#endif

First weload the I2C library, as the library will use I2C functions to manage the eeprom.

The chip used is checked, and defined by default to a 24C64.

We then have a list of functions to manage the memory chip:

  • write_24Cxx: sends a byte to the specified address. The upper byte of the address is only sent on chip above 2416. Smaller memory requires the address to be sent as 1 byte. After the first I2C_stop, the write sequence is started in the chip. During that time, the chip is 'offline', and will not return an ack if addressed. This is to allow the chip to finish writing before anything else can happen. We could just wait 5ms, which is the longuest time it would take, but it is usually much faster, so we poll the chip until we get an ack back, which indicate the write sequence is finished.
  • read_24Cxx: reads the byte from the specified address.

Compile the project and program the target with a PicKIT 2 programmer for example. Connect the processor board to the I2C Eeprom board with the I2C bus and the hexa display on port B. Make sure SW1 on the memory board is setup to the I2C_eeprom address defined in I2C_Addr.h.

Power up the boards.
The chip will be written with the byte, and then that same address is read and is displayed on the hexa display.

To change chip type, just define Chip_24Cxx with the desired value and recompile. The program is then set for that chip. It makes a difference only when switching from 2416 to 2432, where the address is changed from an 8 bits value to a 16 bits one.


Files and links:

Tutorial 9 source files.
Processor board 4.
I2C Eeprom board.
Hexa display board.

Post your comments...

    Copyright 2011. Poker Games. Copyright © 2012 riaDesign