2014-07-06 06:59 AM
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
2014-07-15 07:20 PM
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
2014-07-15 07:57 PM
You seem to be using C++ syntax, are you sure it's not mangling the IRQ name, check the .MAP file.
Try usingextern ''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?
2014-07-17 10:35 PM
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 ??2014-07-18 06:38 AM
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.
2014-07-20 06:37 AM
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 ?2014-07-20 07:35 AM
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. 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)2014-08-22 04:29 AM
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 ??2014-08-22 07:27 AM
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.