cancel
Showing results for 
Search instead for 
Did you mean: 

pwm output timer1

mohamad_armoon
Associate III
Posted on July 06, 2014 at 15:59

hi guys, i create a program to generate pwm signals in stm32f407 i did it in past for another timer but when i wanna do it for timer1 i doesn.t work.

here is my code :

#include <stm32f4xx.h>
void
InitializeTimer1(
int
period = 1000)
{
RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1,ENABLE);
TIM_TimeBaseInitTypeDef timerInitStructure;
timerInitStructure.TIM_Prescaler = 1000;
timerInitStructure.TIM_CounterMode = TIM_CounterMode_Up;
timerInitStructure.TIM_Period = period;
timerInitStructure.TIM_ClockDivision = TIM_CKD_DIV1;
timerInitStructure.TIM_RepetitionCounter = 0;
TIM_TimeBaseInit(TIM1, &timerInitStructure);
TIM_Cmd(TIM1, ENABLE);
}
void
initializeGPIO()
{
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOE, ENABLE);
GPIO_InitTypeDef gpioStructure;
gpioStructure.GPIO_Pin = GPIO_Pin_9 | GPIO_Pin_11 | GPIO_Pin_13 |GPIO_Pin_14;
gpioStructure.GPIO_Mode = GPIO_Mode_AF;
gpioStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOE, &gpioStructure);
}
void
InitializePWMChannel1()
{
TIM_OCInitTypeDef outputChannelInit = {0,};
outputChannelInit.TIM_OCMode = TIM_OCMode_PWM1;
outputChannelInit.TIM_Pulse = 300;
outputChannelInit.TIM_OutputState = TIM_OutputState_Enable;
outputChannelInit.TIM_OCPolarity = TIM_OCPolarity_High;
TIM_OC2Init(TIM1, &outputChannelInit);
TIM_OC2PreloadConfig(TIM1, TIM_OCPreload_Enable);
GPIO_PinAFConfig(GPIOE, GPIO_PinSource11, GPIO_AF_TIM1);
}
int
main()
{
InitializeTimer1();
initializeGPIO();
InitializePWMChannel1();
for
(;;)
{}
}

can any body help me , what's wrong with my code ?? any helpappreciate
17 REPLIES 17
mohamad_armoon
Associate III
Posted on July 16, 2014 at 04:20

hi clive ,

after you mentioned i wrote some things about timer in manual but it just said about register and some things else, and i also check the links you put here and compare your code with mine , but all of steps was same as each other. However, again i wrote another code exactly with your procedure , in main loop i set LED to blink , and when i connect PA3(the generated pwm) to PB4 to measure the frequency and duty cycle , blinking stops , it seems the micro gets interrupt well but i don't get any thing from usart , can you explain what's exactly wrong with my code ??

#include <stm32f4xx.h>
void

Delay(__IO uint32_t nCount);
void

init_usart(

void

){
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOD, ENABLE);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE);
GPIO_InitTypeDef GPIO_InitStructure;
USART_InitTypeDef USART_InitStructure;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5 | GPIO_Pin_6;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP ;
GPIO_Init(GPIOD, &GPIO_InitStructure);
GPIO_PinAFConfig(GPIOD, GPIO_PinSource5, GPIO_AF_USART2);
GPIO_PinAFConfig(GPIOD, GPIO_PinSource6, GPIO_AF_USART2);
USART_InitStructure.USART_BaudRate = 9600;
USART_InitStructure.USART_WordLength = USART_WordLength_8b;
USART_InitStructure.USART_StopBits = USART_StopBits_1;
USART_InitStructure.USART_Parity = USART_Parity_No;
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
USART_InitStructure.USART_Mode = USART_Mode_Tx | USART_Mode_Rx;
USART_Init(USART2, &USART_InitStructure);
USART_Cmd(USART2, ENABLE);
}
void

LED_STATUS()
{
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12 | GPIO_Pin_13| GPIO_Pin_14| 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_NOPULL;
GPIO_Init(GPIOD, &GPIO_InitStructure);
}
void

InitializeTimer2(

int

period = 1000)
{
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE);
TIM_TimeBaseInitTypeDef timerInitStructure;
timerInitStructure.TIM_Prescaler = (uint16_t) (((SystemCoreClock / 1000000) / 2) - 1);
timerInitStructure.TIM_CounterMode = TIM_CounterMode_Up;
timerInitStructure.TIM_Period = period;
timerInitStructure.TIM_ClockDivision = TIM_CKD_DIV1;
timerInitStructure.TIM_RepetitionCounter = 0;
TIM_TimeBaseInit(TIM2, &timerInitStructure);
TIM_Cmd(TIM2, ENABLE);
TIM_CtrlPWMOutputs(TIM2, ENABLE);
}
void

initializeGPIOA()
{
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);
GPIO_InitTypeDef gpioStructure;
gpioStructure.GPIO_Pin = GPIO_Pin_3 ;
gpioStructure.GPIO_Mode = GPIO_Mode_AF;
gpioStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &gpioStructure);
}
void

InitializePWMChannel1()
{
TIM_OCInitTypeDef outputChannelInit = {0,};
outputChannelInit.TIM_OCMode = TIM_OCMode_PWM1;
outputChannelInit.TIM_Pulse = 900;
outputChannelInit.TIM_OutputState = TIM_OutputState_Enable;
outputChannelInit.TIM_OCPolarity = TIM_OCPolarity_High;
TIM_OC4Init(TIM2, &outputChannelInit);
TIM_OC4PreloadConfig(TIM2, TIM_OCPreload_Enable);
GPIO_PinAFConfig(GPIOA, GPIO_PinSource3, GPIO_AF_TIM2);
}
//***************************************************
void

TIM3_Configuration(

void

)
{
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_ICInitTypeDef TIM_ICInitStructure;
GPIO_InitTypeDef GPIO_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
/* TIM3

clock

enable */
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);
/* GPIO clock enable */
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE);
/* Configure GPIO input for timer */
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4;

// PB4 TIM3_CH1

GPIO_Init(GPIOB, &GPIO_InitStructure);
/* Connect TIM3 pins to AF */
GPIO_PinAFConfig(GPIOB, GPIO_PinSource4, GPIO_AF_TIM3);
/* Enable the TIM3 global Interrupt */
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn;
NVIC_Init(&NVIC_InitStructure);
/* Time base configuration - SystemCoreClock = 168000000 for 168 MHz board ABP1 @ 42 MHz (DIV4) */
TIM_TimeBaseStructure.TIM_Prescaler = (uint16_t) (((SystemCoreClock / 1000000) / 2) - 1);

// Shooting for 1 MHz, (1us)

TIM_TimeBaseStructure.TIM_Period = 0xFFFF;

// Maximal

TIM_TimeBaseStructure.TIM_ClockDivision = 0;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure);
/* Configure PWM Input Capture */
TIM_ICInitStructure.TIM_Channel = TIM_Channel_1;

// PB4 TIM3_CH1

TIM_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising;
TIM_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI;
TIM_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1;
TIM_ICInitStructure.TIM_ICFilter = 0x0;
TIM_PWMIConfig(TIM3, &TIM_ICInitStructure);
/* Select the TIM3 Input Trigger: TI1FP1 */
TIM_SelectInputTrigger(TIM3, TIM_TS_TI1FP1);
/* Select the slave Mode: Reset Mode */
TIM_SelectSlaveMode(TIM3, TIM_SlaveMode_Reset);
TIM_SelectMasterSlaveMode(TIM3, TIM_MasterSlaveMode_Enable);
/* TIM Interrupts enable */
TIM_ITConfig(TIM3, TIM_IT_CC1, ENABLE);
/* TIM3 enable counter */
TIM_Cmd(TIM3, ENABLE);
}
union

{uint16_t value; uint8_t byte[2];} inttobyte;
volatile

uint16_t Reading[2];

// Readings from PB4 TIM3_CH1 (1us units)

void

TIM3_IRQHandler(

void

)
{
if

(TIM_GetITStatus(TIM3, TIM_IT_CC1) != RESET)
{
TIM_ClearITPendingBit(TIM3, TIM_IT_CC1);
Reading[0] = TIM_GetCapture1(TIM3);

// Period (us) ~20000

Reading[1] = TIM_GetCapture2(TIM3);

// Duty/Width (us) ~1500 or whatever (600-2400 us)

inttobyte.value = Reading[0];
for

(

int

i = 0 ; i < 2 ; i++){
while

(USART_GetFlagStatus(USART2, USART_FLAG_TXE) == RESET);
USART_SendData(USART2,inttobyte.byte[i]);
}
}
}
int

main()
{
init_usart();
LED_STATUS();
InitializeTimer2();
initializeGPIOA();
InitializePWMChannel1();
TIM3_Configuration();
while

(

true

){
GPIO_SetBits(GPIOD,GPIO_Pin_12);
Delay(0xFFFFF);
GPIO_ResetBits(GPIOD,GPIO_Pin_12);
Delay(0xFFFFF);
}
return

0;
}
void

Delay(__IO uint32_t nCount)
{
while

(nCount--)
{
}
}

thanks a lot
Posted on July 16, 2014 at 04:57

You seem to be using C++ syntax, are you sure it's not mangling the IRQ name, check the .MAP file.

Try using

extern ''C''

 void

TIM3_IRQHandler(

void

)

Does the USART output ASCII characters properly as configured here? If not consider if HSE_VALUE reflects the 8 MHz clock of the STM32F4-DISCO The code is trying to output two binary bytes, these will not be in ASCII. Perhaps use RealTerm in Hex output mode?
Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
mohamad_armoon
Associate III
Posted on July 18, 2014 at 07:35

hi clive. i really don't know what's going on , i use c++ syntax and iar compiler but i don't know maybe it's my compiler problem , i have same problem when i was using interrupt for usart and it solved when i copy the IRQ to stm32f4xx_it.c and compiled again,

so you think that the structure of the code is true ??

i did what is necessary for getting the frequency and duty cycle of on pwm channnel ??

Posted on July 18, 2014 at 15:38

C++ uses name mangling, this would cause the interrupt vector table entry to not point to your IRQHandler, and consequently it wouldn't get called. You'd need to review your .MAP file, and use the method I suggested to ensure you have correct linkage of the function.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
mohamad_armoon
Associate III
Posted on July 20, 2014 at 15:37

hi again.

excuse me, what is exactly the .MAP file, i have never seen this,

and how the program counter knows that it should go to for example to IRQHandler function when the interrupt occur ??

because this function is not defined in somewhere else.

i just want to know how the compiler know what function have to be executed after interrupt ?

Posted on July 20, 2014 at 16:35

It's a file output by a Linker describing how the space and functions were placed within the executable image created. Check the output directory for the project.

If you don't understand how the processor works, I would suggest reviewing a technical manual for it, or another guiding text.

http://www.st.com/st-web-ui/static/active/en/resource/technical/document/programming_manual/DM00046982.pdf

http://store.elsevier.com/The-Definitive-Guide-to-ARM%C2%AE-Cortex%C2%AE-M3-and-Cortex%C2%AE-M4-Processors/Joseph-Yiu/isbn-9780124080829/

The processor includes an interrupt controller called the NVIC, wiring inside the chip associates particular peripherals and sources with specific interrupt numbers, and these are described in a ''Vector Table'' which can be found in startup_stm32f4x.s (or some equivalent file)
Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
mohamad_armoon
Associate III
Posted on August 22, 2014 at 13:29

hi clive.

i really appreciate you because of your information.i was far from stm for a while because of exams . that's right the c++ compiler mangle my code. i'm a real fool.i just had to use extern ''c''

thanks . 

after 3 years work with c and c++ i didn't find an application for extern ''C'', and i didn't realize  it's function after 1000 time reading open source projects until now that i wrote my own code .

but how did you find that the compiler mangle my function name . is it a problem for this compiler, why many of other c++ functions and methods i wrote wasn't like that. and worked well. wasn't this problem because of my main code was .cpp but the stm32f4xx_it was .c ??
Posted on August 22, 2014 at 16:27

Name mangling is a feature of all C++ compilers and platforms I am familiar with (assume that's quite a few), it permits functions with the same name, but different type parameters to be identified within the name space, and linked correctly. Generally it will occur with .CPP files, but usually there are command line options to force a compiler to use C or C++ parsing. The linkage gets to be an issue if you mixed C, C++ and Assembler source files, and then you have to be careful and explicitly define things.

You'll often observe it being used in include files (extern ''C'', or cdecl), and also the #ifdef/#define practice that stops the include file being parsed more than once, where it might be pulled/touched by multiple other source files.

Looking at the .MAP allows you both to see the names used, and if subroutines/functions were jettisoned by ''dead code elimination'' techniques the linker might apply when it sees (or assumes) noting calls a particular piece of code.
Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..