2022-01-26 10:18 AM
I'm trying to do a periodic ADC capture on 2 channels, triggered by TIM5. ADC should output to memory via DMA, with a DMA interrupt upon each completion to read the data from each scan.
So far, the DMA interrupts aren't hitting, and the ADC doesn't even appear to be reading anything. Any ideas what I'm missing?
TIM5_CC4 outputs on a GPIO. ADC captures should be synced with that, so I'm trying to use TIM5_CC3 to trigger the ADC.
Code was generated by STM32CubeMX 6.1.1, with STM32F4 package 1.25.2. (MX_DMA_Init() is called before MX_ADC1_Init().)
CubeMX Project Screenshots
Code Excerpts
Order of some relevant function calls:
// in main():
HAL_Init();
SystemClock_Config();
MX_GPIO_Init();
MX_DMA_Init();
// elsewhere, after OS starts:
MX_ADC1_Init();
EDIT: Added relevant code excerpts as attachments.
Solved! Go to Solution.
2022-01-28 09:47 AM
Thanks for your help.
On further investigation, I see no sanctioned way with the (non-LL) HAL to enable the channels before starting the PWM output.
I'm working around the issue by (ab)using the private function TIM_CCxChannelCmd(). I've replaced
TIM_CCxChannelCmd(htim5.Instance, TIM_CHANNEL_4, TIM_CCx_ENABLE);
with
TIM_CCxChannelCmd(htim5.Instance, TIM_CHANNEL_3, TIM_CCx_ENABLE);
TIM_CCxChannelCmd(htim5.Instance, TIM_CHANNEL_4, TIM_CCx_ENABLE);
HAL_TIM_Base_Start(&htim5);
EDIT: the DMA interrupts aren't correct yet. The interrupt gets hammered for a while, then isn't called anymore. I think the ADC config isn't correct. But I'm over the main roadblock now.
2022-01-26 10:44 AM
use the timer update event for TRGO, not the reset event.
2022-01-26 12:22 PM
Changed as specified. Problem persists, i.e. HAL_ADC_ConvCpltCallback() still isn't called.
2022-01-26 01:40 PM
Which STM32?
Read out and check/post TIM, ADC and DMA registers content.
JW
2022-01-27 02:29 AM
2022-01-27 07:09 AM
> Did you start...
1. No, actually - we call
HAL_TIM_PWM_Start(&htim5, TIM_CHANNEL_4);
Maybe this is the problem, as it doesn't start TIM_CHANNEL_3? How would I start them both at the same time, and produce the same output as this does on CHANNEL_4? (HAL_TIM_PWM_Start only takes single channel args.)
EDIT: Maybe HAL_TIM_PWM_ConfigChannel() before HAL_TIM_Base_Start()? I'm looking into it...
2. Yes, MX_ADC1_Init() --> HAL_ADC_Init() --> HAL_ADC_MspInit(), which includes
/* USER CODE BEGIN ADC1_MspInit 1 */
static uint32_t dummyData[2];
HAL_ADC_Start_DMA(&hadc1, (uint32_t*)dummyData, 2);
/* USER CODE END ADC1_MspInit 1 */
(Trying to get it going before I bother actually trying to capture the data...)
2022-01-27 07:38 AM
Start HAL_TIM_OC_Start (?) TIM_CHANNEL_3 next line. This should not affect sync. because all channels share the same time counter (CNT register).
2022-01-27 07:49 AM
> Start HAL_TIM_OC_Start (?) TIM_CHANNEL_3
Did you mean HAL_TIM_PWM_Start()?
EDIT: I see HAL_TIM_OC_Start() is identical to HAL_TIM_PWM_Start().
> next line. This should not affect sync.
What I mean is not only do I need them in sync for steady state operation. Also the first pulse output from both channels (3 & 4) must be simultaneous, i.e. never a pulse on just one of them.
I thought the Start functions actually start the timer, and so separate calls to HAL_TIM_PWM_Start() / HAL_TIM_OC_Start() would risk missing some initial pulses on one channel?
2022-01-27 07:59 AM
> Did you mean HAL_TIM_PWM_Start()?
correct, you are using PWM mode
Its correct the you might miss one or more PWM events if you start the 2nd channel too late. How realistic this threat is, depends on the ... timing. You might read back the counter (__HAL_TIM_GET_COUNTER) register and check how many ticks you have spent in the HAL code and if this comes close to the PWM edges. If this sounds risky, you might want to go register level or low level (LL_) programming.
2022-01-28 09:47 AM
Thanks for your help.
On further investigation, I see no sanctioned way with the (non-LL) HAL to enable the channels before starting the PWM output.
I'm working around the issue by (ab)using the private function TIM_CCxChannelCmd(). I've replaced
TIM_CCxChannelCmd(htim5.Instance, TIM_CHANNEL_4, TIM_CCx_ENABLE);
with
TIM_CCxChannelCmd(htim5.Instance, TIM_CHANNEL_3, TIM_CCx_ENABLE);
TIM_CCxChannelCmd(htim5.Instance, TIM_CHANNEL_4, TIM_CCx_ENABLE);
HAL_TIM_Base_Start(&htim5);
EDIT: the DMA interrupts aren't correct yet. The interrupt gets hammered for a while, then isn't called anymore. I think the ADC config isn't correct. But I'm over the main roadblock now.