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

Sending multiple bytes by i2c

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

View user's profile Send private message AIM Address

Sending multiple bytes by i2c
PostPosted: Tue Apr 22, 2025 12:23 pm     Reply with quote

How do I return multiple bytes from a Slave PIC?
The following software works.
This is how a Master PIC sends more than one byte in MAIN:
Code:
// *** send p_speed and s_speed to SIDE THRUSTERS ***
   I2C_START ();                        // start I2C
   I2C_WRITE (SIDE_WRT_ADDR);           // addr of side thrusters PIC
   I2C_WRITE (p_motor);                 // send port speed
   I2C_WRITE (s_motor);                 // send stbd speed
   I2C_WRITE (side_thr_reset);          // send any resets
   I2C_STOP ();                         // stop I2C


This is how they are received by a Slave PIC in the ISR (Interrupt Service Routine):
Code:
#INT_SSP
 void ssp_interrupt ()                      // have an interrupt
   {
    int incoming, state;                    // variables
    state = i2c_isr_state ();               // get state
     if (state <= 0x80)                     // master is sending data
      {
       if (state == 0x80)                   // throw away device address if state = 0x80
        incoming = i2c_read (2);            // but do not release i2c bus
       else
        incoming = i2c_read ();
       if (state == 1)                      // first data received is port speed
         p_speed = incoming;
       if (state == 2)                      // second data received is stbd speed
         s_speed = incoming;
       if (state == 3)                      // third data received is status reset
       status_reset = incoming;
       }
    if (state >= 0x80)                      // master is requesting data from slave
     {
      i2c_write (side_thr_status);          // send side thruster status
      CKP = TRUE;
     }
   }

I need to send an array of, say 200, int bytes back from a slave PIC.
To make it more complicated the Master in this case is a RaspberryPi 4b running Python. Not relevant to this forum but suggestions welcome.
I found this in https://www.ccsinfo.com/forum/viewtopic.php?t=59131&highlight=i2c+array
he seems to be incrementing the array for each request from the master, so there are 16 requests and 16 transactions? Cannot be sent as in the Main example?
I don't understand how count can be incremented if it is reset to 0 each interrupt. I probably don't fully understand Static.
Code:
#INT_SSP
void ssp_interrupt(){

   int8 incoming, state;
   static int8 count=0;

   state = i2c_isr_state();
   
   if(state < 0x80)
   {     // Master is sending data
      incoming = i2c_read();
   }

   if(state == 0x80)
   {
       count=0;
       incoming = i2c_read(2);  //perform the read on state==0x80
       //note special read that does not release the CKP
   }

   if (state>=0x80)
   {   // Master is requesting data from slave
      i2c_write(sensorArray[count++]);
  }
}
jeremiah



Joined: 20 Jul 2010
Posts: 1384

View user's profile Send private message

PostPosted: Tue Apr 22, 2025 2:28 pm     Reply with quote

One thing to understand is that i2c_isr_state() returns an 8 bit result, reserving the values 0x00 and 0x80 for special things. That means that if you use i2c_isr_state() on a message with more than 127 bytes, then you will get erroneous results (0x7F == 127, so incrementing that to 128 will be 0x80, one of the special states).

instead of using that, you may need to manually check the register status bits for the I2C to determine what i2c_isr_state() does. I haven't touched raw I2C in years, so I don't remember the status bits of note off the top of my head, but I am sure someone will come by and give better info.
rovtech



Joined: 24 Sep 2006
Posts: 270

View user's profile Send private message AIM Address

PostPosted: Tue Apr 22, 2025 2:53 pm     Reply with quote

Thanks Jeremiah.
That only applies to incoming in the ISR and I don't need to send the slave more than a few bytes. I have done that before as you can see from my example.
What I have never done is reply with many bytes from the slave and the array size could be anything. Ttelmah's code shown above uses a counter that is initialized as 0 and increments probably until the master stops asking. However it appears to me that only one byte can be returned at a time from the ISR, with the counter somehow being incremented each iteration. How then is the counter reset for the next batch?
Python has means of receiving an array according to AI but I have low trust in AI. AI says:

Code:
# Read an array
register = 0x00
length = 4
received_data = bus.read_i2c_block_data(address, register, length)
print(received_data) # Output: [1, 2, 3, 4]

# Using bytearray
data_to_send = bytearray([0x05, 0x06, 0x07, 0x08])
bus.write_i2c_block_data(address, register, list(data_to_send)) # bytearray needs to be converted to list
received_data = bus.read_i2c_block_data(address, register, len(data_to_send))
print(received_data) # Output: [5, 6, 7, 8]

But how do I send from my PIC ISR?
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