Nucleo-F439ZI: SPI DMA normal mode and TIM6 running at background does not work
Hello,
I wanna read an external ADC.
The ADC has following serial process conditions:
1. Get a CNV signal by µC
2. Convert and send BUSY=HIGH to µC
3. After Convert send BUSY=LOW to µC
4. µC send SCK to ADC, then ADC send data and is running as long as it gets SCK signals
That causes, that I cannot run my SPI DMA communication in circular mode, because I have to run the CNV and BUSY process first and always de-/activate SPI (the SCK signal) after it. So I have choosen the normal mode.
But the thing is I want to run the SPI communication fully at the background, also the CNV and BUSY process, that my main while function does not block the regular SPI and Convert process. This is what should be fast always. And at the main while loop I can choose, if I output the data at 100 ms rate or whatever.
So I had the idea to use TIM6´s Callback function to run the CNV/BUSY/DMA-Receive-call at the background, wile the DMA-call also runs at the background.
(I have tested the DMA Communication at the main while loop before, it works, the tim callback also works without the DMA SPI function call)
I use UART outputs with PUTTY.
Here is my Code:
...
//Over the main while loop:
#ifdef SPI_MODE_DMA
cplt_callback_ready = true; // At the beginning the callback was never processing, so it is ready
HAL_TIM_Base_Start_IT(&htim6); // Starting the Timer TIM6 to let the callback process the CNV/BUSY and SPI DMA receive function call
#endif
while(1)
{
...
}
...
// Non blocking function to process the serial procedure with adc and µC (CNV High, then Low, then SPI and so on...)
// It functions continously like a while(1) loop
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
if (htim->Instance == TIM6) // TIM1 interrupt trigger check
{
if (hspi1.State == HAL_SPI_STATE_READY && cplt_callback_ready == true) // Only process, when spi DMA communication is ready already for next communication
{
if (pinstate(BUSY) == LOW) // When the adc is ready to start a new convert
{
set_pin(CNV, HIGH); // Give Start signal to convert
while (pinstate(BUSY) == HIGH); // Wait the whole converting process
set_pin(CNV, LOW); // Now set CNV back to low for the next signal sending
test_message("\n \n\nHere starting DMA function.\n");
cplt_callback_ready = false;
HAL_SPI_Receive_DMA(&hspi1, (uint8_t*)spi_buffer, sizeof(spi_buffer)); // Now asking adc out for the digital value
}
}
}
}
// ___________________________________________________________________________________________________
//SPI DMA functions
// Callback for Half-Transfer
void HAL_SPI_RxHalfCpltCallback(SPI_HandleTypeDef *hspi)
{
if (hspi->Instance == SPI1)
{
processing stuff...
test_message("\n\nHALF!\n");
}
}
// Callback for Complete-Transfer
void HAL_SPI_RxCpltCallback(SPI_HandleTypeDef *hspi)
{
if (hspi->Instance == SPI1)
{
processing stuff...
test_message("\n\FULL!\n");
cplt_callback_ready = true;
}
}
It runs 2 times and prints "Here starting DMA..." the third time. Then there is no output any longer.
I added the bool "cplt_callback_ready" to be sure, that a callback processing is ready first, before the TIM6 callback calls the next DMA receive. But it does not change anything.
Somehow I dont understand anything, what causes my error, it seems that the interrupts of TIM6 and the SPI DMA interrupt has time issues???
By the way, the TIM6 callback runs perfectly without calling the receive DMA SPI function.
Please help me.
