第四节:STM32定时器(2.输出PWM波控制电机转速)

 关联:STM32总结超全笔记【秋招自用】

 四.STM32定时器(重中之重中之重)

【前言】

我觉得在冗长的理论之前,我们首先要对定时器的输出比较功能做一个理解。

【问】输出比较用来做什么?应用场景是什么??

输出比较,就是可以控制定时器,去比较 CNT 和 CCR 寄存器值的关系,来对输出的电平进⾏置1、置0或翻转的操作,⽤于输出⼀定频率和占空比的 PWM 波形。

【问】什么是PWM波?

PWM全称为脉冲宽度调制。

PWM波输出原理:

当 CNT<CCRx 时, IO 输出低电平(逻辑 0 );
当 CNT>=CCRx 时, IO 输出高电平(逻辑 1 );
当 CNT=ARR 时,定时器溢出, CNT 的值被清零,然后继续递增,依次循环;

占空比:高电平所占时间 / 周期时间
占空比 = CCR / (ARR + 1)

频率 =  CK_PSC / (PSC + 1) / (ARR + 1)

【PWM的应用场景】

【问】我们已经知道了输出比较,就是通过cnt和arr的比较,输出高低电平,输出PWM波,那么PWM波有什么用???

1.PWM输出呼吸灯

之前学完了最简单的基本定时器,我们来学习通用定时器。

首先人眼对80Hz以上的刷新频率是感受不到闪烁的。

我们来分析一下比如说:

  • 频率100Hz的场景:10毫秒内,5毫秒打开,5毫秒关闭,(占空比50%)此时常量。
  • 频率1Hz的场景:1秒内,0.5秒打开,0.5秒关闭,此时很明显的闪烁。
  • 频率100Hz的场景:10毫秒内,9毫秒打开,1毫秒关闭,(占空比90%)此时亮度比第一个例子亮。

所以:频率相同,占空比越大,灯越亮。

改变占空比,即可改变灯的亮度,实现呼吸灯。

2.PWM控制电机转速

直流电机中,电机转速是周期内输出的平均电压值,那么占空比越大,输出电压越大,速度越大。

改变占空比,即可改变电机转速。

3.PWM控制舵机

舵机频率一般为50Hz,相当于20毫秒的脉冲,脉冲的高电平部分范围是0.5ms到2.5ms之间。如果是180度的舵机,那么:

0.5ms对应0度

1ms对应45度

以此类推,2.5ms对应180度

---------------------------------------------------------------------------------------------------------------------------------

有了这些知识铺垫后,我们开始定时器输出比较的学习。

之前学完了最简单的基本定时器,我们来学习通用定时器。

【通用定时器】

 我们着重看一下输出比较这部分框图:

【输出比较】

说白了就是先初始化定时器模块和输出比较模块,然后通过控制CCR的值,改变灯的亮度或者是电机的速度。

那么例程就写一个控制直流电机转速,为后面的STM32小车做铺垫。

【例程6】输出PWM波控制电机转速

首先看一下硬件连接:

因为直流电机属于大功率器件,单片机引脚输出电压太小无法直接驱动,所以需要一个电机驱动模块,这里用TB6612。

【PWM初始化】

void PWM_Init(void)
{
	/*开启时钟*/
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);			//开启TIM2的时钟
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);			//开启GPIOA的时钟
	
	/*GPIO初始化*/
	GPIO_InitTypeDef GPIO_InitStructure;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOA, &GPIO_InitStructure);							//将PA2引脚初始化为复用推挽输出	
																	//受外设控制的引脚,均需要配置为复用模式
	
	/*时基单元初始化*/
	TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;				//定义结构体变量
	TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1;     //时钟分频,选择不分频,此参数用于配置滤波器时钟,不影响时基单元功能
	TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up; //计数器模式,选择向上计数
	TIM_TimeBaseInitStructure.TIM_Period = 100 - 1;                 //计数周期,即ARR的值
	TIM_TimeBaseInitStructure.TIM_Prescaler = 36 - 1;               //预分频器,即PSC的值
	TIM_TimeBaseInitStructure.TIM_RepetitionCounter = 0;            //重复计数器,高级定时器才会用到
	TIM_TimeBaseInit(TIM2, &TIM_TimeBaseInitStructure);             //将结构体变量交给TIM_TimeBaseInit,配置TIM2的时基单元
	
	/*输出比较初始化*/ 
	TIM_OCInitTypeDef TIM_OCInitStructure;							//定义结构体变量                                                                                           
	TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;               //输出比较模式,选择PWM模式1
	TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;       //输出极性,选择为高,若选择极性为低,则输出高低电平取反
	TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;   //输出使能
	TIM_OCInitStructure.TIM_Pulse = 0;								//初始的CCR值
	TIM_OC3Init(TIM2, &TIM_OCInitStructure);                        //将结构体变量交给TIM_OC3Init,配置TIM2的输出比较通道3
	
	/*TIM使能*/
	TIM_Cmd(TIM2, ENABLE);			//使能TIM2,定时器开始运行
}

【问】为什么PA2被设置为了复用推挽输出?

因为PA2接的是PWMA,由内部外设控制的时候,需要设置为复用推挽输出。

后面都是比较基础的设置了。

【电机驱动模块的GPIO初始化】

void Motor_Init(void)
{
	/*开启时钟*/
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);		//开启GPIOA的时钟
	
	GPIO_InitTypeDef GPIO_InitStructure;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4 | GPIO_Pin_5;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOA, &GPIO_InitStructure);						
	
	PWM_Init();													//初始化直流电机的底层PWM
}

【设置电机速度的函数】

void PWM_SetCompare3(uint16_t Compare)
{
	TIM_SetCompare3(TIM2, Compare);		//设置CCR3的值
}

这里是对TIM_SetCompare3做一个封装。

void Motor_SetSpeed(int8_t Speed)
{
	if (Speed >= 0)							//如果设置正转的速度值
	{
		GPIO_SetBits(GPIOA, GPIO_Pin_4);	//PA4置高电平
		GPIO_ResetBits(GPIOA, GPIO_Pin_5);	//PA5置低电平,设置方向为正转
		PWM_SetCompare3(Speed);				//PWM设置为速度值
	}
	else									//否则,即设置反转的速度值
	{
		GPIO_ResetBits(GPIOA, GPIO_Pin_4);	//PA4置低电平
		GPIO_SetBits(GPIOA, GPIO_Pin_5);	//PA5置高电平,设置方向为反转
		PWM_SetCompare3(-Speed);			//PWM设置为负的速度值,因为此时速度值为负数,而PWM只能给正数
	}
}

此函数就是根据TB6612的数据手册编写的(所以查Datasheet非常重要)

 此时在主函数中利用封装好的Motor_SetSpeed函数即可控制电机速度了。

  • 27
    点赞
  • 37
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值