Menu

I2C Address Confusion.

Help
mkstevo
2018-12-04
2018-12-05
  • mkstevo

    mkstevo - 2018-12-04

    Not a problem with GCB as such, but I'm a little confused by the addressing of a 24C16 Eeprom device.

    I've got the LCD discovery program running on my 16F1829 with a serial LCD, and have this connected to my 24C16. When the program is run, it reports:

    ID: 0xA0
    EEProm_Device

    ID: 0xA2
    EEProm_Device

    ID: 0xA4
    EEProm_Device

    ID: 0xA6
    EEProm_Device

    ID: 0xA8
    EEProm_Device

    ID: 0xAA
    EEProm_Device

    ID: 0xAC
    EEProm_Device

    ID: 0xAE
    EEProm_Device

    If I connect a small RTC module from China with a DS3231 and an on board 24C32, when the program is run it reports:

    ID: 0xAE
    EEProm_Device

    ID: 0xD0
    DS1307 RTC

    By soldering the links on the RTC module for the EEProm address, I can set the address of the 24C32 for any of the addresses from A0 to AE. I only ever see one address for the 24C32 on this module.

    I've tried pulling the address lines high on the 24C16, tried pulling them low, tried all combinations, but it still responds to all the addresses A0 to AE. I've tried a 24C16WP and a U02016B (Atmel device that should be either a 24C16 equivalent or 24C04) which give the same results as the 24C16.

    Being new to I2C, is this normal? Which of the addresses should I choose? Have I done something daft in how I've connected it and need to 'activate' the address lines?

     
  • David Stephenson

    It would seem that the top 4-bits of the address are set to A (1010) and the next 3-bits are the MSB of the eeprom memory (so can take any value) the last bit is 0 for write and 1 for read.
    Seems a bit dodgy as any I2C device (connected to the same pins) with a top 4-bits of its address = 1010 could be woken up and addressed inadvertently.
    So the I2C discovery is working correctly.

     
  • Anobium

    Anobium - 2018-12-04

    If I can advise. Is there an Alternative I2C Discovery for that part?

    Why? When I wrote the initial discovery I (stupidly) assumed I would be able to maintain the look up of devices... this update prooved too hard. So, I wrote the Alternative I2C Discovery which simply displays active I2C port addresses. Is there a version for that part?

    Always pull i2c high. I used 4k but anything between 2k and 4k should work.

    I have not used a 24C16 but the adresses between 0xA0and 0xAE are the write address of the banks of EEPROM.
    - So, write and read data A0 and AxA1 should be different to the write and read data to and 0xA2 and 0xA3. Try, reading and writing to the different loctions.

     
  • mkstevo

    mkstevo - 2018-12-04

    I'm not sure about the 'Alternative I2C Discovery'. I simply tweaked the file from the demo folder: I2CSoftwareDiscovery to_LCD_ATMega8 so that it worked on a 16F1825, and output the display to a serial LCD display.

    I have 4k7 pull up resistors on my I2C bus. I did try 1k but that made no difference.

    I had wondered if the memory 'banks' might be on the different device IDs. I modified the Discovery demo so that it wrote a Byte into an address, and then read it back to see if it was actually working, and that did seem to write and read, to each of the device IDs. I'll have to try to write and read a differing value to each location tomorrow. I think the version I've left running overnight is clocking through each memory location, but writing the same value to each.

    It does seem odd that it is (not) addressed in that way, but if it is, it is. It might explain why some versions of the parts don't show the A0, A1 or A2 connections on pins 1, 2 and 3.

    Thanks for the suggestions. I'll have to order some DIL versions of the 24C32 to try.

    I was simply considering getting to grips with some off chip EeProm for storing a few program parameters, run counts and the like. Thinking of the write life of the EeProm on the 16F1825/1829 being limited, I wondered if I could extend the device lifetime by using external memory. I think the lifetime of my devices, even using the on chip EeProm, should be in the region of a few years, after which it isn't unreasonable to be able to sell the customer a new chip anyway, but if I can improve the lifetime by using external memory, I'd quite like to.

     
  • David Stephenson

    The EEPROM lifetime is a bit confusing and as I do store backup variables in the eeprom (in case of a power outage) I researched the problem.
    Microchip generally say that each byte will typically stand 100k erase/write cycles - so if you're not storing many bytes - moving the write byte address around would make it difficult to exceed this.
    The other consideration is if you have some bytes that have data stored, but are not frequently re-written the data could be lost after 10M read/writes to other bytes in the EEPROM ( If you erase and write 256 bytes this is counted as 256 erase/writes towards your 10M).

    I have never found pull-ups critical 4k7 seems good enough, if the device is close to the chip even the internal weak pull-ups will suffice (that is if there is not much capacitance in the clock/data lines)..

     

    Last edit: David Stephenson 2018-12-05
  • Chris Roper

    Chris Roper - 2018-12-05

    @David and mkstevo

    Have you considered using EERAM
    https://www.microchip.com/design-centers/memory/serial-eeram

    It is Serial RAM with EEPROM backup.

    You just write as if it were RAM and the device takes care of the rest by only writing to the EEPROM if it detects a power fail condition and It automatically restores the RAM on power Up.

    So it only uses write cycles in the event of an actual power fail, rather than a scheduled basis.

    There is a Library for it in GCBASIC along with examples.

    Cheers
    Chris

     

    Last edit: Chris Roper 2018-12-05
    • mkstevo

      mkstevo - 2018-12-05

      Given the low cost of the EERAM devices, I've ordered a few to 'play' with. Thanks for pointing them out.

      So far, I've had no failures of EeProm within the PIC devices I use (mostly the 16F1829 or 1825) I generally store a few program parameters, a serial number and a few other things that are mostly static. and don't change more than once or twice a year. I have a few programs which store more items that change around 50 times per day, but 100,000 write cycles / 50 per day = 2000 days = 5 years. So I expect to see some orders for replacement devices in a year or two!

       
  • mkstevo

    mkstevo - 2018-12-05

    Thanks again for all the suggestions.

    I will look at the Serial EeRAM device, it does sound ideal. Especially so if there is a library for it!

    Having looked again at this, it appears as though the 24C16 has it's EePROM split into 8 banks of 255 bytes, each bank is addressed through the addresses A0 - AE, in 'even numbered blocks' so A0, A2, A4, A6, A8, AA, AC and AE.

    The code I have used to access this is:

    '''A demonstration program for GCGB and GCB.
    '''--------------------------------------------------------------------------------------------------------------------------------
    '''This program searches for I2C devices and display their adresses to a serial LCD.
    '''This program uses the GCB software TWI implementation for the I2C protocol.
    '''@author  TheoL plus works of EvanV
    '''@licence GPL
    '''@version 1.0a
    '''@date    23.02.15
    '''   Modified for a Serial LCD Mark Stevenson 4/12/2018
    '''********************************************************************************
    
    ; ----- Configuration
    #chip 16F1825,32
    #option explicit
    
    ; ----- Define Hardware settings
    ' Define I2C settings - CHANGE PORTS
    #define I2C_MODE Master
    #define I2C_DATA PORTC.1   'Dat Pin 9
    #define I2C_CLOCK PORTC.2  'Clk Pin 8
    #define I2C_DISABLE_INTERRUPTS ON
    
    ' turn on the RS232 and terminal port.
    ' Define the USART port
    #define USART_BAUD_RATE 9600
    #define USART_BLOCKING
    #define SerOutPort portC.4 'Ser Pin 6
    
    'Defines a serial LCD connection. Use the Serial_LCD_16F1825.gcb and LCD.
    
    #include <I2CEEPROM.h>
    
    Dim Read_Value As Byte
    Dim DeviceID   As Byte
    Dim Mem_Loc    As Byte
    
    Let Mem_Loc = 0
    
    Wait 500 mS
    
    ; ----- Main body of program commences here.
    SerLocate 0,0
    HSerPrint "**Software TWI**"
    SerLocate 1,0
    HSerPrint "I2C Dev. Search "
    Wait 1000 mS
    SerCls
    Do
      For deviceID = 0 to 255
         I2CStart
         I2CSend ( deviceID )
         If I2CSendState = True then
            SerLocate 0,0
            HSerPrint "ID: 0x"
            HSerPrint hex(deviceID)
            Select Case deviceID
               SerLocate 1,0
               case 48
                  HSerPrint "DS2482_1Channel "
               case 64
                  HSerPrint "IC2/Serial_Expan"
               case 68
                  HSerPrint "IC2/Serial_Expan"
               case 72
                  HSerPrint "PCF8574 8bit I/O"
               case 74
                  HSerPrint "PCF8574 8bit I/O"
               case 76
                  HSerPrint "PCF8574 8bit I/O"
               case 78
                  HSerPrint "PCF8574 8bit I/O"
               case 96
                  HSerPrint "GCB Slave Device"
               case 144
                  HSerPrint "PCF8591 AD/DA   "
               case 160
                  HSerPrint "EEProm          "
                  TestEeProm
               case 162
                  HSerPrint "EEProm          "
                  TestEeProm
               case 164
                  HSerPrint "EEProm          "
                  TestEeProm
               case 166
                  HSerPrint "EEProm          "
                  TestEeProm
               case 168
                  HSerPrint "EEProm          "
                  TestEeProm
               case 170
                  HSerPrint "EEProm          "
                  TestEeProm
               case 172
                  HSerPrint "EEProm          "
                  TestEeProm
               case 174
                  HSerPrint "EEProm          "
                  TestEeProm
               case 198
                  HSerPrint "AXE033 I2C LCD  "
               case 208
                  HSerPrint "DS1307 RTC      "
               case 248
                  HSerPrint "FRAM_Device     "
               case else
                  HSerPrint "Unknown_Device  "
            End select
            deviceID++
            wait 500 mS
         Else
            SerLocate 0,0
            HSerPrint "ID: 0x          "
            SerLocate 0,6
            HSerPrint hex(deviceID)
            SerLocate 1,0
            HSerPrint "    Searching   "
         End if
         I2CStop
      next
      Let Mem_Loc = Mem_Loc + 2
    loop
    
    
    Sub SerLocate(L_Line,L_Pos As Byte)
    
        If L_Line = 0 Then
          Let L_Pos = L_Pos + 128
        Else
          Let L_Pos = L_Pos + 192
        End if
        HSerSend 254 'Command follows
        HSerSend L_Pos
        Wait 10 mS
    
    End Sub
    
    Sub SerCLS
        HSerSend 254 'Command follows
        HSerSend 1   'CLS
        Wait 30 mS   'Mandatory after a CLS command
    End Sub
    
    Sub TestEeProm
        For Mem_Loc = 0 to 255
          WriteByte(DeviceID,Mem_Loc,Mem_Loc)
          Wait 10 mS
          Let Read_Value = ReadByte(DeviceID,Mem_Loc)
          SerLocate 0,9
          If Read_Value = Mem_Loc Then
            HSerPrint "S:"
          Else
            HSerPrint "F:"
          End If
          HSerPrint Read_Value
          SerLocate 1,9
          HSerPrint "L:"
          HSerPrint Mem_Loc
        Next
        SerLocate 0,9
        HSerPrint "     "
        SerLocate 1,9
        HSerPrint "     "
    End Sub
    
    Sub WriteByte(In EePDev, In EePAddr As Byte, In WByte As Byte)
      EeProm_Wr_Byte( EePDev, EePAddr , WByte)
       'NOTE the original line from the I2CEEPROM header file has an error. eepAddr MUST be a Byte value.
       'Correct: eeprom_wr_byte (in eepDev as byte, in eepAddr as Byte, in eepromVal as byte)
      'Wrong: eeprom_wr_byte (in eepDev as byte, in eepAddr as word, in eepromVal as byte)
    
    End Sub
    
    Function ReadByte(In EePDev As Byte, In EePAddr As Byte)
      Dim EePromVal As Byte
      Let EePromVal = 0
      EeProm_Rd_Byte(EePDev, EepAddr, EePromVal)
      Let ReadByte=EePromVal
      'eeprom_rd_byte(in eepDev as byte, in eepAddr as byte, out eepromVal as byte )
    End Function
    

    This is a modified version of the file: I2CSoftwareDiscovery to_LCD_ATMega8 from the demo folder.

    To test the correct operation, I'm using a Hi-Lo All100 programmer which after the program has been run at least once, shows the contents of memory as having the values 0-255 sequentially in each of the blocks of memory.

    So in conclusion, I was confused by the multiple addresses found by the Discovery program, I then made the mistake of trying to use a word variable for the eepAddr value in 'eeprom_wr_byte' which I'd copied from the I2CEEPROM header file. This added to the confusion as it messed everything up big time and the storage location went haywire.

     

    Last edit: mkstevo 2018-12-05
  • mkstevo

    mkstevo - 2018-12-05

    With the program slightly modified to show the I2C device address at the start and end of each of the banks, here is a capture of part of the data read back by the All100 programmer. Byte 0 and byte 255, have the bank address stored within them showing the start and end of each bank.

     

Log in to post a comment.

Want the latest updates on software, tech news, and AI?
Get latest updates about software, tech news, and AI from SourceForge directly in your inbox once a month.