cancel
Showing results for 
Search instead for 
Did you mean: 

Triggering injected conversion start with TIM1_CH4

chris12892
Associate II
Posted on August 23, 2016 at 21:01

In my STM32F2 application, I need to trigger the conversion start of several injected channels using TIM_CH4. The documents are a little bit unclear as to how to configure the timer for this.

It seems like I need to configure TIM1_CH4 as a PWM output, but if that's the case, the wave would go high immediately on timer reset and the conversion would start. To address this, I invert the polarity of the CH4 PWM wave, but keep the ADC injected start trigger set to a rising edge. this would mean that the wave would go high on compare, and then the conversion would be triggered. Can anyone comment if I'm on the right track with this?

// Init ADC for current sampling
void InitAdc()
{
// Enable Clocks
__GPIOC_CLK_ENABLE();
__ADC1_CLK_ENABLE();
__DMA2_CLK_ENABLE();
// Common current sense GPIO
GPIO_InitTypeDef GPIO_InitStruct;
GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
GPIO_InitStruct.Pull = GPIO_NOPULL;
// Gate driver 1: SO1
GPIO_InitStruct.Pin = GPIO_PIN_1;
HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
// Gate driver 2: SO2
GPIO_InitStruct.Pin = GPIO_PIN_2;
HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
// Configure the ADC
adcHandle.Instance = ADC1;
adcHandle.Init.ClockPrescaler = ADC_CLOCK_SYNC_PCLK_DIV2;
adcHandle.Init.Resolution = ADC_RESOLUTION_12B;
adcHandle.Init.ScanConvMode = DISABLE; 
adcHandle.Init.DataAlign = ADC_DATAALIGN_RIGHT;
adcHandle.Init.ContinuousConvMode = DISABLE;
adcHandle.Init.DiscontinuousConvMode = DISABLE;
adcHandle.Init.ExternalTrigConv = ADC_SOFTWARE_START;
adcHandle.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE;
adcHandle.Init.EOCSelection = DISABLE;
adcHandle.Init.DMAContinuousRequests = DISABLE;
adcHandle.Init.NbrOfConversion = 0;
adcHandle.Init.NbrOfDiscConversion = 0;
// Commit the ADC
HAL_ADC_Init(&adcHandle);
// NVIC configuration for DMA Input data interrupt
HAL_NVIC_SetPriority(DMA2_Stream0_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(DMA2_Stream0_IRQn);
// Configure for injected channels
ADC_InjectionConfTypeDef adcInjectedConfig;
adcInjectedConfig.AutoInjectedConv = DISABLE; // As per note in driver
adcInjectedConfig.ExternalTrigInjecConv = ADC_EXTERNALTRIGINJECCONV_T1_CC4; // TIM1 compare
adcInjectedConfig.ExternalTrigInjecConvEdge = ADC_EXTERNALTRIGCONVEDGE_RISING; //
adcInjectedConfig.InjectedDiscontinuousConvMode = DISABLE; // Because we are using main seq
adcInjectedConfig.InjectedSamplingTime = ADC_SAMPLETIME_3CYCLES;
adcInjectedConfig.InjectedOffset = 0;
// Channel 11 :: SO1
adcInjectedConfig.InjectedChannel = ADC_CHANNEL_11;
adcInjectedConfig.InjectedRank = ADC_INJECTED_RANK_1;
HAL_ADCEx_InjectedConfigChannel(&adcHandle, &adcInjectedConfig);
// Channel 12 :: SO2
adcInjectedConfig.InjectedChannel = ADC_CHANNEL_11;
adcInjectedConfig.InjectedRank = ADC_INJECTED_RANK_2;
HAL_ADCEx_InjectedConfigChannel(&adcHandle, &adcInjectedConfig);
// Configure DMA
adcDmaHandle.Instance = DMA2_Stream0;
adcDmaHandle.Init.Channel = DMA_CHANNEL_0;
adcDmaHandle.Init.Direction = DMA_PERIPH_TO_MEMORY;
adcDmaHandle.Init.PeriphInc = DMA_PINC_DISABLE;
adcDmaHandle.Init.MemInc = DMA_MINC_ENABLE;
adcDmaHandle.Init.PeriphDataAlignment = DMA_PDATAALIGN_WORD;
adcDmaHandle.Init.MemDataAlignment = DMA_MDATAALIGN_WORD;
adcDmaHandle.Init.Mode = DMA_CIRCULAR;
adcDmaHandle.Init.Priority = DMA_PRIORITY_HIGH;
adcDmaHandle.Init.MemBurst = DMA_MBURST_SINGLE;
adcDmaHandle.Init.PeriphBurst = DMA_PBURST_SINGLE;
// Bring DMA up 
HAL_DMA_Init(&adcDmaHandle);
// Associate the DMA handle
__HAL_LINKDMA(&adcHandle, DMA_Handle, adcDmaHandle);
// Start the conversion
//HAL_ADC_Start_DMA(&adcHandle, conversionResults, 2);
}
void InitMotorControl()
{ 
// Enable clocks
__TIM1_CLK_ENABLE();
// [[ .. Code to configure PWM channels ommited .. ]]
// Configure the timer
pwmOutTimer.Instance = TIM1;
pwmOutTimer.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
pwmOutTimer.Init.CounterMode = TIM_COUNTERMODE_UP;
pwmOutTimer.Init.Period = MOTOR_CONTROL_PWM_PERIOD;
// Commit the timer
HAL_TIM_PWM_Init(&pwmOutTimer);
// ADC sync channel
adcSyncConfig.OCMode = TIM_OCMODE_PWM1;
adcSyncConfig.OCFastMode = TIM_OCFAST_DISABLE;
adcSyncConfig.OCIdleState = TIM_OCIDLESTATE_SET;
adcSyncConfig.OCNIdleState = TIM_OCNIDLESTATE_RESET;
adcSyncConfig.OCPolarity = TIM_OCPOLARITY_LOW;
adcSyncConfig.OCNPolarity = TIM_OCNPOLARITY_LOW;
adcSyncConfig.Pulse = 0;
// Commit ADC sync config
//HAL_TIM_OC_ConfigChannel(&pwmOutTimer, &adcSyncConfig, TIM_CHANNEL_4);
HAL_TIM_PWM_ConfigChannel(&pwmOutTimer, &adcSyncConfig, TIM_CHANNEL_4);
// Configure break and deadtime
TIM_BreakDeadTimeConfigTypeDef TIM_BreakDeadTimeConfig;
TIM_BreakDeadTimeConfig.BreakState = TIM_BREAK_DISABLE;
TIM_BreakDeadTimeConfig.DeadTime = 10;
TIM_BreakDeadTimeConfig.OffStateRunMode = TIM_OSSR_ENABLE;
TIM_BreakDeadTimeConfig.OffStateIDLEMode = TIM_OSSI_ENABLE;
TIM_BreakDeadTimeConfig.LockLevel = TIM_LOCKLEVEL_1; 
TIM_BreakDeadTimeConfig.BreakPolarity = TIM_BREAKPOLARITY_HIGH;
TIM_BreakDeadTimeConfig.AutomaticOutput = TIM_AUTOMATICOUTPUT_ENABLE;
// Commit the break/deadtime config
HAL_TIMEx_ConfigBreakDeadTime(&pwmOutTimer, &TIM_BreakDeadTimeConfig);
// Commit the timer sync 
//HAL_TIM_OC_Start(&pwmOutTimer, TIM_CHANNEL_4);
HAL_TIM_PWM_Start(&pwmOutTimer, TIM_CHANNEL_4);
}

2 REPLIES 2
mark239955_stm1
Associate II
Posted on August 24, 2016 at 14:30

I've never worked with an F2, but assuming that TIM1 in the F2 is very similar to TIM1 in the F4, take a look at the OC4M field in the CCMR2 register.  If you set OC4M to 0b000, any TIM1_CH4 outputs are frozen (so, no PWM output), but the timer still generates CC4 output triggers (ST also refer to them as OC4REF for maximum confusion) that can cause the ADC to start a conversion.

Unfortunately, I can't help you with the Cube HAL code; I use RTFM + register access.

chris12892
Associate II
Posted on August 24, 2016 at 17:20

I actually ended up figuring it out.

I accidentally omitted setting the NbrOfInjectedConv in the ADC injected channel setup. Other than that, PWM1 mode must be used with the timer CC channel, and you must set a rising or falling edge on the injected conversion start trigger settings. I haven't verified that the conversion is actually occurring at the right time, but it is definitely occurring.