提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
提示:这里可以添加本文要记录的大概内容:
上次学习了STM32的基本定时器功能,它只是最基本的功能,STM32的功能非常强大,定时器还有输出功能,即PWM。
提示:以下是本篇文章正文内容,下面案例可供参考
PWM是脉冲宽度调制,简称脉宽调制,是利用微处理器的数字输出来对模拟电路进行控制的一种非常有效的技术,广泛应用在从测量、通信到功率控制与变换的许多领域中。
T1:为高电平时间
T2:为低电平时间
T1+T2-=T
占空比为 = T/T *100%
void timer1_gpio_init()
{
GPIO_InitTypeDef GPIO_InitStruct;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
GPIO_InitStruct.GPIO_Pin= GPIO_Pin_8; //TX
GPIO_InitStruct.GPIO_Speed= GPIO_Speed_50MHz;
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_Init(GPIOA, &GPIO_InitStruct); //&x
}
void timer1(u16 period,u16 prescaler)
{
/*
1.开启APB1时钟 72MHz
2.配置定时器6 TimeInit() 72预分配,0-65535 1000000us/50000us =CNT=20 定时时间/中断溢出时间=计数值
3.中断配置 分组,优先级 。开启中断源
4.中断服务函数 计数值, 1us ,计数20次后让一个LED取反
*/
TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStruct;
TIM_OCInitTypeDef TIM_OCInitStruct;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1, ENABLE);
//TIM_TimeBaseInitStruct.TIM_ClockDivision=
TIM_TimeBaseInitStruct.TIM_CounterMode=TIM_CounterMode_Up;
TIM_TimeBaseInitStruct.TIM_Period=period-1;//50000-1;
TIM_TimeBaseInitStruct.TIM_Prescaler=prescaler-1;// 72-1;
//TIM_TimeBaseInitStruct.TIM_RepetitionCounter=
TIM_TimeBaseInit(TIM1, &TIM_TimeBaseInitStruct);
//TIM_OCInitStruct.TIM_OCIdleState=
// TIM_OCInitStruct.TIM_OCNIdleState=
TIM_OCInitStruct.TIM_OCMode= TIM_OCMode_PWM1;
TIM_OCInitStruct.TIM_OCPolarity= TIM_OCPolarity_High;
// TIM_OCInitStruct.TIM_OCNPolarity=
// TIM_OCInitStruct.TIM_OutputNState=
TIM_OCInitStruct.TIM_OutputState= TIM_OutputState_Enable;
TIM_OCInitStruct.TIM_Pulse= period/2; //百分之50占空比
TIM_OC1Init(TIM1, &TIM_OCInitStruct);
TIM_CtrlPWMOutputs(TIM1, ENABLE);
//开启中断:
TIM_ITConfig( TIM1, TIM_IT_CC1, ENABLE);
TIM_Cmd( TIM1, ENABLE); //使能
}
TIM_ITConfig( TIM1, TIM_IT_CC1, ENABLE);
TIM_CtrlPWMOutputs(TIM1, ENABLE);
void timer1_gpio_init()
{
GPIO_InitTypeDef GPIO_InitStruct;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
GPIO_InitStruct.GPIO_Pin= GPIO_Pin_8; //TX
GPIO_InitStruct.GPIO_Speed= GPIO_Speed_50MHz;
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_Init(GPIOA, &GPIO_InitStruct); //&x
}
void timer1(u16 period,u16 prescaler)
{
/*
1.开启APB1时钟 72MHz
2.配置定时器6 TimeInit() 72预分配,0-65535 1000000us/50000us =CNT=20 定时时间/中断溢出时间=计数值
3.中断配置 分组,优先级 。开启中断源
4.中断服务函数 计数值, 1us ,计数20次后让一个LED取反
*/
TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStruct;
TIM_OCInitTypeDef TIM_OCInitStruct;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1, ENABLE);
//TIM_TimeBaseInitStruct.TIM_ClockDivision=
TIM_TimeBaseInitStruct.TIM_CounterMode=TIM_CounterMode_Up;
TIM_TimeBaseInitStruct.TIM_Period=period-1;//50000-1;
TIM_TimeBaseInitStruct.TIM_Prescaler=prescaler-1;// 72-1;
//TIM_TimeBaseInitStruct.TIM_RepetitionCounter=
TIM_TimeBaseInit(TIM1, &TIM_TimeBaseInitStruct);
//TIM_OCInitStruct.TIM_OCIdleState=
// TIM_OCInitStruct.TIM_OCNIdleState=
TIM_OCInitStruct.TIM_OCMode= TIM_OCMode_PWM1;
TIM_OCInitStruct.TIM_OCPolarity= TIM_OCPolarity_High;
// TIM_OCInitStruct.TIM_OCNPolarity=
// TIM_OCInitStruct.TIM_OutputNState=
TIM_OCInitStruct.TIM_OutputState= TIM_OutputState_Enable;
TIM_OCInitStruct.TIM_Pulse= period/2; //百分之50占空比
TIM_OC1Init(TIM1, &TIM_OCInitStruct);
TIM_CtrlPWMOutputs(TIM1, ENABLE);
//开启中断:
TIM_ITConfig( TIM1, TIM_IT_CC1, ENABLE);
TIM_Cmd( TIM1, ENABLE); //使能
}
周期->是由时基来决定的。
时基->是由预分频和周期决定的
RCC时钟也是关键,最高设置为了72MHz
公式 1:72000000=分频系数*周期数
分频系数的范围是 0-65535
周期数的范围是:0-65535。
所以公式1 将得到很多种可能,这正是STM32预分频的神奇之处
之前定时1s实现,
72000000 =72*(5000020)
20是在定时器中断里面放变量自加的。现在配置PWM没有这个内容,根据大小值都不能超过65535的原则,将20分给预分频
timer1(50000,7220);
方法1:写一个函数 关联公式1
通过看图,占空比就是改变比较值,所以改变比较值就可以了
TIM_SetCompare1(TIM1, i++);