2015-01-22 05:11 PM
Hello,
I am new to this forum and have migrated from Freescale to STM32 based projects. I am implementing a switched mode power supply (SMPS) on the STM32F4Discovery board. I have successfully configured PB0 as a PWM output using TIM1_CH2N. Based on the information in the RM0090 Reference Manual (p.538) an external signal applied to the ETRF pin (PA12) can be used to gate the PWM output. On the Discovery board this is used by the OTG connector. However, I rigged up a USB cable to assert a signal on PA12 and verified its operation by configuring it as a GPIO. Based on the code below does anyone know what I have done wrong since the ETRF does not seem to be gating the PWM? Thanks in advance!
GPIO_InitTypeDef GPIO_InitStructure;
/* GPIOB Clocks enable */
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE);
/* GPIOB Configuration: Channel 2N as alternate function push-pull */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP ;
GPIO_Init(GPIOB, &GPIO_InitStructure);
GPIO_PinAFConfig(GPIOB, GPIO_PinSource0, GPIO_AF_TIM1);
/* GPIOA Clocks enable */
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);
/* Configure ETR for current control */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_DOWN;
GPIO_PinAFConfig(GPIOA, GPIO_PinSource12, GPIO_AF_EVENTOUT);
GPIO_Init(GPIOA, &GPIO_InitStructure);
/* Compute the value to be set in ARR regiter to generate signal frequency at 1MHZ */
TimerPeriod = (SystemCoreClock / 1000000) - 1;
/* Compute CCR2 value to generate a duty cycle at 667% for channel 2 and 2N */
Channel2Pulse = (uint16_t) (((uint32_t) 666 * (TimerPeriod - 1)) / 1000);
/* TIM1 clock enable */
RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1 , ENABLE);
/* Time Base configuration */
TIM_TimeBaseStructure.TIM_Prescaler = 0;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseStructure.TIM_Period = TimerPeriod;
TIM_TimeBaseStructure.TIM_ClockDivision = 0;
TIM_TimeBaseStructure.TIM_RepetitionCounter = 0;
TIM_TimeBaseInit(TIM1, &TIM_TimeBaseStructure);
/* Channel 2 Configuration in PWM mode */
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM2;
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
TIM_OCInitStructure.TIM_OutputNState = TIM_OutputNState_Enable;
TIM_OCInitStructure.TIM_Pulse = Channel2Pulse;
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_Low;
TIM_OCInitStructure.TIM_OCNPolarity = TIM_OCNPolarity_High;
TIM_OCInitStructure.TIM_OCIdleState = TIM_OCIdleState_Set;
TIM_OCInitStructure.TIM_OCNIdleState = TIM_OCIdleState_Reset;
TIM_OC2Init(TIM1, &TIM_OCInitStructure);
/* Configure ETR for current control */
TIM_ETRConfig(TIM1, TIM_ExtTRGPSC_OFF, TIM_ExtTRGPolarity_NonInverted, 0);
TIM_ClearOC2Ref(TIM1, TIM_OCClear_Enable);
}
#tim1 #pwm #etrf #smps
2015-01-26 10:44 AM
For the interests of others I have found the solution for the ETRF pin configuration:
GPIO_InitTypeDef GPIO_InitStructure;
/* GPIOB Clocks enable */
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE);
/* GPIOB Configuration: Channel 2N as alternate function push-pull */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP ;
GPIO_Init(GPIOB, &GPIO_InitStructure);
GPIO_PinAFConfig(GPIOB, GPIO_PinSource0, GPIO_AF_TIM1);
/* GPIOA Clocks enable */
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);
/* Configure ETR for current control */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_DOWN;
GPIO_PinAFConfig(GPIOA, GPIO_PinSource12, GPIO_AF_TIM1);
GPIO_Init(GPIOA, &GPIO_InitStructure);
/* TIM1 Configuration ---------------------------------------------------
Generate PWM signals with various different duty cycles:
TIM1 input clock (TIM1CLK) is set to 2 * APB2 clock (PCLK2), since APB2
prescaler is different from 1.
TIM1CLK = 2 * PCLK2
PCLK2 = HCLK / 2
=> TIM1CLK = 2 * (HCLK / 2) = HCLK = SystemCoreClock
TIM1CLK = SystemCoreClock, Prescaler = 0, TIM1 counter clock = SystemCoreClock
SystemCoreClock is set to 168 MHz for STM32F4xx devices
The objective is to generate a PWM signal at 1MHz:
- TIM1_Period = (SystemCoreClock / 1000000) - 1
The channel 2 and channel 2N duty cycle is set to 6%
The Timer pulse is calculated as follows:
- ChannelxPulse = DutyCycle * (TIM1_Period - 1) / 100
Note:
SystemCoreClock variable holds HCLK frequency and is defined in system_stm32f4xx.c file.
Each time the core clock (HCLK) changes, user had to call SystemCoreClockUpdate()
function to update SystemCoreClock variable value. Otherwise, any configuration
based on this variable will be incorrect.
----------------------------------------------------------------------- */
/* Compute the value to be set in ARR regiter to generate signal frequency at 1MHz */
TimerPeriod = (SystemCoreClock / 1000000 ) - 1;
/* Compute CCR2 value to generate a duty cycle at 667% for channel 2 and 2N */
Channel2Pulse = (uint16_t) (((uint32_t) 666 * (TimerPeriod - 1)) / 1000);
/* TIM1 clock enable */
RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1 , ENABLE);
/* Time Base configuration */
TIM_TimeBaseStructure.TIM_Prescaler = 0;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseStructure.TIM_Period = TimerPeriod;
TIM_TimeBaseStructure.TIM_ClockDivision = 0;
TIM_TimeBaseStructure.TIM_RepetitionCounter = 0;
TIM_TimeBaseInit(TIM1, &TIM_TimeBaseStructure);
/* Channel 2 Configuration in PWM mode */
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM2;
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
TIM_OCInitStructure.TIM_OutputNState = TIM_OutputNState_Enable;
TIM_OCInitStructure.TIM_Pulse = Channel2Pulse;
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_Low;
TIM_OCInitStructure.TIM_OCNPolarity = TIM_OCNPolarity_High;
TIM_OCInitStructure.TIM_OCIdleState = TIM_OCIdleState_Set;
TIM_OCInitStructure.TIM_OCNIdleState = TIM_OCIdleState_Reset;
TIM_OC2Init(TIM1, &TIM_OCInitStructure);
/* Configure ETR for current control */
TIM_ETRConfig(TIM1, TIM_ExtTRGPSC_OFF, TIM_ExtTRGPolarity_NonInverted, 0);
TIM_ClearOC2Ref(TIM1, TIM_OCClear_Enable);