View previous topic :: View next topic |
Author |
Message |
JamesW
Joined: 23 Apr 2007 Posts: 91 Location: Rochester, England
|
I2C Slave - emulating a PCF8574 - any pointers? |
Posted: Tue Nov 01, 2011 10:34 am |
|
|
Hi folks,
I've been asked to port some assembler code written years ago, for a PIC16F876A into C, so some basic changes can be made.
The main function of the chip is to emulate a PCF8574 i/o chip. It does a bit more than this - but essentially this is it.
My assembly code is pretty rusty, so I've tried to modify the ccs ex_slave.c example to do this - but with little success.
Has anyone done this before, and if so - could they offer any advice please?
My I2C slave attempt (or the relevant buts) are posted below.
I could paste the old assembly code too - but it's probably not worth it.
Thanks in advance
James
Code: |
unsigned int8 ControlByte = 0;
#use i2c(SLAVE, sda=PIN_C4, scl=PIN_C3,force_hw,address=0x20)
#INT_SSP
void ssp_interupt ()
{
BYTE incoming, state;
state = i2c_isr_state();
if(state <= 0x80) //Master is sending data
{
incoming = i2c_read();
/* FIRST RECEIVED BYTE IS DATA WRITE */
if(state == 1)
{
/* BIT 7 - OUTPUT */
if (bit_test(incoming, 7))
{
bit_set(ControlByte,7);
}
else
{
bit_clear(ControlByte,7);
}
/* BIT 6 - OUTPUT */
if (bit_test(incoming, 6))
{
bit_set(ControlByte,6);
}
else
{
bit_clear(ControlByte,6);
}
/* BIT 5 - OUTPUT */
if (bit_test(incoming, 5))
{
bit_set(ControlByte,5);
}
else
{
bit_clear(ControlByte,5);
}
/* BIT 4 - OUTPUT */
if (bit_test(incoming, 4))
{
bit_set(ControlByte,4);
}
else
{
bit_clear(ControlByte,4);
}
}
/* SECOND RECEIVED BYTE IS EEPROM DATA - NOT USED IN THIS INSTANCE */
if(state == 2)
{
//buffer[address] = incoming;
}
}
/* MASTER READ */
if(state == 0x80)
{
i2c_write(ControlByte);
}
} |
|
|
|
jeremiah
Joined: 20 Jul 2010 Posts: 1349
|
|
Posted: Tue Nov 01, 2011 11:53 am |
|
|
One thing that will help is going over how each of the i2c functions in CCS work. The help index in the compiler is very useful for this (or the manual online as well).
For example, the "Function" section for i2c_isr_state() says
Quote: |
Returns the state of I2C communications in I2C slave mode after an SSP interrupt. The return value increments with each byte received or sent.
If 0x00 or 0x80 is returned, an i2C_read( ) needs to be performed to read the I2C address that was sent (it will match the address configured by #USE I2C so this value can be ignored)
|
I don't see you reading that byte when the i2c_isr_state() function returns 0x80 for example.
Are there specific problems that you are running into? |
|
|
JamesW
Joined: 23 Apr 2007 Posts: 91 Location: Rochester, England
|
|
Posted: Tue Nov 01, 2011 12:12 pm |
|
|
Hi Jeremiah,
Thanks for the reply - at the current moment, all I can really say is that it doesn't seem to be recognised on the bus.
Whilst I have the master unit to play with, I have no code for it at all - so it's a matter of compiling and downloading the code - then power cycling the unit to see if the master recognises the new device (I can tell this - as apparently the master will turn a light on, on the slave when it has connected).
I don't really want to have to build a pic master circuit, in order to test the driver in the slave (although I will if I have to) - hence the question that if anyone has got a driver working, could they provide any pointers / code snippets.
The sample code in the ex_slave I have used and modified many times (for many applications)- but this is a slightly weird example in that there are no address bytes being sent - and I'm not entirely sure how to handle this with the I2C.
Cheers
James |
|
|
jeremiah
Joined: 20 Jul 2010 Posts: 1349
|
|
Posted: Tue Nov 01, 2011 1:21 pm |
|
|
What is the sequence that allows the master to "detect" the slave and turn on the LED? It could be that your slave code is mostly working, but just not fulfilling the sequence the master expects.
Also, what kind of master are you using to test with? |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Tue Nov 01, 2011 1:47 pm |
|
|
Get a low-cost but capable Logic Analyzer, such as this one:
http://www.pctestinstruments.com/
Configure it as an i2c interpreter. Put the known-good i2c Master and
assembly language Slave together and run them through every possible
command. Capture the waveforms for each test (with i2c interpreter
enabled) and print them out. Study them and completely understand it.
Go through the source for the ASM code. Study each section and make
notes in the listing, showing which parts of the code correspond to the
signals in the waveforms that you captured.
Using this information as the basis, now try to make a CCS program in C.
Do a little bit at a time. Try to emulate the operation of the most simple
command(s) in the ASM code first.
The above description is one possible way to do the project. Another way
is just to look at the ASM code and compare it to the C listing (in ASM) and
write the C code based on what you see. If it was me, I would do this
last method and then add the logic analyzer later, to check everything. |
|
|
JamesW
Joined: 23 Apr 2007 Posts: 91 Location: Rochester, England
|
|
Posted: Wed Nov 02, 2011 4:56 am |
|
|
thanks.
I've bitten the bullet and ordered the logic analyser - it was about time I bought a replacement for my 1980s HP logic analyser that's about the size of a wardrobe!
I will keep you posted
Cheers
James |
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9229 Location: Greensville,Ontario
|
|
Posted: Wed Nov 02, 2011 9:41 am |
|
|
While you wait..you might want to try out 'realterm' as it has an I2C interface...
never tried it but..... |
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9229 Location: Greensville,Ontario
|
|
Posted: Wed Nov 02, 2011 9:45 am |
|
|
Well my memory is getting old..just checked, had a fuzzy moment...and it seems Realterm has to have a $90 'interface' module to make it work... Yeesh,probably why I forgot about using it!Ffar easier to use a $2 PIC and cut my own code...
I wouldn't be surprised if someone on the Web has a PC app to do I2C though, it ain't rocket science ! |
|
|
|