Has anyone decoded the current I2C protocol? Any fixes available?
I have just spent many hours trying to figure out errors I was getting using a DS1307 and a 24LC256 - both use i2c.
I have discovered that the protocol is not perfect and multiple reads and writes to the same device simple did not work. The ACK handshaking is not right - I believe.
When I review the handshaking, using a protocol analyser, between the Master and the slaves, I see error in communications.
I have a work around. But, has someone fix the I2C hand shaking for ACK/NAK?
Thanks.
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Well that explains the weirdness I was getting.
Having issues with the MCP79410 rtc as well.
Two thoughts:
1. Slow down the system clock try 1Mhz.
2. Are the resistors near the last part in the i2c chain.
Neither worked.
It appears that Sda is not being released [tristated] at the end of a cycle.
see the images attached.
Scl = line 0 and 5
Sda = line 1 and 2
i2c = the I2c subroutines start [hi] and finish [low].
I am sharing the LCD data bus d4-d7 on c.0 - c.3 while holding EN [CS] low.
sub i2cWrite (in i2cDevice, i2cAddress, i2cData) #NR
'reg_status = RCSTA
'rcsta = 0 ' shutdown the serial port to share with the i2c bus
LCD_Enable = 0 ' Make sure the LCD will not be pestered with the i2c Writes on the LCD Databus
LCD_RS = 0
LCD_DB5 = 1
Rotate i2cDevice left Simple' *2 = << 1 ' is shifted left 1 because of The RW bit: $26 << 1 = $4C
i2cstart
I2CSend i2cDevice + I2C_Write_BIT ' Who + how
I2CSend i2cAddress ' Where to put it
I2CSend i2cData ' What to put there
I2CStop
RCSTA = reg_status
Rotate i2cDevice right Simple
I2C_DATA= 1 'trisC.0 = 1 ' I2C_DATA PORTc.0
trisC.3 = 1 ' I2C_CLOCK PORTc.3
LCD_DB5 = 0
end sub
Function i2cRead (in i2cDevice, i2cAddress)
Rotate i2cDevice left Simple ' *2 = << 1 ' is shifted left 1 because of The RW bit: $26 << 1 = $4C
'reg_status = RCSTA
'rcsta = 0 ' shutdown the serial port to share with the i2c bus
LCD_Enable = 0 ' Make sure the LCD will not be pestered with the i2c Writes on the LCD Databus
LCD_RS = 0
LCD_DB5 = 1
I2CStart
I2CSend i2cDevice + I2C_Write_BIT ' Who + how, Tell it where to read
I2CSend i2cAddress ' Where to GET it, Give it the location
I2CStop
I2CStart
I2CSend i2cDevice + I2C_Read_BIT ' Who + how, Tell it you want to read
I2CReceive i2cData ' What to GET from there
I2CStop
i2cRead = i2cData
RCSTA = reg_status
Rotate i2cDevice right Simple
I2C_DATA= 1 'trisC.0 = 1 ' I2C_DATA PORTc.0
trisC.3 = 1 ' I2C_CLOCK PORTc.3
LCD_DB5 = 0
end function
Dimitris seems to have a working example for I2CRecieve in his DS1307 routine here: https://sourceforge.net/p/gcbasic/discussion/579126/thread/1d3f96c9/ It appears that there is an extra I2CStop? in the I2CRead function. Restart doesn't look right, nor does the master Nack.
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
I have just discovered this. Send a few values, then read and then the lines are not in the correct state. I thought I had it resolved than I messed up.
My first issue... I need to confirm my decoding method is value. Can you decode the following please?
I get 20> 20> (means 0x40 is being sent twice, this is how my decoder works) will 0x20 as the 7 bits of number 0x40. So, I am assuming that IC2Send OK.
My decoder shows... request to device 0x40 (0x20 being the 7 bit address), requests 0x09 (09+), device responds with 0x20 (020<).... SO, where DID the F0+ come from? badly clocked data? I think so.
20> 09+ 20< F0+
Are you able to confirm these results. I do not want to be chasing my tail. :-)
And, you should reset you power to all devices prior to trying this. As when you get a protocol failure the Ic2 devices are all messed up.
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Anonymous
-
2013-10-02
Hi everyone,
I, too am having some trouble getting the 24LC256 to work over the I2C bus with a 16F88. I'm using the header file provided by Kent in the "Contributor Section." My rig is simply to send some text to the eeprom via a terminal (with a pause after each character), and then later turn around and read the eeprom to the terminal.
The code works perfectly for reading the eeprom, but I've been unable to write to it (garbage goes in). I've been working on it for a week now, tried many variations of both code and hardware but just can't get the write to work.
Any leads from other people? By the way, I had no trouble making it work reliably with some PICAXE chips, so it sure seems like it should be possible with GC Basic.
Thomas Henry
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Update from me. I will publish later today when I get home.
I have essentially re-written I2C.h from the start. There is something not quite right in the existing code. I am sure that it is our use of it but I tried and tried (four days) until I started the re-write on Sunday.
My findings on the existing code are very similar to others, the code leaves the SDA and/or CLK in the incorrect state and ACK/NACKS are not handled correctly for every device. Again, I am sure this could be my use of the functions but I gave up on the existing code.
So, I have taken Microchip App Note AN1488 and re-coded into GCB.
Last night, after only four hours of coding, I have four devices working. One Master and three different I2C devices. I have no errors and I can selectively choose read / writes between the devices. It essentially works. The new code splits byte send/read, bit send/read and ACK/NACK into different functions - this provides a greater level of flexibility and control to ensure this GCB I2C handler follows the device protocol correctly.
My test setup is:
16F1937 - Master
12LC256 - Eeprom
DS1307 - RTC & NVRAM
MCP23008 - Serial expander
and... a Picaxe 18M2... also, an I2C MASTER. I have been using this device as my baseline to ensure the new GCB I2C code complies with the device I2C protocol. Why did I do this? The Picaxe device write/reads to these devices with no issue. It is good to have a baseline!
So, I can release this code, so, others can test. I currently have all the functions called v2_IC2_[name] this provides uniqueness in the functions but I think I would replace the existing code base. What is the best way forward?
I also have written a couple of library functions to support this devices using the new I2C code. I have one for the EEPROM device (this supports Low-Density and High-Density devices as these have different addressing schemes), I will adapt the DS1307 that has been also published and I will write one for the MCP type devices.
Examples of the use of the new code base:
eeprom_wr_byte ( ug_addr , 0x44 ): 'write to EEPROM at ug_addr at address 0x44
This is supported by the function:
'.............................................................................
' Writes data to the EEPROM address
'.............................................................................
Sub eeprom_wr_byte ( addr, data_out)
'eeprom_wr_byte(addr,data_out); ' write data to addr EEPROM address
'generate Start COndition
v2_i2c_start
'send WRITE command
v2_i2c_writebyte( EEPROM_WR )
'comment the next line if a Low-Density (<=2kB) device is used
addrh = uf_shift ( addr, 8, >> )
addrl = addr & 0xff
'address MSB
'comment the next line if a Low-Density (<=2kB) device is used
v2_i2c_writebyte(addrh)
'address LSB
v2_i2c_writebyte(addrl)
'send data
v2_i2c_writebyte( data_out )
'initiate Stop Condition
v2_I2C_Stop
' ACK polling
v2_ack_poll( EEPROM_WR )
end sub
~~~~~
For the MCP23008 this works using the new code. My LEDS attached the MCP device light up....
' see the Data sheet for this protocol. there is not ACK/NACKS required.
v2_i2c_start
v2_i2c_writebyte( 0x40 )
v2_i2c_writebyte( MCP23008_IODIR )
v2_i2c_writebyte( 0x0 )
'initiate Stop Condition
v2_I2C_Stop
In my test code I write to the MCP device twice (once to set the port direction and then to set ports off), write to the EEPROM address #1, read the EEPROM address #1, write to the EEPROM address #2, read the EEPROM address #2, read the EEPROM address #1 then write to the MCP device once (to set ports on). This now works.
My code is currently full of serial debug... I promise to remove.
Anobium
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
However..... for those who have still got the original I2C.H - try this. Does this resolve the issues?
Save a copy of i2c,h and then edit i2c.h and change the file as follows:
'Constants (shouldn't change)
#define I2C_DATA_HIGH Dir I2C_DATA In
#define I2C_DATA_LOW Dir I2C_DATA Out: Set I2C_DATA Off
#define I2C_CLOCK_HIGH Set I2C_CLOCK On
#define I2C_CLOCK_LOW Set I2C_CLOCK Off
#define I2CStopped I2COldState
'Subs
Sub InitI2C
'Initialisation routine
'Release data and clock lines
I2C_DATA_HIGH
Dir I2C_CLOCK Out
I2C_CLOCK_HIGH
'Set old state flag (slave mode)
#if I2C_MODE = Slave
I2COldState = 255
#endif
End Sub
You should replace the CONSTANTS and the Sub routine.
For DS1307 and MCP23xxx devices I think you can just use I2CSend as normal. For the 24LC256 you need to send an additional acknowledgement (see device datasheet, section 7) at the end after the IC2Stop but I do not know how the existing code can do this. So, I think the existing code is limited to devices that do not need ACKNOWLEDGE POLLING.
Please test and post the results. This is a workaround, it is NOT the new code but something I discovered when I was trying to resolve my issues.
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Has anyone decoded the current I2C protocol? Any fixes available?
I have just spent many hours trying to figure out errors I was getting using a DS1307 and a 24LC256 - both use i2c.
I have discovered that the protocol is not perfect and multiple reads and writes to the same device simple did not work. The ACK handshaking is not right - I believe.
When I review the handshaking, using a protocol analyser, between the Master and the slaves, I see error in communications.
I have a work around. But, has someone fix the I2C hand shaking for ACK/NAK?
Thanks.
Well that explains the weirdness I was getting.
Having issues with the MCP79410 rtc as well.
Two thoughts:
1. Slow down the system clock try 1Mhz.
2. Are the resistors near the last part in the i2c chain.
Neither worked.
It appears that Sda is not being released [tristated] at the end of a cycle.
see the images attached.
Last edit: ofuzzy1 2013-09-30
Dimitris seems to have a working example for I2CRecieve in his DS1307 routine here: https://sourceforge.net/p/gcbasic/discussion/579126/thread/1d3f96c9/ It appears that there is an extra I2CStop? in the I2CRead function. Restart doesn't look right, nor does the master Nack.
I am in the same place.
I have just discovered this. Send a few values, then read and then the lines are not in the correct state. I thought I had it resolved than I messed up.
My first issue... I need to confirm my decoding method is value. Can you decode the following please?
I get 20> 20> (means 0x40 is being sent twice, this is how my decoder works) will 0x20 as the 7 bits of number 0x40. So, I am assuming that IC2Send OK.
The try,
My decoder shows... request to device 0x40 (0x20 being the 7 bit address), requests 0x09 (09+), device responds with 0x20 (020<).... SO, where DID the F0+ come from? badly clocked data? I think so.
20> 09+ 20< F0+
Are you able to confirm these results. I do not want to be chasing my tail. :-)
And, you should reset you power to all devices prior to trying this. As when you get a protocol failure the Ic2 devices are all messed up.
Hi everyone,
I, too am having some trouble getting the 24LC256 to work over the I2C bus with a 16F88. I'm using the header file provided by Kent in the "Contributor Section." My rig is simply to send some text to the eeprom via a terminal (with a pause after each character), and then later turn around and read the eeprom to the terminal.
The code works perfectly for reading the eeprom, but I've been unable to write to it (garbage goes in). I've been working on it for a week now, tried many variations of both code and hardware but just can't get the write to work.
Any leads from other people? By the way, I had no trouble making it work reliably with some PICAXE chips, so it sure seems like it should be possible with GC Basic.
Thomas Henry
Thomas, why don't you start a new thread. Post your I2C and Usart code, and we'll see if things can be sorted.
Update from me. I will publish later today when I get home.
I have essentially re-written I2C.h from the start. There is something not quite right in the existing code. I am sure that it is our use of it but I tried and tried (four days) until I started the re-write on Sunday.
My findings on the existing code are very similar to others, the code leaves the SDA and/or CLK in the incorrect state and ACK/NACKS are not handled correctly for every device. Again, I am sure this could be my use of the functions but I gave up on the existing code.
So, I have taken Microchip App Note AN1488 and re-coded into GCB.
Last night, after only four hours of coding, I have four devices working. One Master and three different I2C devices. I have no errors and I can selectively choose read / writes between the devices. It essentially works. The new code splits byte send/read, bit send/read and ACK/NACK into different functions - this provides a greater level of flexibility and control to ensure this GCB I2C handler follows the device protocol correctly.
My test setup is:
16F1937 - Master
12LC256 - Eeprom
DS1307 - RTC & NVRAM
MCP23008 - Serial expander
and... a Picaxe 18M2... also, an I2C MASTER. I have been using this device as my baseline to ensure the new GCB I2C code complies with the device I2C protocol. Why did I do this? The Picaxe device write/reads to these devices with no issue. It is good to have a baseline!
So, I can release this code, so, others can test. I currently have all the functions called v2_IC2_[name] this provides uniqueness in the functions but I think I would replace the existing code base. What is the best way forward?
I also have written a couple of library functions to support this devices using the new I2C code. I have one for the EEPROM device (this supports Low-Density and High-Density devices as these have different addressing schemes), I will adapt the DS1307 that has been also published and I will write one for the MCP type devices.
Examples of the use of the new code base:
This is supported by the function:
' see the Data sheet for this protocol. there is not ACK/NACKS required.
v2_i2c_start
v2_i2c_writebyte( 0x40 )
v2_i2c_writebyte( MCP23008_IODIR )
v2_i2c_writebyte( 0x0 )
'initiate Stop Condition
v2_I2C_Stop
v2_i2c_start
v2_i2c_writebyte( 0x40 )
v2_i2c_writebyte( MCP23008_GPIO )
v2_i2c_writebyte( 0x00 )
'initiate Stop Condition
v2_I2C_Stop
wait 2 s
v2_i2c_start
v2_i2c_writebyte( 0x40 )
v2_i2c_writebyte( MCP23008_GPIO )
v2_i2c_writebyte( 0xff )
'initiate Stop Condition
v2_I2C_Stop
end
~~~~
In my test code I write to the MCP device twice (once to set the port direction and then to set ports off), write to the EEPROM address #1, read the EEPROM address #1, write to the EEPROM address #2, read the EEPROM address #2, read the EEPROM address #1 then write to the MCP device once (to set ports on). This now works.
My code is currently full of serial debug... I promise to remove.
Anobium
However..... for those who have still got the original I2C.H - try this. Does this resolve the issues?
Save a copy of i2c,h and then edit i2c.h and change the file as follows:
You should replace the CONSTANTS and the Sub routine.
For DS1307 and MCP23xxx devices I think you can just use I2CSend as normal. For the 24LC256 you need to send an additional acknowledgement (see device datasheet, section 7) at the end after the IC2Stop but I do not know how the existing code can do this. So, I think the existing code is limited to devices that do not need ACKNOWLEDGE POLLING.
Please test and post the results. This is a workaround, it is NOT the new code but something I discovered when I was trying to resolve my issues.
New code is ready. Testing in my config for MASTER device.
I have zero transmission errors. I am testing as follows:
I just need some volunteers to do some testing.