I2C slave mode

General discussion on mikroBasic.
Post Reply
Author
Message
extrapilot
Posts: 130
Joined: 28 Nov 2006 17:59

I2C slave mode

#1 Post by extrapilot » 30 Apr 2007 21:31

Hello

I have an application running on an 18F4550 that may require PIC to PIC communication via I2C; unfortunately, due to other interface requirements on the 4550 (including USB), it seems I2C is the only native hardware interface remaining, and ISRs will likely prevent me from using soft-anything.

It seems that mE has not provided any I2C slave support in their libraries- native or software emulated.

Has anyone come up with I2C slave code that they can share, or can anyone point me towards some sample code, etc? Im curious as to why mE has not implemented I2C slave mode, and wonder if there is some fundamental problem with it on the PIC, or with their compiler, etc.

Regards,
Rob

jpc
Posts: 1986
Joined: 22 Apr 2005 17:40
Location: France 87

#2 Post by jpc » 01 May 2007 07:00


extrapilot
Posts: 130
Joined: 28 Nov 2006 17:59

#3 Post by extrapilot » 01 May 2007 17:48

JPC

Thanks you very much for the reference. I did not see this post; I probably gave up after looking through the first year of threads on I2C ;)

This code has some inconsistencies with C-based sample code posted on the Microchip site (supposedly, corrected code, where their earlier examples had a major flaw). And, it is not ISR based- but it seems like conversion will be simple if this source works. Ill post an ISR-based version if I can get this cleaned up and happy.

Best,
Rob

Andreas
Posts: 139
Joined: 05 Feb 2005 12:43
Location: Germany

I2C slave mode

#4 Post by Andreas » 01 Jul 2007 15:50

Hi extrapilot,
did you have any luck with the above code?

extrapilot
Posts: 130
Joined: 28 Nov 2006 17:59

#5 Post by extrapilot » 02 Jul 2007 18:21

Hello Andreas!

Yes, much progress here. There are a number of silicon problems as you may know, and I suspect that this is one of the reasons many people have had difficulty with what should be a simple protocol implementation. One of the biggest challenges for me has been timings. For example, there needs to be a very specific delay between writing to the SSPBUF (as a slave) and then releasing the clock. Same goes on the Slave for determining when end-of-transmission has happened, since it seems that the SSPSTAT.P (stop bit) is raised only 10us after the character-received interrupt is raised- which makes things pretty difficult to trap if you are doing any processing in your ISR while keeping interrupts disabled. Here, a specific delay and a poll on SSPSTAT.P works well.

The problem is, it seems that there are subtle differences between uCs that makes it difficult to generalize functions. But once I get some of this sorted out, Ill post the base Master/Slave functions in the Projects section here...

Rob

Andreas
Posts: 139
Joined: 05 Feb 2005 12:43
Location: Germany

I2C slave mode

#6 Post by Andreas » 02 Jul 2007 21:25

Hi Rob,
my problem still is that the bus sometimes hangs after a couple of hours. Till then everything works fine, but then it suddenly hangs (and with it the whole system). I'm not quite sure if it is the silicon flaw, my software or the noisy environment (engine compartment).

Can you be a little more specific about the delay/poll for SSPSTAT.P ?

Andreas

dangerous
Posts: 748
Joined: 08 Mar 2005 16:06
Location: Nottinghamshire, UK

#7 Post by dangerous » 03 Jul 2007 23:02

This link works for an I2C peripheral.

http://www.mikroe.com/forum/viewtopic.p ... ght=#24530

I used a 16F88 as a port reader and port extender to give me some enhancement over a PCF8574 port.

The main controller is a 16F876A using the I2C engine.

The link includes code for slave (F88) and master (F876A).

extrapilot
Posts: 130
Joined: 28 Nov 2006 17:59

#8 Post by extrapilot » 19 Jul 2007 21:15

Andreas

Sorry to have missed your reply; I dont think I got a notification that the thread was updated.

Did you resolve the issue with the I2C bus?

If not, can you elaborate on the setup (i.e. is the master hanging, or the slave, and how are you validating that the system is locked?).

Generally, on the slave side, my experience with hangs is related to timings, or to an overflow that is not cleared. There is an errata on some silicon relating to overflow clearing when you have more than one slave on a bus.

On the master side, in my experience hangs are generally caused by the slave not responding (clock stretching)- where the master is just waiting for a reply. I suspect that a watchdog might be a solution here, since generally you are not going to see latencies on a slave reply of more than a few ms. If there is some EMF causing bus corruption, and the slave is not releasing the clock for whatever reason, better to reset than to remain locked.

Regards,

Andreas
Posts: 139
Joined: 05 Feb 2005 12:43
Location: Germany

I2C slave mode

#9 Post by Andreas » 19 Jul 2007 21:34

Hi Rob,
in my case it seems like you wrote: The slave does not release the clock. So I've implemented a timer to see if it hangs. That works most of the time, but not always. The problem is that I can't reset the PIC with the watchdog because the slave writes on a CF card and on reset all data would be lost. It is really hard to figure out the position in the code where the bus hangs and even more difficult to find the cause because it sometimes takes hours until that happens. That slows the debugging down pretty much. But I'll keep trying.

dangerous
Posts: 748
Joined: 08 Mar 2005 16:06
Location: Nottinghamshire, UK

#10 Post by dangerous » 23 Jul 2007 08:13

Hi,

On the I2C Bus I use this arrangement:

I2C_Start
I2C_Write (Slv_Address) 'If read only address = slave_address + 1
I2C_Write (Sub_Adress) 'If needed, may be control byte or sub_add.
I2C_Write (data) 'for writes or
'********************************************************
'can do a repeated start followed by address+1 if needed. Earlier bytes are in write mode to set up slave for data from address
I2C_Repeated_Start 'only needed if sub addressing is used eg eeprom
I2C_Write (Slv_Address + 1) 'read from device
'****************************************************
d0 = I2C_Read (1) 'read a byte (+ACK)
d1 = I2C_Read (1) 'next byte, repeat until n-1 bytes are received
...........................................
dn = I2C_Read (0) 'last byte or if only one byte. Must tell slave to stop sending more data. (NO ACK)
while I2C_IS_IDLE <> 1
NOP
wend 'wait for Bus free
I2C_Stop

Also some devices (EEPROM etc) have slow write times.

This snippet:

while I2C_IS_IDLE <> 1
NOP
wend 'wait for Bus free

will automatically test for bus free between writes or blocks of writes.

When the device has finished its writes, it releases the bus.

Post Reply

Return to “mikroBasic General”