Page 1 of 1
I2C adressing issue
Posted: 18 April 2010, 5:37 AM
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
Re: I2C adressing issue
Posted: 18 April 2010, 8:01 AM
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.
Posted: 18 April 2010, 8:14 AM
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
Posted: 18 April 2010, 9:52 AM
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
Posted: 18 April 2010, 11:13 AM
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.
Posted: 18 April 2010, 11:48 AM
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