Shop OBEX P1 Docs P2 Docs Learn Events
12c long eeprom addressing — Parallax Forums

12c long eeprom addressing

Chicago MikeChicago Mike Posts: 88
edited 2007-12-22 23:56 in Propeller 1
I'm converting a program I wrote from James Burrows i2c driver to Mike Greens Basic_i2c_Driver, and ironically have had no problems with converting usage for other i2c devices, (an RTC, and an I/O expander), but I'm having a really hard time converting fram read/writes, even though the basic_i2c_driver is designed for it. I know it has to do with the addressing somehow. Below is a basic program, which will always save the last value written to all the registers..... (A zero in this case. Below should write 0 1 0 in registers 0-2, instead it writes 0 0 0 to them. I'm a bit confused on the syntax of the writebyte and readbyte commands.

Below is the syntax in Mike Greens Comments:
WriteByte(SCL, devSel, addrReg, data)

I would anticipate the following string to write a 1 from register $02... But it doesn't work.....
writebyte(outil_scl_i2c, $A0, 2,1)

Below is my sample program. any help would be great, or a simple example. Thanks again!


CON
  Page1         =               %10100000               ' Fram Memory (2048bits) - Used for Good/Bad Status 1 byte per DMX Address 
  Page2         =               %10100010
  Page3         =               %10100100
  Page4         =               %10100110
  Page5         =               %10101000
  Page6         =               %10101010
  Page7         =               %10101100  
  outil_scl_i2c =                9  

OBJ
  i2c : "Basic_i2c_Driver"

PUB Mainline
  Write_config
  Read_Config

PUB Write_config | i
  i:=1                                                                          ' Start memory counting at 1
  i2c.WriteByte(outil_scl_i2c, Page7, ((i++*8)-8), 0)                                     ' Write byte to address 0 of page 7
  i2c.WriteByte(outil_scl_i2c, Page7, ((i++*8)-8), 1)                                     ' Write byte to address 1 of page 7
  i2c.WriteByte(outil_scl_i2c, Page7, ((i++*8)-8), 0)                                     ' Write byte to address 2 of page 7
  Read_config

PUB Read_config | i
  i:=1                                                                          ' Start memory counting at 1
  bValidation_enabled := i2c.readbyte(outil_scl_i2c, Page7,((i++*8)-8))         ' read byte to address 0 of page 7
  bHunt_on_time := i2c.readbyte(outil_scl_i2c, Page7,((i++*8)-8))               ' read byte of address 1 of page 7
  bRf_enabled := i2c.readbyte(outil_scl_i2c, Page7,((i++*8)-8))                 ' read byte of address 2 of page 7
  
  lcd.posdec(3,2,bValidation_enabled)
  lcd.posdec(3,7,bHunt_on_time)  
  lcd.posdec(3,12,bRF_enabled)


Comments

  • rjo_rjo_ Posts: 1,825
    edited 2007-12-21 04:23
    Chicago,

    Can't help you with i2c... but i love your icon... the little guy needs a propeller hat[noparse]:)[/noparse]

    Rich
  • Mike GreenMike Green Posts: 23,101
    edited 2007-12-21 04:31
    The write routines don't include a wait for the write to complete.
    See the example in the comments to show how the WriteWait call works.
  • Chicago MikeChicago Mike Posts: 88
    edited 2007-12-21 13:00
    I'll give it a run, but my understand was that with fram, because of the bus write speeds, that waits were not needed, which would be required with a standard eeprom.
  • Mike GreenMike Green Posts: 23,101
    edited 2007-12-21 15:39
    I didn't notice the comment about FRAM. Yes, the WriteWait is not necessary.

    What's the bit with the Page1 .. Page7? That may be your problem. I had assumed that you actually had 7 EEPROM devices present. Maybe you don't. EEPROMs (unless they're 2048 bytes or less) assume that you use 2 bytes for addressing before you have to use the device select code. The I2C routines assume you're using 2 byte addressing. You should be using the same device select code for all EEPROM accesses (as long as you have only one EEPROM device ... those larger than 64K appear to be multiple devices, each 64K). If you want to have "pages" of 256 bytes, just use multiples of 256 bytes for your addresses. ($000-$0FF, $100-$1FF, etc.).

    By the way, the routines in this I2C library assume that there's contiguous memory attached to the I2C bus and that what you have is a 512K address space (19 bits). The upper 3 bits get copied (OR'd) into the device select code so that you can seamlessly have up to 8 x 64K EEPROMs and treat them as a single device.

    Post Edited (Mike Green) : 12/21/2007 4:23:52 PM GMT
  • deSilvadeSilva Posts: 2,967
    edited 2007-12-21 16:15
    i2c.initialize(outil_scl_i2c) at the start could stabilze the situation, perhaps..
    You are aware that you do readConfig twice?
    The pin programmed address of your device is %110 ?
    When you talk of "registers" you mean "FRAM memory cells" I presume...
    As Mike already pointed out, the device will most likely become shortly unresponsive after WritePage has flagged STOP...

    Edit, BTW: What FRAM are you using... I do only find FRAMs with SPI interface

    Post Edited (deSilva) : 12/21/2007 4:45:02 PM GMT
  • Chicago MikeChicago Mike Posts: 88
    edited 2007-12-21 17:18
    The paging things was a terrible mess. I fixed that. Thanks Mike. I've rewritten this is a little test program with your suggestions and deSilva's and I'm having the same problem:

    CON
      outil_scl_i2c : 2
    
    OBJ
      i2c           : "Basic_I2C_Driver" 
    
    VAR
      byte bValidation_enabled
      byte bHunt_on_time
      byte bRf_enabled
             
    Pub Main
      i2c.Initialize(outil_scl_i2c) 
      i2c.Writebyte(outil_scl_i2c, $A0, $0000, 3)
      i2c.Writebyte(outil_scl_i2c, $A0, $0001, 4)
      i2c.Writebyte(outil_scl_i2c, $A0, $0002, 5)
      Read_config
    
    PUB Read_config
      bValidation_enabled := i2c.readbyte(outil_scl_i2c, $A0,$0000)        
      bHunt_on_time := i2c.readbyte(outil_scl_i2c, $A0,$0001)              
      bRf_enabled := i2c.readbyte(outil_scl_i2c, $A0,$0002)                 
    
      lcd.posdec(4,1,i2c.devicepresent(outil_scl_i2c,$A0))
    
      lcd.posdec(3,2,bValidation_enabled)
      lcd.posdec(3,7,bHunt_on_time)  
      lcd.posdec(3,12,bRF_enabled)
    
    



    So I would expect to write 3,4,5 to memory cells 0,1,2. Then I perform the read, and I display the variables back and I always get 5 5 5 not 3 4 5 as I'd expect. (Or whatever value I write last). to verify it was the write and not the read, I commented out the last two reads, and still read a 5 on the first variable. So this is something with the writebyte. I attempted to add a read wait with change of results. The address of my fram is $A0, you'll notice I used a devices present function (James BUrrows) and it finds it.

    Incidentally, I'm using a ramtron FM24CL16. Its spec is very close to the 24LC series from Microchip.... (Got it from Mouser).

    Thanks again!

    Post Edited (Chicago Mike) : 12/21/2007 5:24:22 PM GMT
  • deSilvadeSilva Posts: 2,967
    edited 2007-12-21 17:49
    So I read through the datasheet.
    (a) They do not say it's I2C I think the still fear the NXP lawyers smile.gif That was the reason I did not find it...

    (b) They use a slightly different protocol: You cannot use ReadPage or WritePage which add a 16-bits byte address.
    Just modify that to rather include what the datasheet calles "page" (3 bits) and "word" (8 bits) address.
    Reading is a little bit more tricky, but well explained in the data sheet.

    Edit: However: The FM24CL64 (and(256, 512) seem to have exactly the protocol as the 24C256 EPROMs

    Post Edited (deSilva) : 12/22/2007 11:51:34 AM GMT
  • Chicago MikeChicago Mike Posts: 88
    edited 2007-12-22 23:56
    Your completely right. I feel like I just bought the cheap knock off watch. The Rolex or Zony TV. Oh well, just for informational sake, I wrote byte routines that would handle this... below for anyone who runs into this problem like I did. You just have to go through the math and its not that hard. I'm using selective read and writes in this case. It would be really easy to modify to sequential if needed. Thanks again for everyones help.

    PUB Writeframbyte(SCL,devSel,addrReg,data) : ackbit  
    '' Run a selective write routine to write to RAMTRON fram. Addressing is designed for 2048*8(16K) chips.
       Start(SCL)                                                                ' Send a start
       ackbit := (ackbit << 1) | Write(SCL, (devSel|=(addrReg>>7|0)))            ' Take the top 4 bits of the 11 bit address and tack them on the bottom of the devSel. Add a 0 at the LSB for selective read.
       ackbit := (ackbit << 1) | Write(SCL, addrReg)                             ' Send the addrReg. The write will automaticly only send the 8 LSB, as required by spec.   
       ackbit := (ackbit << 1) | Write(SCL, data)                                ' Send the byte of data
       Stop(SCL)                                                                 ' Send a stop
       return ackbit
    
    PUB Readframbyte(SCL,devSel,addrReg) : data | ackbit 
    '' Run a selective read routine to read from RAMTRON fram. Addressing is designed for 2048*8(16K) chips.
    
       Start(SCL)                                                         ' Send a start bit
       ackbit := (ackbit << 1) | Write(SCL, (devSel|=(addrReg>>7|0)))     ' Take the top 4 bits of the 11 bit address and tack them on the bottom of the devSel. Add a 0 at the LSB for selective read.
       ackbit := (ackbit << 1) | Write(SCL, addrReg)                      ' Send the addrReg. The write will automaticly only send the 8 LSB, as required by spec.
       Start(SCL)                                                         ' Send another start bit.
       ackbit := (ackbit << 1) | Write(SCL, (devSel|=(addrReg>>7|1)))     ' Take the top 4 bits of the 11 bit address and tack them on the bottom of the devSel. Add a 1 at the LSB for selective read.
       data:=Read(SCL,NAK)                                                ' Finally read in the byte, but no ACK.. Kizz thats what the spec says to do. 
       Stop(SCL)                                                          ' Send a stop
       return data
    
    
Sign In or Register to comment.