CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to CCS Technical Support

I2C Slave - emulating a PCF8574 - any pointers?

 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
JamesW



Joined: 23 Apr 2007
Posts: 91
Location: Rochester, England

View user's profile Send private message Visit poster's website

I2C Slave - emulating a PCF8574 - any pointers?
PostPosted: Tue Nov 01, 2011 10:34 am     Reply with quote

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: 1347

View user's profile Send private message

PostPosted: Tue Nov 01, 2011 11:53 am     Reply with quote

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

View user's profile Send private message Visit poster's website

PostPosted: Tue Nov 01, 2011 12:12 pm     Reply with quote

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: 1347

View user's profile Send private message

PostPosted: Tue Nov 01, 2011 1:21 pm     Reply with quote

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

View user's profile Send private message

PostPosted: Tue Nov 01, 2011 1:47 pm     Reply with quote

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

View user's profile Send private message Visit poster's website

PostPosted: Wed Nov 02, 2011 4:56 am     Reply with quote

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: 9226
Location: Greensville,Ontario

View user's profile Send private message

PostPosted: Wed Nov 02, 2011 9:41 am     Reply with quote

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: 9226
Location: Greensville,Ontario

View user's profile Send private message

PostPosted: Wed Nov 02, 2011 9:45 am     Reply with quote

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 !
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group