I2C adressing issue

Discussion about the ZBasic language including the System Library. If you're not sure where to post your message, do it here. However, do not make test posts here; that's the purpose of the Sandbox.
Post Reply
hakha4
Posts: 47
Joined: 01 June 2009, 21:23 PM
Location: Moholm Sweden

I2C adressing issue

Post by hakha4 »

I'm trying to learn I2C playing with a miniboard with PFC 8574A from Futurelec but I'm a little confused how to address it. I've used the code in AN203 as a template where the adress is hex 70 if A0,A1,A2 is set to low. If I run the code below it stops in the : stat = I2CCmd(i2cChan, i2cAddr, 1 ,b, 1, b) row and never get's to the loop (just for checking if something happen's). Reading manual's for PFC 8574A says that the address is 7-bit and should be hex 38, (hex 70 assumes 8-bit) I've tried with hex 38 but same effect. It's probably simple but I can't figure out how . Any help is appreciated
Regards Hucke

Code: Select all


Private Const i2cChan as Byte = 0
Private Const i2cSpeed as Integer = 66



Private Const i2cAddr as Byte = &H70


Dim stat as Integer
Dim b as Byte

Sub Main()
Call OpenI2C(i2cChan, 0, 0, i2cSpeed)
' Write a value to the port expander, note that 1’s must
' be written for pins that will be used as inputs.
b = &Hf5 ' value chosen for example purposes only
stat = I2CCmd(i2cChan, i2cAddr, 1 ,b, 1, b)

Do
call blinkleds()'just to see if processor is working
debug.print stat & "   " & b
Loop
End Sub

Public Sub BlinkLEDs()

    Const GreenLED As Byte = 26
    Const RedLED As Byte = 25

    Const LEDon As Byte = 0
    Const LEDoff As Byte = 1

    ' Red pulse.
    Call PutPin(RedLED, LEDon)
    Call Delay(0.07)
    Call PutPin(RedLED, LEDoff)

    Call Delay(0.07)

    ' Green pulse.
    Call PutPin(GreenLED, LEDon)
    Call Delay(0.07)
    Call PutPin(GreenLED, LEDoff)

    Call Delay(0.07)

End Sub
dkinzer
Site Admin
Posts: 3120
Joined: 03 September 2005, 13:53 PM
Location: Portland, OR

Re: I2C adressing issue

Post by dkinzer »

hakha4 wrote:If I run the code below it stops in the : stat = I2CCmd(i2cChan, i2cAddr, 1 ,b, 1, b) row and never get's to the loop
That is a symptom of a slave not answering. This could be because SDA/SCL are not connected correctly, because you're missing pullup resistors on SDA/SCL (use something in the range 2.2K to 4.7K) or that you're using the wrong slave address.

If you have the A2-A0 bits grounded on a PCF8574A, use the address &H70. If you actually have a PCF8574, the base address &H40. With regard the the PCF8574A, when the documentation refers to the value &H38, it is describing the 7-bit address not including the R/W bit that occupies position zero. If you include the eighth bit, the address value then becomes &H70.
- Don Kinzer
kranenborg
Posts: 57
Joined: 27 July 2009, 14:20 PM
Location: Groningen, The Netherlands
Contact:

Post by kranenborg »

Hej Hucke!

Not a direct answer maybe, but regarding the particular device type I would generally recommend a MCP23008 I/O expander, which is a much more modern device with active output drive capability (the PCF8574 devices can only sink some current in the mA range) and has much more options. I can provide for working example code if needed.

/Jurjen
hakha4
Posts: 47
Joined: 01 June 2009, 21:23 PM
Location: Moholm Sweden

Post by hakha4 »

Thank's Don for clarifying the addressing issue,I got that part now. I have a preassembled board with pullup resistors enabled so it should work. I'm on a train right now playing with the zx24 in a Stamp in class board so I cant measure that connections are ok but I should be able to solve the problem now that I know that code should work.

Jurjen! I've read datasheet and have ordered a few MCP23008 to test with but I'll be happy if you could give me a code sample to start with.

Regards Hucke
kranenborg
Posts: 57
Joined: 27 July 2009, 14:20 PM
Location: Groningen, The Netherlands
Contact:

Post by kranenborg »

Hi Hucke,

As an example use of the MCP23008 I/O expander; here follows a class definition for driving a 7-segment display. The code is used in an SCP1000-based altitude meter (I posted part of that code on this forum). The MCP23008 is used to sink LED current in my app (see the inverted bit patterns for each number definition) because I had only access to a common-anode 7-segment display, i.e. the outputs act as a current sink instead of a source. With a common cathode non-inverted output bit definitions would be used.

Code: Select all

Class Display_7seg

Public:

	Sub InitializeDisplay()
		initByteString(1) = 0
		initByteString(2) = 0
		initByteString(3) = 0
		Call OpenI2C(i2c_channel, 0, 0, i2c_speed_400KHz)
		i2cstat = I2CCmd(i2c_channel, i2c_address, 3, initByteString, 0, 0)
	End Sub

	Sub Display_MCP23008(ByVal number as Byte)
		Dim i2cData (1 to 2) As Byte
		Dim dispoutput As Byte
		Select Case number
		Case 0
			dispoutput = &B00000100
		Case 1
			dispoutput = &B11110101
		Case 2
			dispoutput = &B01011000
		Case 3
			dispoutput = &B01010001
		Case 4
			dispoutput = &B10110001
		Case 5
			dispoutput = &B00010011
		Case 6
			dispoutput = &B00010010
		Case 7
			dispoutput = &B01110101
		Case 8 
			dispoutput = &B00000000
		Case 9 
			dispoutput = &B00000001
		Case Else
			dispoutput = &B11111111
		End Select
		i2cData(1) = 9
		i2cData(2) = dispoutput
		i2cstat = I2CCmd(i2c_channel, i2c_address, 2, i2cData, 0, 0)
	End Sub

Private:

	Const i2c_channel As Byte = 0
	Const i2c_speed_400KHz As Byte = 10
	Const i2c_address As Byte = &B01000000
	Dim initByteString(1 To 3) as Byte
	Dim i2cstat as Integer

End Class

Regards,
Jurjen

EDIT: text slightly changed since non-inverted outputs are used.
Last edited by kranenborg on 19 April 2010, 6:27 AM, edited 1 time in total.
dkinzer
Site Admin
Posts: 3120
Joined: 03 September 2005, 13:53 PM
Location: Portland, OR

Post by dkinzer »

Here is a modified version of the class that uses a table for the segment data.

Code: Select all

Class Display_7seg

Public:

   Sub InitializeDisplay()
      initByteString(1) = 0
      initByteString(2) = 0
      initByteString(3) = 0
      Call OpenI2C(i2c_channel, 0, 0, i2c_speed_400KHz)
      i2cstat = I2CCmd(i2c_channel, i2c_address, 3, initByteString, 0, 0)
   End Sub

   Sub Display_MCP23008(ByVal number as Byte)
      Dim i2cData (1 to 2) As Byte
      Dim dispoutput As Byte

      ' limit the input value
      If (number > 10) Then
         number = 10
      End If
      dispoutput = segData(number + 1)
      i2cData(1) = 9
      i2cData(2) = dispoutput
      i2cstat = I2CCmd(i2c_channel, i2c_address, 2, i2cData, 0, 0)
   End Sub

Private:

   Const i2c_channel As Byte = 0
   Const i2c_speed_400KHz As Byte = 10
   Const i2c_address As Byte = &B01000000
   Dim initByteString(1 To 3) as Byte
   Dim i2cstat as Integer

   ' active low segment data
   Static segData as ByteVectorData ({
      &B00000100
      &B11110101
      &B01011000
      &B01010001
      &B10110001
      &B00010011
      &B00010010
      &B01110101
      &B00000000
      &B00000001
      &B11111111
  })
End Class
- Don Kinzer
Post Reply