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 issue

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








i2c SLAVE issue
PostPosted: Thu Jan 04, 2007 9:18 pm     Reply with quote

I have been trying to implement I2C interface for quite a long time, but it has all been in vain!!!
I am trying to talk to a MASTER that is not a microchip product. I am trying the use the Slave example in the CCS compiler on a PIC18F2520. I put a bunch of printf() statements for incoming byte and the state, and noticed that my code hangs in the I2C routine.
The reason I think for this is the way the master code is written. Below is the pseudo code for the master code:

MASTER
1. ID data Record:
start()
write(0x9C) //0x9C = WR
start()
write(0x9D) //0x9D = RD ID
data[3] = read(ACK)
data[2] = read(ACK)
data[1] = read(ACK)
data[0] = read(NACK)
stop()

2. Read short data record:
start()
write(0x9F) //0x9F = RD SHORT
data[12] = read(ACK)
...
data[1] = read(ACK)
data[0] = read(NACK)
stop()

3. Read long data record:
start()
write(0x9D) //0x9E = RD LONG
data[32] = read(ACK)
...
data[1] = read(ACK)
data[0] = read(NACK)
stop()

Master sends one of these 3 requests at a time.
I have an infinite for loop in my main method. In order to be able to feed the master with the required data. I disable the SSP and GLOBAL interrupts. And then Enable them when I have the data ready. And if I go into the interrupt I give the master the data as per request then, come out of the interrupt. Disable the interrupt and prepare the data for the next sequence.
I tend to hang in the interrupt for some reason.
If you notice the in 2 of the 3 cases the Master sends the Address of the slave and the control byte combined in one command. Where as the slave example code use the first command from the master for just matching the address, and then the second command from the master as the control byte.
Since I cannot change the code in the master, any suggestions as to how I can retrieve the address sent by the master in the first command.

Another big problem using the Slave code is that whenever I check for the STATE I always get 0x80 and whenever I check foe the incoming byte, I always get 0x9D. I have spent a lot of time trying to debug this.
Any Suggestions!!!!!!
Mark



Joined: 07 Sep 2003
Posts: 2838
Location: Atlanta, GA

View user's profile Send private message Send e-mail

PostPosted: Thu Jan 04, 2007 9:57 pm     Reply with quote

My first suggestion would be to post the slave code.
Guest








PostPosted: Fri Jan 05, 2007 2:08 pm     Reply with quote

Here is the code.
Code:


# include <18f2520.h>                                                  // Contains all the defined variables for the Pic
# include <PScomp.h>                                      // Contains all the definitions for the Project
#device adc=10                                                         // 10 bit output
#fuses HS,NOWDT,NOPROTECT,NOLVP                                       
#use delay(clock=4910000)                                              // External Clock 4.91 MHz
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7)                         // RS232 Settings
#use i2c(SLAVE, SDA=PIN_C4, SCL=PIN_C3,FORCE_HW, address=0x9C)
void main()
{
for(;;) 
        {   
        disable_interrupts(GLOBAL);
        disable_interrupts(INT_SSP);

        // Here I have code to prepare all the data that needs to be sent  to the master.

          enable_interrupts(GLOBAL);
          enable_interrupts(INT_SSP);
         }



#INT_SSP
void ssp_interupt ()
{
BYTE incoming, state;
int i;
state = i2c_isr_state();




 if(state = 0x80) //Master is Sending data

  {
      incoming = i2c_read();

      if(incoming == 0x9D) // Master is Asking for the Firmware Identifier
        {

         for(i=0;i<4;i++)
          {
           i2c_write(IDpack[i]);
           
            if(state >!(0x81))
            {
             i2c_stop();
            }
          }
       
        }

     
   }
      if(incoming == 0x9D) // Here I need to actualy find the addess of the First command sent by the Mater instead of 'incoming'(I THINK SO!!)
        {

            for(i=0;i<33;i++)
            {
            i2c_write(IDpack[i]);
           
              if(state >!(0x81))
              {
              i2c_stop();
              }
            }
       
        }
        if(incoming == 0x9F) //// Here I need to actualy find the addess of the First command sent by the Mater instead of 'incoming'(I THINK SO!!)
        {

            for(i=0;i<13;i++)
            {
              i2c_write(IDpack[i]);
           
                if(state >!(0x81))
               {
                i2c_stop();
               }
            }
       
        }



   }


I would really appreciate any help!
Mark



Joined: 07 Sep 2003
Posts: 2838
Location: Atlanta, GA

View user's profile Send private message Send e-mail

PostPosted: Fri Jan 05, 2007 3:36 pm     Reply with quote

This is definitely wrong

if(state = 0x80) //Master is Sending data

I am not sure what you are trying to do here
if(state >!(0x81))

Lastly, if the I2C address of the slave is 0x9C then

start()
write(0x9F) //0x9F = RD SHORT
data[12] = read(ACK)
...
data[1] = read(ACK)
data[0] = read(NACK)
stop()

would never work since its I2C address would be 0x9E.

How do you know what the master is sending? What was used instead of a PIC before?
Guest








PostPosted: Fri Jan 05, 2007 6:07 pm     Reply with quote

I agree with you. I have 3 different cases. The master polls me periodically with any of the three cases.

In the 1st case where the master asks for the ID data Record it sends a 0x9C then 0x9D. So here, I can have the ISR as:
Code:

if(state < 0x80)   // Master is sending data
  {
   incoming = i2c_read();
   if(state == 1)         // First received byte is address
   address = incoming; //  for a read or write operation.
     if(incoming == 0x9D) // Master is Asking for the Firmware Identifier
        {

         for(i=0;i<4;i++)
          {
           
            i2c_write(IDpack[i]);
           
            if(state >!(0x81))
            {
             i2c_stop();
            }
          }
       
        }

    }


But in case 2 and 3 the Master just writes once to the slave (0x9F and 0x9D respectively). I don’t know how to retrieve that one address the master wrote to the slave so I can know if it’s the 2nd or 3rd case the master is interested in.
As I understand since the device select bits (0x9) in this case remains the same from the master, the slave should respond. It’s the don’t care bits are the bits that are being changed by the master in order to make the slave respond differently.

Quote:

Posted: Fri Jan 05, 2007 3:36 pm Post subject:

--------------------------------------------------------------------------------


I am not sure what you are trying to do here
if(state >!(0x81))


I read on the compiler help page that the state returns 0x81-0xFF if the transmission was acknowledged. So that’s why I thought of calling it after every i2c_write() from the slave.
The master is using Philips P87C51RC+4N.
I just have its pseudo code unfortunately!!!
Mark



Joined: 07 Sep 2003
Posts: 2838
Location: Atlanta, GA

View user's profile Send private message Send e-mail

PostPosted: Sat Jan 06, 2007 12:33 pm     Reply with quote

Quote:
As I understand since the device select bits (0x9) in this case remains the same from the master, the slave should respond. It’s the don’t care bits are the bits that are being changed by the master in order to make the slave respond differently.

This is incorrect. The address bits are either 7 or 10 bits. For what you are suggesting, the address would have to be a 4 bit number.

If you don't have access to the master's code, then this leads me to believe that this must be an existing product that already has a slave device that works but you are now trying to emulate the existing slave device. What is the existing slave device?
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