2014-11-21 03:04 AM
2014-11-21 04:11 AM
Pin configuration is broken, wrong pin, wrong bank
Duty is wrong, Period = N-1, Pulse (50%) = N / 2, not Pulse = (N - 2) / 2 Channel 3 setting configure Channel 12014-11-21 04:43 AM
PB9?? The AF settings also appear completely wrong.
A quick blind fix here, using the data sheet pin configurations.#include ''stm32f30x.h''
static void TIM_Config(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_OCInitTypeDef TIM_OCInitStructure;
uint16_t TimerPeriod = 0;
uint16_t ChannelPulse = 0;
/* GPIOA & GPIOB Clocks enable */
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA | RCC_AHBPeriph_GPIOB, ENABLE);
/* GPIOA & GPIOB Configuration: Channel 3 (TIM2) and Channel 1 (TIM15) as alternate function push-pull */
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_InitStructure.GPIO_Pin = GPIO_Pin_9; // TIM2_CH3
GPIO_Init(GPIOA, &GPIO_InitStructure);
GPIO_PinAFConfig(GPIOA, GPIO_PinSource9, GPIO_AF_10); // TIM2
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_14; // TIM15_CH1
GPIO_Init(GPIOB, &GPIO_InitStructure);
GPIO_PinAFConfig(GPIOB, GPIO_PinSource14, GPIO_AF_1); // TIM15
/* Tim15 and Tim2 Configuration ---------------------------------------------------
Generate 2 PWM signals :
Tim15 input clock (Tim15CLK) is set to APB2 clock (PCLK2)
Tim2 input clock (Tim2CLK) is set to APB1 clock (PCLK1)
=> Tim15CLK = PCLK2 = SystemCoreClock
=> Tim2CLK = PCLK1 = SystemCoreClock
Tim15CLK = SystemCoreClock, Prescaler = 0, Tim15 counter clock = SystemCoreClock
Tim2CLK = SystemCoreClock, Prescaler = 0, Tim2 counter clock = SystemCoreClock
SystemCoreClock is set to 72 MHz for STM32F30x devices
The objective is to generate 2 PWM signal at 1MHz for Tim15 and at 4MHz for Tim2:
- Tim15_Period = (SystemCoreClock / 1000000) - 1
- Tim2_Period = (SystemCoreClock / 4000000) - 1
The channel 1 and channel 3 duty cycle are set to 50%
The Timer pulse is calculated as follows:
- Channel2Pulse = DutyCycle * (Tim15_Period + 1) / 100
- Channel3Pulse = DutyCycle * (Tim2_Period + 1) / 100
Note:
SystemCoreClock variable holds HCLK frequency and is defined in system_stm32f30x.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);
/* Compute CCR1 value to generate a duty cycle at 50% for channel 1 */
ChannelPulse = (uint16_t) (((uint32_t) 5 * TimerPeriod) / 10);
/* Tim15 clock enable */
RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM15, ENABLE);
/* Time Base configuration */
TIM_TimeBaseStructure.TIM_Prescaler = 0;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseStructure.TIM_Period = TimerPeriod - 1;
TIM_TimeBaseStructure.TIM_ClockDivision = 0;
TIM_TimeBaseStructure.TIM_RepetitionCounter = 0;
TIM_TimeBaseInit(TIM15, &TIM_TimeBaseStructure);
/* Channel Configuration in PWM mode */
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM2;
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
TIM_OCInitStructure.TIM_Pulse = ChannelPulse;
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
TIM_OCInitStructure.TIM_OCIdleState = TIM_OCIdleState_Set;
TIM_OC1Init(TIM15, &TIM_OCInitStructure); // TIM15_CH1
/* Tim1 counter enable */
TIM_Cmd(TIM15, ENABLE);
/*----------------------------------------------------------------------- */
/* Compute the value to be set in ARR regiter to generate signal frequency at 4MHz */
TimerPeriod = (SystemCoreClock / 4000000 );
/* Compute CCR1 value to generate a duty cycle at 50% for channel 3 */
ChannelPulse = (uint16_t) (((uint32_t) 5 * TimerPeriod) / 10);
/* Tim2 clock enable */
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2 , ENABLE);
/* Time Base configuration */
TIM_TimeBaseStructure.TIM_Prescaler = 0;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseStructure.TIM_Period = TimerPeriod - 1;
TIM_TimeBaseStructure.TIM_ClockDivision = 0;
TIM_TimeBaseStructure.TIM_RepetitionCounter = 0;
TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);
/* Channel Configuration in PWM mode */
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM2;
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
TIM_OCInitStructure.TIM_Pulse = ChannelPulse;
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
TIM_OCInitStructure.TIM_OCIdleState = TIM_OCIdleState_Set;
TIM_OC3Init(TIM2, &TIM_OCInitStructure); // TIM2_CH3
/* Tim2 counter enable */
TIM_Cmd(TIM2, ENABLE);
}
int main(void)
{
/*!< At this stage the microcontroller clock setting is already configured,
this is done through SystemInit() function which is called from startup
file (startup_stm32f30x.s) before to branch to application main.
To reconfigure the default setting of SystemInit() function, refer to
system_stm32f30x.c file
*/
/* TIM Configuration */
TIM_Config();
/* Infinite loop */
while (1);
}
#ifdef USE_FULL_ASSERT
/**
* @brief Reports the name of the source file and the source line number
* where the assert_param error has occurred.
* @param file: pointer to the source file name
* @param line: assert_param error line source number
* @retval None
*/
void assert_failed(uint8_t* file, uint32_t line)
{
/* User can add his own implementation to report the file name and line number,
ex: printf(''Wrong parameters value: file %s on line %d
'', file, line) */
/* Infinite loop */
while (1)
{
}
}
#endif
2014-11-21 04:48 AM
Hi Clive,
Pin configuration is broken, wrong pin, wrong bank Looking at STM32F302R8 LQFP48 pinout: PB14=Tim15_ch1(AF1) and PA9=TIM2_CH3. Where am I wrong? I don't understand.Channel 3 setting configure Channel 1 You mean the Timer period of one overwrite the other? Thanks for your feedback. Best regards2014-11-21 04:59 AM
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9 | GPIO_Pin_14;
GPIO_Init(GPIOA, &GPIO_InitStructure); Sets up PA9 and PA14, not PB14 AF_6 != AF1 or AF_10 OC1 != OC3 See blind fix example, I don't have a board/scope to hand and I haven't eat my breakfast yet.2014-11-21 06:24 AM
Sorry to disturb again Clive, but PA14 is assigned for the debugg serial Wire on the STM32F302. As far I understand I can use any other one with correct banck and OC channel.
Thanks a lot for your resolved. Have a good day and take care! Franck2014-11-21 07:53 AM
Still Problem on generating PWM for Timer
I took now Tim15 ch2 (PA3) on PortA AF9 bus APB2. Code is as follow: #include ''stm32f30x.h'' static void TIM_Config(void) { GPIO_InitTypeDef GPIO_InitStructure; TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; TIM_OCInitTypeDef TIM_OCInitStructure; uint16_t TimerPeriod = 0; uint16_t ChannelPulse = 0; /* GPIOA & GPIOB Clocks enable */ RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA | RCC_AHBPeriph_GPIOB, ENABLE); /* GPIOA & GPIOB Configuration: Channel 3 (TIM2) and Channel 1 (TIM15) as alternate function push-pull */ 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_InitStructure.GPIO_Pin = GPIO_Pin_9; // TIM2_CH3 GPIO_Init(GPIOA, &GPIO_InitStructure); GPIO_PinAFConfig(GPIOA, GPIO_PinSource9, GPIO_AF_10); // TIM2 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3; // TIM15_CH2 GPIO_Init(GPIOA, &GPIO_InitStructure); GPIO_PinAFConfig(GPIOA, GPIO_PinSource14, GPIO_AF_9); // TIM15 /* Tim15 and Tim2 Configuration --------------------------------------------------- Generate 2 PWM signals : Tim15 input clock (Tim15CLK) is set to APB2 clock (PCLK2) Tim2 input clock (Tim2CLK) is set to APB1 clock (PCLK1) => Tim15CLK = PCLK2 = SystemCoreClock => Tim2CLK = PCLK1 = SystemCoreClock Tim15CLK = SystemCoreClock, Prescaler = 0, Tim15 counter clock = SystemCoreClock Tim2CLK = SystemCoreClock, Prescaler = 0, Tim2 counter clock = SystemCoreClock SystemCoreClock is set to 72 MHz for STM32F30x devices The objective is to generate 2 PWM signal at 1MHz for Tim15 and at 4MHz for Tim2: - Tim15_Period = (SystemCoreClock / 1000000) - 1 - Tim2_Period = (SystemCoreClock / 4000000) - 1 The channel 1 and channel 3 duty cycle are set to 50% The Timer pulse is calculated as follows: - Channel2Pulse = DutyCycle * (Tim15_Period + 1) / 100 - Channel3Pulse = DutyCycle * (Tim2_Period + 1) / 100 Note: SystemCoreClock variable holds HCLK frequency and is defined in system_stm32f30x.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); /* Compute CCR1 value to generate a duty cycle at 50% for channel 1 */ ChannelPulse = (uint16_t) (((uint32_t) 5 * TimerPeriod) / 10); /* Tim15 clock enable */ RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM15, ENABLE); /* Time Base configuration */ TIM_TimeBaseStructure.TIM_Prescaler = 0; TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; TIM_TimeBaseStructure.TIM_Period = TimerPeriod - 1; TIM_TimeBaseStructure.TIM_ClockDivision = 0; TIM_TimeBaseStructure.TIM_RepetitionCounter = 0; TIM_TimeBaseInit(TIM15, &TIM_TimeBaseStructure); /* Channel Configuration in PWM mode */ TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM2; TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; TIM_OCInitStructure.TIM_Pulse = ChannelPulse; TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; TIM_OCInitStructure.TIM_OCIdleState = TIM_OCIdleState_Set; TIM_OC2Init(TIM15, &TIM_OCInitStructure); // TIM15_CH2 /* Tim1 counter enable */ TIM_Cmd(TIM15, ENABLE); /*----------------------------------------------------------------------- */ /* Compute the value to be set in ARR regiter to generate signal frequency at 4MHz */ TimerPeriod = (SystemCoreClock / 4000000 ); /* Compute CCR1 value to generate a duty cycle at 50% for channel 3 */ ChannelPulse = (uint16_t) (((uint32_t) 5 * TimerPeriod) / 10); /* Tim2 clock enable */ RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2 , ENABLE); /* Time Base configuration */ TIM_TimeBaseStructure.TIM_Prescaler = 0; TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; TIM_TimeBaseStructure.TIM_Period = TimerPeriod - 1; TIM_TimeBaseStructure.TIM_ClockDivision = 0; TIM_TimeBaseStructure.TIM_RepetitionCounter = 0; TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure); /* Channel Configuration in PWM mode */ TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM2; TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; TIM_OCInitStructure.TIM_Pulse = ChannelPulse; TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; TIM_OCInitStructure.TIM_OCIdleState = TIM_OCIdleState_Set; TIM_OC3Init(TIM2, &TIM_OCInitStructure); // TIM2_CH3 /* Tim2 counter enable */ TIM_Cmd(TIM2, ENABLE); } int main(void) { /*!< At this stage the microcontroller clock setting is already configured, this is done through SystemInit() function which is called from startup file (startup_stm32f30x.s) before to branch to application main. To reconfigure the default setting of SystemInit() function, refer to system_stm32f30x.c file */ /* TIM Configuration */ TIM_Config(); /* Infinite loop */ while (1); } #ifdef USE_FULL_ASSERT /** * @brief Reports the name of the source file and the source line number * where the assert_param error has occurred. * @param file: pointer to the source file name * @param line: assert_param error line source number * @retval None */ void assert_failed(uint8_t* file, uint32_t line) { /* User can add his own implementation to report the file name and line number, ex: printf(''Wrong parameters value: file %s on line %d\r\n'', file, line) */ /* Infinite loop */ while (1) { } } #endif Nothing on pin PA3 as can be see on attachement. One more pb. Somehow it seems that I break the communication with NUCLEO board. LED1 fixed orange! Keil debugger setting indicating a SW error: No cortex-M. SW device found. It is the second board that I put in the same state and I don't know how to come back!! Thanks for your help on that ''easy'' - I understand subject. ________________ Attachments : Screen_2014-11-21_04-54-36.jpeg : https://st--c.eu10.content.force.com/sfc/dist/version/download/?oid=00Db0000000YtG6&ids=0680X000006I0s2&d=%2Fa%2F0X0000000bi3%2Fz.WiPvwLpAoggFkPO_G7hf3DHBpk_XbwA1giO7CmMZM&asPdf=false2014-11-21 07:56 AM
Still Problem on generating PWM for Timer
I took now Tim15 ch2 (PA3) on PortA AF9 bus APB2. Code is as follow: #include ''stm32f30x.h'' static void TIM_Config(void) { GPIO_InitTypeDef GPIO_InitStructure; TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; TIM_OCInitTypeDef TIM_OCInitStructure; uint16_t TimerPeriod = 0; uint16_t ChannelPulse = 0; /* GPIOA & GPIOB Clocks enable */ RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA | RCC_AHBPeriph_GPIOB, ENABLE); /* GPIOA & GPIOB Configuration: Channel 3 (TIM2) and Channel 1 (TIM15) as alternate function push-pull */ 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_InitStructure.GPIO_Pin = GPIO_Pin_9; // TIM2_CH3 GPIO_Init(GPIOA, &GPIO_InitStructure); GPIO_PinAFConfig(GPIOA, GPIO_PinSource9, GPIO_AF_10); // TIM2 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3; // TIM15_CH2 GPIO_Init(GPIOA, &GPIO_InitStructure); GPIO_PinAFConfig(GPIOA, GPIO_PinSource14, GPIO_AF_9); // TIM15 /* Tim15 and Tim2 Configuration --------------------------------------------------- Generate 2 PWM signals : Tim15 input clock (Tim15CLK) is set to APB2 clock (PCLK2) Tim2 input clock (Tim2CLK) is set to APB1 clock (PCLK1) => Tim15CLK = PCLK2 = SystemCoreClock => Tim2CLK = PCLK1 = SystemCoreClock Tim15CLK = SystemCoreClock, Prescaler = 0, Tim15 counter clock = SystemCoreClock Tim2CLK = SystemCoreClock, Prescaler = 0, Tim2 counter clock = SystemCoreClock SystemCoreClock is set to 72 MHz for STM32F30x devices The objective is to generate 2 PWM signal at 1MHz for Tim15 and at 4MHz for Tim2: - Tim15_Period = (SystemCoreClock / 1000000) - 1 - Tim2_Period = (SystemCoreClock / 4000000) - 1 The channel 1 and channel 3 duty cycle are set to 50% The Timer pulse is calculated as follows: - Channel2Pulse = DutyCycle * (Tim15_Period + 1) / 100 - Channel3Pulse = DutyCycle * (Tim2_Period + 1) / 100 Note: SystemCoreClock variable holds HCLK frequency and is defined in system_stm32f30x.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); /* Compute CCR1 value to generate a duty cycle at 50% for channel 1 */ ChannelPulse = (uint16_t) (((uint32_t) 5 * TimerPeriod) / 10); /* Tim15 clock enable */ RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM15, ENABLE); /* Time Base configuration */ TIM_TimeBaseStructure.TIM_Prescaler = 0; TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; TIM_TimeBaseStructure.TIM_Period = TimerPeriod - 1; TIM_TimeBaseStructure.TIM_ClockDivision = 0; TIM_TimeBaseStructure.TIM_RepetitionCounter = 0; TIM_TimeBaseInit(TIM15, &TIM_TimeBaseStructure); /* Channel Configuration in PWM mode */ TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM2; TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; TIM_OCInitStructure.TIM_Pulse = ChannelPulse; TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; TIM_OCInitStructure.TIM_OCIdleState = TIM_OCIdleState_Set; TIM_OC2Init(TIM15, &TIM_OCInitStructure); // TIM15_CH2 /* Tim1 counter enable */ TIM_Cmd(TIM15, ENABLE); /*----------------------------------------------------------------------- */ /* Compute the value to be set in ARR regiter to generate signal frequency at 4MHz */ TimerPeriod = (SystemCoreClock / 4000000 ); /* Compute CCR1 value to generate a duty cycle at 50% for channel 3 */ ChannelPulse = (uint16_t) (((uint32_t) 5 * TimerPeriod) / 10); /* Tim2 clock enable */ RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2 , ENABLE); /* Time Base configuration */ TIM_TimeBaseStructure.TIM_Prescaler = 0; TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; TIM_TimeBaseStructure.TIM_Period = TimerPeriod - 1; TIM_TimeBaseStructure.TIM_ClockDivision = 0; TIM_TimeBaseStructure.TIM_RepetitionCounter = 0; TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure); /* Channel Configuration in PWM mode */ TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM2; TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; TIM_OCInitStructure.TIM_Pulse = ChannelPulse; TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; TIM_OCInitStructure.TIM_OCIdleState = TIM_OCIdleState_Set; TIM_OC3Init(TIM2, &TIM_OCInitStructure); // TIM2_CH3 /* Tim2 counter enable */ TIM_Cmd(TIM2, ENABLE); } int main(void) { /*!< At this stage the microcontroller clock setting is already configured, this is done through SystemInit() function which is called from startup file (startup_stm32f30x.s) before to branch to application main. To reconfigure the default setting of SystemInit() function, refer to system_stm32f30x.c file */ /* TIM Configuration */ TIM_Config(); /* Infinite loop */ while (1); } #ifdef USE_FULL_ASSERT /** * @brief Reports the name of the source file and the source line number * where the assert_param error has occurred. * @param file: pointer to the source file name * @param line: assert_param error line source number * @retval None */ void assert_failed(uint8_t* file, uint32_t line) { /* User can add his own implementation to report the file name and line number, ex: printf(''Wrong parameters value: file %s on line %d\r\n'', file, line) */ /* Infinite loop */ while (1) { } } #endif Nothing on pin PA3 as can be see on attachement. One more pb. Somehow it seems that I break the communication with NUCLEO board. LED1 fixed orange! Keil debugger setting indicating a SW error: No cortex-M. SW device found. It is the second board that I put in the same state and I don't know how to come back!! Thanks for your help on that ''easy'' - I understand subject. ________________ Attachments : Screen_2014-11-21_04-54-36.jpeg : https://st--c.eu10.content.force.com/sfc/dist/version/download/?oid=00Db0000000YtG6&ids=0680X000006I0yA&d=%2Fa%2F0X0000000bi4%2FE8ocxkJKo6Yc_pXy0ri6JcdGWY9dERXrH7ZrL9hx67Q&asPdf=false2014-11-21 07:59 AM
Error is obvious in my code:
GPIO_PinAFConfig(GPIOA, GPIO_PinSource14, GPIO_AF_9); // TIM15 Should be PinSource3 Now I need to debugg the NUCLEO board and come back to a communication protocol. Somebody know how I can?2014-11-21 09:10 AM
Hard PB solved by a hard reset.
Now still no PWM at Pin PA3. I don't understand! ________________ Attachments : Screen_2014-11-21_06-10-23.jpeg : https://st--c.eu10.content.force.com/sfc/dist/version/download/?oid=00Db0000000YtG6&ids=0680X000006I0t9&d=%2Fa%2F0X0000000bi2%2FpBNacSml_1zkwUeH_RzX8K4CNZdN7o3Nzxbb6YSOwu4&asPdf=false