cancel
Showing results for 
Search instead for 
Did you mean: 

I2C action from timer callback

sireevenkat1
Senior

Hi,
I am working with STM32G4 and I have problem reading/writing the I2C data with in the  timer callback.
I have Timer1 calling my interrupt callback every 50 microseconds which is working well.
I have I2C read/write functions which are working well.I2C is not Interrupt based.
The problem occur while reading/writing the I2C data within the timer callback
I am unable to read/write  the I2C data in the timer interrupt callback
Below is the timer callback

 

 

void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
    if (htim == &htim1)
        {
	        if(dcheck.flagon_2sec1){
	        dcount.s_2_sec1++;
		if(dcount.s_2_sec1==40000){
			delay.flag_2sec1 = 1;
		      expander_read(&hmcp,REGISTER_INPUT,data);
			dcount.s_2_sec1=0;
			dcheck.flagon_2sec1=0;
		}
	        }
 
    }
    }

 

 

Normal I2C read/write working but with in the timer callback its not working.
Can anyone suggest.
Thanks

 

15 REPLIES 15
sireevenkat1
Senior

Hi @TDK ,
I tried below way to clear the triggering flag of timer but I am facing same problem execution not going inside the
if(delay.flag_2sec1 == 1) loop.

 

  void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
	if (htim == &htim1)//50 usec timer interrupt
	    {
               if (__HAL_TIM_GET_FLAG(htim, TIM_FLAG_UPDATE) != RESET) {
                    // Clear the update interrupt flag for TIM1
                    __HAL_TIM_CLEAR_FLAG(htim, TIM_FLAG_UPDATE);
	            if(dcheck.flagon_2sec1){
	                dcount.s_2_sec1++;
		        if(dcount.s_2_sec1==40000){
			    delay.flag_2sec1 = 1;
			    dcount.s_2_sec1=0;
			    dcheck.flagon_2sec1=0;
		         }
	             }
           }
}
//function using 2sec delay
void on(){
      expander_write(&hmcp,IO1_HIGH);
      dcheck.flagon_2sec1=1;
      if(delay.flag_2sec1 == 1){
            delay.flag_2sec1 = 0;
            expander_read(&hmcp,REGISTER_INPUT,data);
       }
       if(data==0x80){
       expander_write(&hmcp,IO2_HIGH);
       }
}


//main.c
HAL_TIM_Base_Start_IT(&htim1);

 

 Is this what were you suggesting or something else? Please suggest.
In other functions I used 50 us and 800 us delay from same timer callback its working fine. So,I think timer is clearing before adding clear the flag logic.
I am facing this issue with I2C read/write only with timer interrupt.
Thanks




Hi @TDK , @AScha.3,
below is my delay application and usage.

 

void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
	if (htim == &htim1)//50 usec timer interrupt
	    {
	        if(dcheck.flagon_100msec){
	        	dcount.m_100_sec++;
			if(dcount.m_100_sec==2000){
			   delay.flag_100msec = 1;
			   dcount.m_100_sec=0;
			   dcheck.flagon_100msec=0;
			}
	        }
	            if(dcheck.flagon_2sec1){
	                dcount.s_2_sec1++;
		        if(dcount.s_2_sec1==40000){
			    delay.flag_2sec1 = 1;
			    dcount.s_2_sec1=0;
			    dcheck.flagon_2sec1=0;
		         }
	             }
           }
}
//function using 2sec  and 100 ms delay
void on(){
       (io expander-inpur register read)
            make I01 HIgh
            //need 2sec delay here
          dcheck.flagon_2sec1=1;
          if(delay.flag_2sec1==1){
            (io expander-inpur register read)
            delay.flag_2sec1==0
           }
            check IO0 value
             //need delay 2sec delay here 
            dcheck.flagon_2sec1=1
          if(delay.flag_2sec1==1){
             IO2 HIGH
             delay.flag_2sec1==0
           }
           //need  delay 100 msec here
           dcheck.flagon_100msec=1
            if(delay.flag_100msec ==1){
             IO1 Low
             delay.flag_100msec ==0
           }           
        }

}


//main.c
HAL_TIM_Base_Start_IT(&htim1);
on();

 

Now what I observed is I2C read/write is working with above logic
but in on() function first checking 2 sec delay since 2sec by not completed by timer  its going to next statement same with next 2 sec delay and then for 100 msec delay when its reached by timer its going inside and performing the logic inside 100ms flag and for one 2sec delay its performing the 100 msec delay logic 20 times.
This is I observed.
But what I need is 
after making IO1 HIgh I need 2sec (non blocking) delay then read expander then 2sec delay(non blocking) and make IO2 HIGH and 100 ms delay (non blocking) make IO1 Low.

Please suggest.
Thanks



Thanks

TDK
Guru

In your last post you were writing TIM1_IRQHandler yourself, now you're using HAL. Either is fine, but let's stick to one so we can make progress.

If using HAL and HAL_TIM_PeriodElapsedCallback is called, the flag has already been cleared in HAL_TIM_IRQHandler.

If you feel a post has answered your question, please click "Accept as Solution".

Hi @TDK,
I am using HAL library only. Sorry for the confusion caused.
My application: after making IO1 High I need 2sec (non blocking) delay then read expander then 2sec delay(non blocking) and make IO2 HIGH and 100ms delay (non blocking) make IO1 Low.
In below logic while checking 2sec flag if it not high its going to next logic performing those instruction execution.
But my issue is I need 2sec delay(make I01 High) and 100ms delay.
dcheck.flagon_2sec1=1,where should I make this flag high?
I will call on() function in my logic only one time so when it enters inside logic it should perform the all the operation inside the on() function.
Please suggest.

 

void on(){
       (io expander-inpur register read)
            make I01 HIgh
            //need 2sec delay here
          dcheck.flagon_2sec1=1;
          while(delay.flag_2sec1==1){
            (io expander-inpur register read)
            delay.flag_2sec1==0
              dcheck.flagon_2sec2=1
           }
            check IO0 value
             //need delay 2sec delay here 
            dcheck.flagon_2sec2=1
        while(delay.flag_2sec2==1){
             IO2 HIGH
             delay.flag_2sec2==0
             dcheck.flagon_100msec=1
           }
           //need  delay 100 msec here
            while(delay.flag_100msec ==1){
             IO1 Low
             delay.flag_100msec ==0
           }           
        }

 


 

You can't have a non-blocking 2 second delay in the middle of code unless you're using an OS such as FreeRTOS.

Consider instead having a timer callback trigger every 100 ms and advance a state machine to perform the required logic. First time it's called will be t=0, 20th time will be at t=2s, etc...

If you feel a post has answered your question, please click "Accept as Solution".
sireevenkat1
Senior
When only using 50us timer, i would make a simple counter in the INT and set a global (volatile) variable, to start the i2c command.

volatile int aa, start_i2c = 0 ;

in INT:
aa++;
if (aa>2000) {aa=0; start_i2c = 1; }


in main loop then:
...
if(start_i2c==1)
{
start_i2c=0;
... >> do i2c things...
}
...

Thanks @TDK @AScha.3 for the support. Above suggestion worked for me. Below suggestion will do the work.



You can't have a non-blocking 2 second delay in the middle of code unless you're using an OS such as FreeRTOS.

Consider instead having a timer callback trigger every 100 ms and advance a state machine to perform the required logic. First time it's called will be t=0, 20th time will be at t=2s, etc...

 

 


Apart from timer related doubts my I2C didn't worked before when I tried the accepted solution I figured out that before  I called I2C handler in main() function it made it local and in other files I can't able to read and write the io expander i2c and now  I mentioned handler before main() function as global and nowI can able to read/write. That's mistake from my side.

Thanks