2013-01-31 05:11 AM
Hi
I am a power electronics engineer and I have been using the STM32F4 to develop AC motor drives and its great I am now working on an application with space vector modulation and I have ran into a difficulty which I would love some advice on For previous programs I could use an interrupt to update a count for timing applications and it was pretty straight forward For my new program I need three PWM outputs center aligned which I can generate quite easily I can update the frequency and duty cycle but what I need to do is generate an interrupt on the carrier apex and I just don't know if I am barking up the right tree? I can upload some code when I get in tonight but can anyone advise me if its feasable to use CCR1, CCR2 and CCR3 as the duty cycles of the different PWM outputs so I have three outputs from one timer and what I think would be great is if I could set CCR4 to the same value as the ARR register so that when the CNT is equal to CCR4 I know its the peak of the carrier but I just don't know how to generate an interrupt based on a CCR4 value is this possible? or is there another way to generate an interrupt on the carrier apex? all I can see changing in the registers is the DIR bit I have been trying for about four days now and I have the manuals etc but I just cant see any useful info in there (it makes terrible reading IMO) The other option would be to sync two timers together and use a separate timer to generate an interrupt but that seems like it shouldnt be needed? Any help/advice is most welcome #center-aligned-pwm2013-01-31 05:19 AM
I could set CCR4 to the same value as the ARR register so that when the CNT is equal to CCR4 I know its the peak of the carrier but I just don't know how to generate an interrupt based on a CCR4 value is this possible?
Like TIM_IT_CC4? but wouldn't that just do what TIM_IT_Update does now?2013-01-31 06:45 AM
2013-02-02 11:36 AM
I managed to get the interrupt firing with PWM on the same timer
I need to use center aligned PWM but my problem now is that the interrupt fires on over flow and underflow where as I need it to fire only once per PWM period = 50us Heres my code /* Includes ------------------------------------------------------------------*/ #include ''stm32f4_discovery.h'' #include <stdio.h> int n=0; GPIO_InitTypeDef GPIO_InitStructure; TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; TIM_OCInitTypeDef TIM_OCInitStructure; void TIM4_IRQHandler(void) { if (TIM_GetITStatus(TIM4, TIM_IT_Update) != RESET) { GPIO_ToggleBits(GPIOB, GPIO_Pin_11); TIM_ClearITPendingBit(TIM4, TIM_IT_Update); } } /* Private function prototypes -----------------------------------------------*/ void TIM_Config(void); void PWM_Config(void); void PWM_SetDC(uint16_t dutycycle); void Delay(__IO uint32_t nCount); void GPIO_Config(void); /* Private functions ---------------------------------------------------------*/ int main(void) { uint16_t pulse_width = 0; GPIO_Config(); TIM_Config(); PWM_Config(); GPIO_ResetBits(GPIOB, GPIO_Pin_11| GPIO_Pin_13| GPIO_Pin_15); while (1) { PWM_SetDC(pulse_width++); if (pulse_width >= 699) { pulse_width = 0; } Delay(100000); } } void GPIO_Config(void) { /* GPIOD clock enable */ RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOD, ENABLE); /* GPIOD For PWM Configuration: TIM4 CH1 (PD12), TIM4 CH2 (PD13), TIM3 CH3 (PD14), TIM3 CH4 (PD15) */ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12| GPIO_Pin_13| GPIO_Pin_14| GPIO_Pin_15; 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(GPIOD, &GPIO_InitStructure); /* Connect TIM3 pins to AF2 */ GPIO_PinAFConfig(GPIOD, GPIO_PinSource12, GPIO_AF_TIM3); GPIO_PinAFConfig(GPIOD, GPIO_PinSource13, GPIO_AF_TIM3); GPIO_PinAFConfig(GPIOD, GPIO_PinSource14, GPIO_AF_TIM3); GPIO_PinAFConfig(GPIOD, GPIO_PinSource15, GPIO_AF_TIM3); /* GPIOB Periph clock enable */ RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE); /* Configure PB11, PB13 and PB15 in output pushpull mode */ RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE); GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11 | GPIO_Pin_13| GPIO_Pin_15; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT; GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz; GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_DOWN; GPIO_Init(GPIOB, &GPIO_InitStructure); } void TIM_Config(void) { NVIC_InitTypeDef NVIC_InitStructure; NVIC_InitStructure.NVIC_IRQChannel = TIM4_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure); /* TIM4 clock enable */ RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4, ENABLE); /* Time base configuration */ TIM_TimeBaseStructure.TIM_Period = 700; TIM_TimeBaseStructure.TIM_Prescaler = 2; TIM_TimeBaseStructure.TIM_ClockDivision = 0; TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_CenterAligned3; TIM_TimeBaseInit(TIM4, &TIM_TimeBaseStructure); /* TIM IT enable */ TIM_ITConfig(TIM4, TIM_IT_Update, ENABLE); /* TIM2 enable counter */ TIM_Cmd(TIM4, ENABLE); } void PWM_Config(void) { /* PWM1 Mode configuration: */ TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM2; TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; TIM_OCInitStructure.TIM_Pulse = 0; /* PWM2 Mode TIM4 CH1 = PD 12 */ TIM_OC1Init(TIM4, &TIM_OCInitStructure); TIM_OC1PreloadConfig(TIM4, TIM_OCPreload_Enable); /* PWM2 Mode TIM4 CH2 = PD 13 */ TIM_OC2Init(TIM4, &TIM_OCInitStructure); TIM_OC2PreloadConfig(TIM4, TIM_OCPreload_Enable); /* PWM2 Mode TIM4 CH3 = PD 14 */ TIM_OC3Init(TIM4, &TIM_OCInitStructure); TIM_OC3PreloadConfig(TIM4, TIM_OCPreload_Enable); /* PWM2 Mode TIM4 CH4 = PD 15 */ TIM_OC4Init(TIM4, &TIM_OCInitStructure); TIM_OC4PreloadConfig(TIM4, TIM_OCPreload_Enable); TIM_ARRPreloadConfig(TIM4, ENABLE); /* TIM4 enable counter */ TIM_Cmd(TIM4, ENABLE); } void PWM_SetDC(uint16_t dutycycle) { TIM4->CCR1 = dutycycle; TIM4->CCR2 = dutycycle; TIM4->CCR3 = dutycycle; TIM4->CCR4 = dutycycle; } void Delay(__IO uint32_t nCount) { while(nCount--) { } } If anyone can tell me a way to only interrupt when the CNT=ARR that would be great I could use CC4 interrupt and set CCR4 to ARR but is there a better way? Thanks in advance2013-02-02 11:39 AM
A separate question I have is regarding PWM polarity
I can use PWM1 or PWM2 to swap polarity but I can also use TIM_OCPolarity to swap the polarity so is there any difference between the two? What method should I be using to change the polarity? and what is the purpose of two different ways Thanks2013-02-03 04:30 AM
Anyone got any ideas?
2013-02-10 05:58 AM