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 will only send one byte

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



Joined: 24 Sep 2006
Posts: 262

View user's profile Send private message AIM Address

I2C slave will only send one byte
PostPosted: Sat Jan 21, 2017 2:39 pm     Reply with quote

I am using a PIC16F884 as master sending to slave PIC16F1509 with the following software stripped to relevant code.
The slave receives the instructions in base_ctrl and responds correctly however when it replies it sends the test byte 48 twice (both base_status and base_posn are 48 although they are initialized to different values). It should send 48 then 24. I have not been able to find an example that has a slave send more than one byte in reply. I tried playing with I2C_poll but the example in the CCS manual “if(i2c_poll())” gives a compile error so I don’t know how to use it.

The code for the MASTER:
Code:
#use I2C (master, SCL=PIN_C3, SDA=PIN_C4)
#define BASE_WRT_ADDR       0X1E
#define BASE_READ_ADDR      0x1F
// send commands to base section
   I2C_START ();                         // start I2C
   I2C_WRITE (BASE_WRT_ADDR);            // addr of Write Base Section
   I2C_WRITE (base_ctrl);                // send switch state
   I2C_STOP ();                          // stop I2C
// read base status
   I2C_START ();                         // start I2C
   I2C_WRITE (BASE_READ_ADDR);           // addr of Read Base Section
   base_status = I2C_READ();             // get base status
   base_posn = I2C_READ();               // get base position
   I2C_STOP ();                          // stop I2C

The Code for the SLAVE:
Code:
#use i2c (SLAVE, SCL=PIN_B6, SDA=PIN_B4, address=0x1E)
// Interrupt on I2C
 #INT_SSP
 void ssp_interrupt ()              // have an interrupt
   {
    char incoming, state;           // variables
    state = i2c_isr_state ();       // get state
     if (state < 0x80)              // master is sending data
      {
       incoming = i2c_read ();      // throw away device address if state = 0
       if (state == 1)              // first data received is base ctrl
         base_ctrl = incoming;
//       if (state == 2)            // third data received is base posn
//         base_posn = incoming;
       }
     if (state >= 0x80)             // master is requesting data from slave
      {
base_status=48;
base_posn=24;
       i2c_write (base_status);     // send base status
       i2c_write (base_posn);       // send base position
      }
   }
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Sat Jan 21, 2017 4:51 pm     Reply with quote

See this example that reads 8 bytes. It does one byte per interrupt.
http://www.ccsinfo.com/forum/viewtopic.php?t=39565&start=4
rovtech



Joined: 24 Sep 2006
Posts: 262

View user's profile Send private message AIM Address

PostPosted: Sat Jan 21, 2017 7:22 pm     Reply with quote

Thanks PCM Programmer.
If I understand correctly the slave can only reply once per request? As you said, one reply per interrupt.
That program uses counters to make the multi requests and the slave uses the ISR state as a counter to get data from an array.
The guy's mistake was not limiting states above 7 counts (0x87), interesting but nothing to do with my problem.
What I need to do is send another request from the master and reply from the slave with the second byte? I think.
Where can I find the slave reply description? All my reference books imply only one send per master request but none of them actually say so, and don't include examples of how to send more than one reply.
Where did the second "48" come from? I assume the second read in Master just returned the unchanged buffer from the first read?

Edit:
Having just opened the slave program to edit I realize why it must be done per the example. The ISR has no way to know what the request is or what to send. Is this correct?

Second edit:
Looking at my program it is almost exactly the same as the example. All I had to do is place a (0) in the brackets after the second i2c_READ in my Master program to tell it No Acknowledge. I really don't understand it but it works. I will post both working programs later after I'm satisfied.
rovtech



Joined: 24 Sep 2006
Posts: 262

View user's profile Send private message AIM Address

PostPosted: Sat Jan 21, 2017 9:15 pm     Reply with quote

Actually a little more to it. The slave still has to know what to send.
Master program just has the 0 in the bracket of the second I2C_READ(0);

Code:
// send commands to base section
   I2C_START ();                                    // start I2C
   I2C_WRITE (BASE_WRT_ADDR);                       // addr of Write Base Section
   I2C_WRITE (base_ctrl);                           // send switch state
   I2C_STOP ();                                     // stop I2C
// read base status
   I2C_START ();                                    // start I2C
   I2C_WRITE (BASE_READ_ADDR);                      // addr of Read Base Section
   base_status = I2C_READ();                       // get base status
   base_posn = I2C_READ(0);                         // get base position
   I2C_STOP ();                                     // stop I2C

The slave uses 'state' to know if this is the first or second data to send:

Code:
// Interrupt on I2C
 #INT_SSP
 void ssp_interrupt ()                        // have an interrupt
   {
    char incoming, state;                      // variables
base_status=33;
    state = i2c_isr_state ();                 // get state
     if (state < 0x80)                        // master is sending data
      {
       incoming = i2c_read ();                // throw away device address if state = 0
       if (state == 1)                        // first data received is base ctrl
         base_ctrl = incoming;
       }
     if (state >= 0x80)                       // master is requesting data from slave
      {
       if (state==0x80)
        i2c_write (base_status);               // send base status
       if (state==0x81)
        i2c_write (base_posn);                 // send base position
      }
   }


Just one slight problem; if there is a mistake the I2C can hang the PIC. I'm not sure how to get around this one. Perhaps it will never happen if the requests match the replies.
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Sat Jan 21, 2017 9:56 pm     Reply with quote

Give an example of a "mistake".
rovtech



Joined: 24 Sep 2006
Posts: 262

View user's profile Send private message AIM Address

PostPosted: Sun Jan 22, 2017 8:50 am     Reply with quote

Sorry, I should have explained;
If the 0 is left out of the last
Code:
i2c_read(0)

in the Master program then the Master PIC hangs presumably waiting for the acknowledge.
Is there any danger of i2c communications getting confused and hanging? Is there a timeout that can be used to prevent this? Perhaps the WDT? I have never used it but think it would still be in an endless loop cutting off the rest of the program.
Perhaps you can explain it better?
Ttelmah



Joined: 11 Mar 2010
Posts: 19518

View user's profile Send private message

PostPosted: Sun Jan 22, 2017 9:46 am     Reply with quote

You can do a timeout.
However on the only chip where I have seen issues with I2C, this wouldn't solve the problem since it is a hardware fault (PIC4431)....
The slave is waiting for the end of transaction.
The lesson is get your transactions right....

You'd need to timeout at both ends and reprogram the I2C interfaces to release the line.
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