cancel
Showing results for 
Search instead for 
Did you mean: 

Why SPI transmit doesn't work from timer interrupt?

NikolaiB
Associate III

Hello everyone!
That works:

int main(void)
{
  ...
  init_SPI1();
  for(;;)
    SPI1_Send();
}

And that doesn't:

void TIM2_IRQHandler(void)
{
  SPI1_Send();
  TIM2->SR &= ~TIM_SR_UIF; // reset UIF bit in the status register of the timer
}

Why?

Thank you very much!

1 ACCEPTED SOLUTION

Accepted Solutions
NikolaiB
Associate III

I have found the problem. It was the initialization order. Hier is the code simlified. 

int main(void)
{
  init_TIM2(); // Timer first
  init_SPI1(); // Here the SPI is enabled
  for(;;) {
    SPI1_Send(data); // SPI enabled
  }
}
void TIM2_IRQHandler(void)
{
  SPI1_Send(data); // SPI not enabled yet, because the timer ist faster than SPI initialization
}

If I change the order of SPI and Timer Initialization the SPI1_Send works from the timer interrupt.

I thank everyone.

View solution in original post

5 REPLIES 5
waclawek.jan
Super User

What does "doesn't work" mean?

What is the expected behaviour and what is the observed one?

What is SPI1_Send()? Note, that you are inside an interrupt service routine, i.e. until SPI1_Send() exits, other interrupts with same or lower priority than the TIM2 interrupt can't be served.

JW

TDK
Super User

You should check for the flag and only act if it’s set. If you clear the flag as the last statement, it will typically cause the irq to be called twice.

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

Works: Clock and MOSI signals are generated by the MCU. I can see them on the oscilloscope.
Does't work: Clock and MOSI signals are NOT generated by the MCU. I can't see any signals on the osci.

Here is my send function

void SPI1_Send(unsigned char* data, int size)
{
  int i = 0;
  while(i<size){
    while(!((SPI1->SR) & (1<<1))){}; // <------- Here it stops (TXE bit in status register)
    SPI1->DR = data[i];
    i++;
  }

  while(!((SPI1->SR) & (1<<1))){};
  while(((SPI1->SR)&(1<<7))){};
  
  unsigned char temp = SPI1->DR;
  temp = SPI1->SR;
}

If I call this function within the Timer interrupt, the while (TXE) never exits. But why? If I call this function from while(1) in main, it works fine.

 

waclawek.jan
Super User

What you've posted looks OK. The problem is probably elsewhere in your program. For example, the second "not working" program may contain some code, which disables the SPI pins in GPIO. Or you have some hardware issue, short between SPI clock signal and some other signal, and that other signal gets enabled with the timer.

Read out and check the SPI and relevant GPIO registers content in debugger, at the point where it "does not work".

JW

 

NikolaiB
Associate III

I have found the problem. It was the initialization order. Hier is the code simlified. 

int main(void)
{
  init_TIM2(); // Timer first
  init_SPI1(); // Here the SPI is enabled
  for(;;) {
    SPI1_Send(data); // SPI enabled
  }
}
void TIM2_IRQHandler(void)
{
  SPI1_Send(data); // SPI not enabled yet, because the timer ist faster than SPI initialization
}

If I change the order of SPI and Timer Initialization the SPI1_Send works from the timer interrupt.

I thank everyone.