Posible interaction between ADC_SAR_Seq and I2C

Tip / Sign in to post questions, reply, level up, and achieve exciting badges. Know more

cross mob
Anonymous
Not applicable

 I've a project with I2C (slave and fixed function) and an ADC_SAR_Seq with many differential inputs (about 20).

   

ADC works perfect without cpu work (only to get values after a complete conversión of the 20 inputs).

   

But I2C doesn't work, the master says BUSY. After a while of testing and retesting I've tested omit ADC_SAR_Seq_StartConvert(); and voilá, I2C works perfect.

   

First I thought about high SPS, so down it. but no improvement, only omiting StartConvert solves the I2C problem.

   

 

   

Also commenting code into ADC ISR solves the problem and I2C begin to work. 

   

 

   

The code for the I2C is simple and it's into the for loop:

   

if(0u != (I2C_SlaveStatus() & I2C_SSTAT_WR_CMPLT))

   

{

   

/* Read the number of bytes transferred */

   

byteCnt = I2C_SlaveGetWriteBufSize();

   

/* Clear the write status bits*/

   

I2C_SlaveClearWriteStatus();

   

/* Move the data written by the master to the read buffer so that the master can read back the data */

   

for(indexCntr = 0; indexCntr < byteCnt; indexCntr++)

   

{

   

rdBuf [indexCntr] = wrBuf[indexCntr]; /* Loop back the data to the read buffer */

   

}

   

/* Clear the write buffer pointer so that the next write operation will start from index 0 */

   

I2C_SlaveClearWriteBuf();

   

/* Clear the read buffer pointer so that the next read operations starts from index 0 */

   

I2C_SlaveClearReadBuf();

   

}

   

/* If the master has read the data , reset the read buffer pointer to 0 and clear the read status */

   

if(0u != (I2C_SlaveStatus() & I2C_SSTAT_RD_CMPLT))

   

{

   

/* Clear the read buffer pointer so that the next read operations starts from index 0 */

   

I2C_SlaveClearReadBuf();

   

/* Clear the read status bits */

   

I2C_SlaveClearReadStatus();

   

}

   
        
   

Again the code into the isr is simple:

   

CY_ISR( ADC_SAR_Seq_ISR )

   

{

   

int i;

   

  for( i=0;i<20;i++)

   

{

   

ichannels = ADC_SAR_Seq_GetResult16(i);

   

}

   

}

   

Best regards.

0 Likes
11 Replies
ETRO_SSN583
Level 9
Level 9
250 likes received 100 sign-ins 5 likes given

I woulkd re-think how ISR handled.

   

 

   

Normally in ISR you want to just set a flag and exit, and service the isr in main().

   

That prevents stack push due to f() calls, etcc. adding extra latency.

   

 

   

Regards, Dana.

0 Likes
Anonymous
Not applicable

 My thought was that I2C component doesn't need mcu to work, so no ISR prevents from doing his work, and use a DMA for input/output info.

   

I need the ISR, get values and compare with a limit with a good latency (under 1ms, or 100us as I achieve now). A flag doesn't guarantee doing thinks with a good timing and depends on what is mcu doing.

   

How can we continue?

0 Likes
Bob_Marlowe
Level 10
Level 10
First like given 50 questions asked 10 questions asked

When looking into the datasheet of I2C master fixed function or UDB implementation you'll see under "Resources" thatz both of them need an interrupt. Your interrupt-handler may consume too much time within the loop to allow a continous  communicatzion.

   

To avoid that situation you could try to re-arrange the interrupt priortties givint the I2C a higher (lower number!) priority, so it will interrupt the SAR-handler or, as Dana suggested and proved to be correct, shorten the SAR-handler and move the handling out of the interrupt routine.

   

 

   

Bob

0 Likes
Anonymous
Not applicable

 I use I2C Slave, and fixed function, so I don't see any interrupt.

0 Likes
Anonymous
Not applicable

 I didn't tell that it's a PSOC5.

0 Likes
Bob_Marlowe
Level 10
Level 10
First like given 50 questions asked 10 questions asked

believe me, there is an interrupt handler for fixed function block I2C slave.

   

Go to "Generated Source" in Workspace Explorer and look for your I2C_INT.c file which contains the interrupt code.

   

When opening the .cydwr-file and opening the "Interrupts" tab you'll see that your I2C-slave is assigned the lowest(default) interrupt priority. Here you may assign a higher priority (lower number) to I2C.

   

 

   

Bob

0 Likes
Bob_Marlowe
Level 10
Level 10
First like given 50 questions asked 10 questions asked

Hopefully a PSoC5 LP ???

   

 

   

Bob

0 Likes
Bob_Marlowe
Level 10
Level 10
First like given 50 questions asked 10 questions asked

Sorry for that many posts, but

   

Are you using Creator 2 or Creator 3 ?

   

Are you working with a PSoC5 or a PSoC5 LP?

   

 

   

Bob

0 Likes
Anonymous
Not applicable

Creator 3

   

PSOC5LP

   

 

   

I see the I2C interrupt, sorry.

   

 

   

The first try was slowing clock for ADC (about 1Mhz, I can't less) so there was lesser interrupts, but no improvement. I don't believe that 60.000SPS with 20 channels (about 3000interrupts/sec) can prevent I2C from working.

   

 

   

Best regards.

0 Likes
Bob_Marlowe
Level 10
Level 10
First like given 50 questions asked 10 questions asked

I2C is realized with a state-machine, so the miss of an edge transition coud get it out of sync. Did you already try to change the priority?

   

 

   

Bob

0 Likes
Bob_Marlowe
Level 10
Level 10
First like given 50 questions asked 10 questions asked

3000 interrupts/s is not few. Depending on the amount of time you spend in your handler it might disturb some time-critical processes.

   

 

   

Bob

0 Likes