cancel
Showing results for 
Search instead for 
Did you mean: 

STM32F100(RBT6): PWM generation with TIM1

awais
Associate
Posted on May 24, 2015 at 19:17

Hi Guys,

I am very new to the STM32 family and right now I am using a STM32F100 to be able to generate a PWM with TIM1. The end goal is to generate a PWM that can be filtered to show a sinewave so I need varying duty cycle. I am unable to even get the PWM running on a fixed duty cycle. Can anyone of you please comment what I might be doing wrong. Below is the current code I am using but I do not see anything on PA8 :(

/* Includes ------------------------------------------------------------------*/
#include ''stm32f10x.h''
#include <
stm32f10x_gpio.h
>
#include <
stm32f10x_rcc.h
>
#include <
stm32f10x_tim.h
>
/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_OCInitTypeDef TIM_OCInitStructure;
uint16_t CCR1_Val = 333;
uint16_t PrescalerValue = 0;
/* Private function prototypes -----------------------------------------------*/
static void TIM_Config(void);
static void PWM_Config(void);
void TIM1_UP_TIM16_IRQHandler(void)
{
if (TIM_GetITStatus(TIM1, TIM_IT_Update) != RESET){
TIM_ClearITPendingBit(TIM1, TIM_IT_Update);
}
}
int main(void)
{
/* Setup SysTick Timer for 1 msec interrupts */
//SysTick_Config(SystemCoreClock / 1000);
/* TIM Configuration */
TIM_Config();
PWM_Config();
while (1)
{}
}
static void TIM_Config(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
/* TIM1 clock enable */
RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1, ENABLE);
/* GPIOA clock enable */
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_AFIO, ENABLE);
/* GPIOA Configuration: TIM1 CH1: PA8 */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure); 
}
static void PWM_Config(void)
{
NVIC_InitTypeDef NVIC_InitStructure;
/* Compute the prescaler value */
PrescalerValue = (uint16_t) ((SystemCoreClock / 2) / 21000000) - 1;
/* Time base configuration */
TIM_TimeBaseStructure.TIM_Period = 665;
TIM_TimeBaseStructure.TIM_Prescaler = PrescalerValue;
TIM_TimeBaseStructure.TIM_ClockDivision = 0;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInit(TIM1, &TIM_TimeBaseStructure);
/* PWM1 Mode configuration: Channel1 */
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
TIM_OCInitStructure.TIM_Pulse = CCR1_Val;
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
TIM_OC1Init(TIM1, &TIM_OCInitStructure);
TIM_OC1PreloadConfig(TIM1, TIM_OCPreload_Enable);
/* Enable the TIM1 update interrupt */
NVIC_InitStructure.NVIC_IRQChannel = TIM1_UP_TIM16_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
TIM_ClearITPendingBit(TIM1, TIM_IT_Update);
TIM_ITConfig(TIM1, TIM_IT_Update, ENABLE);
/* TIM1 enable counter */
TIM_Cmd(TIM1, ENABLE);
}
#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) */
while (1){}
}
#endif

#stm32f100
2 REPLIES 2
Posted on May 24, 2015 at 20:47

TIM1/TIM8 are advanced timers, you need to more thoroughly initialize the timebase and output compare, and finally you need to enable the PWM outputs.

/* TIM1 Main Output Enable */ TIM_CtrlPWMOutputs(TIM1, ENABLE); A more complete example might look like this

// STM32F1xx TIM1_CH1 (PA8) PWM1 1Hz 50/50 Duty - sourcer32@gmail.com
#include ''stm32f10x.h''
int main(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_OCInitTypeDef TIM_OCInitStructure;
uint32_t Prescaler, Period;
/*!< 
At
this stage the microcontroller clock setting is already configured,
this is done through SystemInit() function which is called from startup
file (startup_stm32f10x_xx.s) before to branch to application main.
To reconfigure the default setting of SystemInit() function, refer to
system_stm32f10x.c file
*/
/* Enable GPIO clock */
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
/* Enable TIM clock */
RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1, ENABLE);
/* Configure TIM1_CH1 as alternate function push-pull */
GPIO_InitStructure.GPIO_Mode
= 
GPIO_Mode_AF_PP
;
GPIO_InitStructure.GPIO_Pin
= 
GPIO_Pin_8
;
GPIO_InitStructure.GPIO_Speed
= 
GPIO_Speed_2MHz
; // No point in overdriving
GPIO_Init(GPIOA, &GPIO_InitStructure);
/* Both these must ultimately fit in 16-bit, ie 1..65536 */
Prescaler = (SystemCoreClock / 20000); // System -> 20 KHz
Period = 20000; // 20 KHz -> 1 Hz
/* Extra caution required with TIM1/TIM8 full function timers, to initialize ALL fields */
/* Time base configuration */
TIM_TimeBaseStructure.TIM_Prescaler = (uint16_t)(Prescaler - 1);
TIM_TimeBaseStructure.TIM_Period = (uint16_t)(Period - 1);
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; // Where do those stairs go? They go up!
TIM_TimeBaseStructure.TIM_ClockDivision = 0; // Not used
TIM_TimeBaseStructure.TIM_RepetitionCounter = 0; // Not used
TIM_TimeBaseInit(TIM1, &TIM_TimeBaseStructure);
/* PWM1 Mode configuration: Channel1 */
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
TIM_OCInitStructure.TIM_Pulse = (uint16_t)(Period / 2); // 50%
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
TIM_OCInitStructure.TIM_OutputNState = TIM_OutputNState_Enable;
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_OC1Init(TIM1, &TIM_OCInitStructure);
/* TIM1 enable counter */
TIM_Cmd(TIM1, ENABLE);
/* TIM1 Main Output Enable */
TIM_CtrlPWMOutputs(TIM1, ENABLE);
/* 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

Tips, buy me a coffee, or three.. PayPal Venmo Up vote any posts that you find helpful, it shows what's working..
awais
Associate
Posted on May 25, 2015 at 06:06

clive1, thanks a lot. Going through the forum and looking at your activity I was expecting the first response from you when I posted. I'll test and let you know how it goes.

BTW, is there a good way of debugging under keil? When I start debug it goes to the systeminit and takes a lot of time here and there plus I am unable to make it run (f5) always have to do a step (f10).