2023-12-27 09:30 PM - last edited on 2023-12-28 03:26 AM by SofLit
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
Solved! Go to Solution.
2023-12-28 11:01 PM
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
2023-12-29 12:52 AM - edited 2023-12-29 04:15 AM
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
2023-12-29 06:38 AM
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.
2024-01-02 01:18 AM
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
}
}
2024-01-02 06:43 AM
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...
2024-01-05 01:06 AM
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