Shop OBEX P1 Docs P2 Docs Learn Events
HELP - Interrfacing to I2C Chips using Basic_I2C_Driver — Parallax Forums

HELP - Interrfacing to I2C Chips using Basic_I2C_Driver

hawkeye89736hawkeye89736 Posts: 6
edited 2012-11-23 19:36 in Propeller 1
Hello,
I am still fairly new to the Propeller Chip and the Spin language, but have used the Basic chip. I am working on a model railroad project trying to control LED indications of track turnout switches (using DPDT switches generating 5v signals for input to microcontroller). I am going to be using Microchip's MCP23008 I/O expander to give me the neccessary I/Os for this project (52 I/Os total). This IC uses the I2C protocol and right now I am trying to "play" with controlling the EEPROM using the Basic_I2C_Driver from the OBEX. I can't seem to get the test program I am writing to read the EEPROM. I will attach my code below. As I said, I am farily new to the Spin language, but I think I am using either the I2C driver wrong, or the serial terminal wrong (using serial terminal to display what is read). Can anyone help me figure out what is going wrong? I am using the Parallax P8X32A QuickStart board. If you would like to know what I am planning to do for the whole project, let me know and maybe we can find a better solution. I have a few lines commented out due to trying different methods. It seems like I am pulling some information using the read command, but it does not change when the Write data is changed. Also, when I review the driver, it looks like there is nothing in the read/writebyte subs that send the data to the I2C bus.

Thanks,
Josh
CON
   
  _clkmode = xtal1 + pll16x
  _xinfreq = 5_000_000
  eepromAddress = $7000

VAR
   byte buffer[32]
   byte wtf

OBJ
   i2c : "Basic_I2C_Driver_1.spin"
   pst : "Parallax Serial Terminal.spin"

'PRI readIt
  ' if i2c.ReadPage(i2c#BootPin, i2c#EEPROM, eepromAddress, @buffer, 32)
  '  abort ' an error occurred during the read

'PRI writeIt | startTime
 ' if i2c.WritePage(i2c#BootPin, i2c#EEPROM, eepromAddress, @buffer, 32)
 '  abort ' an error occured during the write
 ' startTime := cnt ' prepare to check for a timeout
 ' repeat while i2c.WriteWait(i2c#BootPin, i2c#EEPROM, eepromAddress)
 '  if cnt - startTime > clkfreq / 10
 '     abort ' waited more than a 1/10 second for the write to finish
             
PUB Main

 wtf := 0
 i2c.Initialize(28)
' i2c.Start(28)

' i2c.WritePage(28,%1010,%000,$7333,1)
 i2c.Writebyte(28,%111,$11,%01010111)
 'i2c.WriteWait(28,%1010,%000)

'wtf := i2c.ReadPage(28,%1010,%000,$7333,1)
 wtf := i2c.ReadByte(28,%000,$12) '6C
 'i2c.Stop(28)



 pst.Start(115200)
repeat
 waitcnt(clkfreq + cnt)
 pst.Str(String ("test"))
 pst.Str(wtf)
  pst.NewLine
 waitcnt(clkfreq + cnt)
 pst.NewLine

Comments

  • kuronekokuroneko Posts: 3,623
    edited 2012-11-23 16:46
    This IC uses the I2C protocol and right now I am trying to "play" with controlling the EEPROM using the Basic_I2C_Driver from the OBEX. I can't seem to get the test program I am writing to read the EEPROM.
    Even when playing around you should adhere to the API. writeByte for example takes the clock pin, the device address, the memory location and the byte to be written. Usually only the last two are user-serviceable (given a specific device on a specific pair of pins). Which changes your code into something like this:
    CON
      _clkmode = xtal1 + pll16x
      _xinfreq = 5_000_000
    
      eepromAddress = $7000
      pin = 28
      
    VAR
      long  wtf
    
    OBJ
      i2c : "Basic_I2C_Driver_1"
      pst : "Parallax Serial Terminal"
                 
    PUB Main
    
      pst.Start(115200)
      waitcnt(clkfreq*3 + cnt)
      
      i2c.Initialize(pin)
    
      i2c.Writebyte([COLOR="#D3D3D3"]pin[/COLOR], [COLOR="#D3D3D3"]i2c#EEPROM[/COLOR], [COLOR="#FFA500"]eepromAddress[/COLOR], [COLOR="blue"]$6C[/COLOR])
      repeat while i2c.WriteWait([COLOR="#D3D3D3"]pin[/COLOR], [COLOR="#D3D3D3"]i2c#EEPROM[/COLOR], [COLOR="#FFA500"]eepromAddress[/COLOR])
        pst.char(".")
    
      wtf := i2c.ReadByte([COLOR="#D3D3D3"]pin[/COLOR], [COLOR="#D3D3D3"]i2c#EEPROM[/COLOR], [COLOR="#FFA500"]eepromAddress[/COLOR])
      
      repeat
        waitcnt(clkfreq + cnt)
        pst.Str(String ("test", 13))
        pst.dec(wtf)
        pst.NewLine
        waitcnt(clkfreq + cnt)
        pst.NewLine
    
    You can now play around with the orange and blue parameters. HTH. Note that the return parameter should at least be a word to distinguish between error code (-1) and real data. With a byte result of $FF you wouldn't know it this is just $FF or a cut down -1 ($FFFFFFFF).

    Also, when you post code please wrap it in [noparse]
    
    [/noparse] tags.                        
  • hawkeye89736hawkeye89736 Posts: 6
    edited 2012-11-23 17:30
    Thanks. I thought I might be entering the EEPROM info wrong. I was working on the code below to use on the I/O expander, would/should I put a writewait command in between all of my writebytes? I am assuming that I am now writing the writebyte command properly for the I/O device so that the IODIR register of the IO1 expander would be written with $00. I used binary in the code for an easier way for me to keep track of what I am setting up the chip for. Thanks again for your help.
    {Code to interface Prop to I2C portion of MCP23008 General Purpose I/O expander.
    Using to control LEDs for indication of N scale track switch direction.}
    
    
    CON
            _clkmode = xtal1 + pll16x                                               'Standard clock mode * crystal frequency = 80 MHz
            _xinfreq = 5_000_000
    
            IO1 = %0100111                                             'GP I/O 1 Address
    
            IODIR = $00                            'Register Addresses for MCP23008
            IOPOL = $01                            'See data sheet for more info
            GPINTEN = $02
            DEFVAL = $03
            INTCON = $04
            IOCON = $05
            GPPU = $06
            INTF = $07
            INTCAP = $08 'Read ONLY!
            GPIO = $09
            OLAT = $0A
    
            SDAPin = 10                             'SDA and SCL Pin Declaration
            SCLPin = 9
    
    OBJ
    
      i2c : "Basic_I2C_Driver_1"
      pst : "Parallax Serial Terminal"
    Var
    
      word Data1                                                        'Data Block 1 Var                                                                                          
      word Data2                                                        'Data Block 2 Var
    
    PUB Main
    
      'Set up device.
      i2c.Initialize(SCLPin)
      i2c.WriteByte(SCLPin,IO1,IODIR,%00000000)
      i2c.WriteByte(SCLPin,IO1,IOPOL,%00000000)
      i2c.WriteByte(SCLPin,IO1,GPIO,%10101010)
    
      Data1 := i2c.ReadByte(SCLPin,IO1,GPIO)
      pst.Start(115200)
      waitcnt(clkfreq + cnt)
      pst.dec(Data1)
    
    
  • kuronekokuroneko Posts: 3,623
    edited 2012-11-23 17:37
    ... should I put a writewait command in between all of my writebytes?
    I'd assume that the I/O expander is fast enough that you can get away without it. That said, having it in there doesn't hurt. The wait in the example simply covers the programming time for the EEPROM which is long enough to get in the way if ignored.
  • Clive WakehamClive Wakeham Posts: 152
    edited 2012-11-23 17:42
    MCP23008 - Archive [Date 2012.11.24 Time 12.00].zip

    Hi hawkeye89736 ...

    Last year I bought a couple of the MCP23008 IC's, and wrote a rudimentary object for it.
  • hawkeye89736hawkeye89736 Posts: 6
    edited 2012-11-23 18:04
    Clive, thanks for the file. I haven't looked at the OBEX for anything specific to the MCP23008s. Why did you add the write/read location to the I2C driver as opposed to just using the writebyte?
  • kuronekokuroneko Posts: 3,623
    edited 2012-11-23 18:32
    ... add the write/read location to the I2C driver as opposed to just using the writebyte?
    Looks like the old driver always used 2 byte addressing whereas the new one allows for single byte mode as well given the right flags being used.
  • Clive WakehamClive Wakeham Posts: 152
    edited 2012-11-23 19:21
    Clive, thanks for the file.

    No problem.
    I haven't looked at the OBEX for anything specific to the MCP23008s.
    Why did you add the write/read location to the I2C driver as opposed to just using the writebyte?

    I didn't. The original I2C driver was modified by James Burrows, and he added a couple extra methods (and modified a couple of other ones) . The extra methods are used in my objects. Mike Green in the meantime had updated his object.

    I will have to sit down and closely examine the updated object by Mike Green since my objects run with the modified James Burrow's object.
  • Clive WakehamClive Wakeham Posts: 152
    edited 2012-11-23 19:36
    kuroneko wrote: »
    Looks like the old driver always used 2 byte addressing whereas the new one allows for single byte mode as well given the right flags being used.

    The old driver was basically for addressing EEPROM's etc, where as the latest version was modified for non-memory devices -- according to the version log.

    Some of my objects use the James Burrows added on methods, so I will more likely have to insert his code into my objects if I am going to use Mike Green's updated object.
Sign In or Register to comment.