Author Topic: Waiting for IIC to complete  (Read 4686 times)

Offline neil

  • Sr. Member
  • ****
  • Posts: 438
    • View Profile
Waiting for IIC to complete
« on: October 04, 2017, 09:58:25 AM »
Hi Mark
  I have connected an IIC that requires initialization of few registers. But there must be a delay in between each  call, see below. When the below is carried out, I assume it goes to a buffer where all is transmitted to the device. Is there a way I can poll a register to see if the 1st send is complete before continuing with the second?

Regards
Neil

unsigned char VAL[4];
VAL[0]=0x40;
 VAL[1]=0;
 VAL[2]=0x0; //set as output
 fnWrite(IICPortIDG2, (unsigned char *)VAL, 3);
 
//has to be a delay here....

VAL[1]=9;
VAL[2]=0;
fnWrite(IICPortIDG2, (unsigned char *)VAL, 3);

Offline mark

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 3236
    • View Profile
    • uTasker
Re: Waiting for IIC to complete
« Reply #1 on: October 05, 2017, 01:17:46 AM »
Hi Neil

If you set tI2CParameters.Task_to_wake to a task name you will get a notification (task will be scheduled) each time the write has terminated, although this is not the best technique here (termination means that the final byte has completed and the stop condition has been commanded).

The driver's queue state will be TX_ACTIVE until this point ,so polling this value shows when it has completed. The value is however local to the driver but can (in an emergency) by read using:
I2CQue *ptI2CQue = (struct stI2CQue *)(que_ids[IICPortIDG2 - 1].output_buffer_control);
if ((ptI2CQue->ucState & TX_ACTIVE) != 0) {
// still transmitting...
}

[older code may use IIC instead of I2C].

I would however just use a software timer and state-event sequence like this:

task() {
static int iInitState = 0;
unsigned char VAL[4];
switch (iInitState) {
case 0:
    VAL[0]=0x40;
    VAL[1]=0;
    VAL[2]=0x0; //set as output
    fnWrite(IICPortIDG2, (unsigned char *)VAL, 3);
    uTaskerMonoTimer(OWN_TASK, (DELAY_LIMIT)(0.05 * SEC), E_TIMER_NEXT_I2C_MESSAGE);
    iInitState++;
    break;
case 1:
    VAL[0]=0x40;
    VAL[1]=0x09;
    VAL[2]=0x02; //set as output
    fnWrite(IICPortIDG2, (unsigned char *)VAL, 3);
    uTaskerMonoTimer(OWN_TASK, (DELAY_LIMIT)(0.05 * SEC), E_TIMER_NEXT_I2C_MESSAGE);
    iInitState++;
    break;
case 2:
    VAL[0]=0x40;
    VAL[1]=0x23;
    VAL[2]=0x22; //set as output
    fnWrite(IICPortIDG2, (unsigned char *)VAL, 3);
    fnDebugMsg("I2C sequence terminated - each command sent with 50ms delay");
    iInitState++;
    break;
}
}


This ensures adequate delay between each message.

Regards

Mark


Offline neil

  • Sr. Member
  • ****
  • Posts: 438
    • View Profile
Re: Waiting for IIC to complete
« Reply #2 on: October 05, 2017, 11:55:25 AM »
Hi Mark,
  Thanks for the reply, cheers.

I will use the timer method to send the commands, this sounds a cleaner approach.

Best Regards
Neil

Offline neil

  • Sr. Member
  • ****
  • Posts: 438
    • View Profile
Re: Waiting for IIC to complete
« Reply #3 on: October 09, 2017, 03:02:14 PM »
Hi Mark,
  This way is fine for initialization, but there are times in the application where a few commands may be sent one after another. If I have delay task then it complicates my application as there may be many places where the commands may sent, and known where to go after the data is sent is tricky. I suppose I can have my own buffer , but this duplicates what the IIC task does (I think). Is there a way to tell the IIC routine to delay for x msec before sending the next packet?

Regards
Neil

Offline mark

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 3236
    • View Profile
    • uTasker
Re: Waiting for IIC to complete
« Reply #4 on: October 13, 2017, 09:35:55 PM »
Hi Neil

When there are multiple messages (read and/or writes) they will be sent as quickly as possible after each other - also repeated starts will be used rather than a stop and a start condition.
There is no option to insert a delay between these so you would need to modify the I2C driver code to not start a following message but instead to send a stop condition and start a delay (eg. a HW timer) that then kicks off the next waiting message when it fires.

Regards

Mark