拓展模块使用教程和心得(四):PWM脉冲宽度调制及普通有刷马达和空心杯电机(测试平台:STC8A8K,STM32F103)

成就更好的自己

这次内容是给未来的新专栏(控制算法)打一个小基础,而且是为了完善上一期拓展模块教程三:步进电机的内容(https://blog.csdn.net/qq_36098477/article/details/107293881),把常用的博主目前手里有的电机,再进一步总结一下。

 

目录

PWM脉冲宽度调制

STC8A8K的PWM实现

STM32F103的PWM实现

普通有刷小马达与空心杯电机

一种电机驱动的典型电路


 

PWM脉冲宽度调制

对于PWM最浅显的理解就是让单片机输出一个占空比可调的方波最常用的方面就是D/A转换和电机控制。具体原理给大家举个例子,8051单片机(STC8A8K等)在5V供电下,IO口置一后的电压是将近5V,如何产生用IO口产生0~5V的任意电压值呢,以2.5V为目标的话,可以输出幅值为5V的,占空比为50%方波,这样的话有效值就是2.5V。我们也可以通过PWM控制IO电平高低的时间,来控制外围附属电路通断时间。目前大多数单片机均支持PWM的硬件(STC公司的单片机有专门的硬件PWM,STM32系列需要设置定时器为PWM模式)。

下面我就以STC8A8K和STM32F103作为测试和介绍平台,讲解一下关于硬件和模拟PWM的过程。

STC8A8K的PWM实现

STC8A8K代表了市场上普遍的8051架构系列的硬件PWM方式;STC8A8K只有一组(8路)PWM通道,工作方式为:需要定时器为这一组PWM提供计数(8路共用一个定时器),但是可以为每一路(共8路)设置自己的电平翻转的两个计数值,通过比较定时器产生的计数是否达到每一路的两个计数值,从而控制每一路的PWM波形发生,此外,还可以设置每一路的初始电平状态,用户也可以将任意两路结合起来实现互补对称输出或死区控制等应用方式。总的来说,这8路PWM通道既同根同祖,又相互独立。

简单来说,硬件PWM的设置需要以下两大部分:

总PWM组设置:

PWM不与ADC关联;

PWM15位计数器溢出中断清零;

允许PWM访问拓展RAM区的SFR;

选择给PWM提供计数时基的定时器;

PWM计数器赋值;

给定时器赋定时值;

PWM组过程中的中断设置;

 

PWM通道设置:

选择这个PWM通道的输出引脚;

设置上面的引脚受PWM波形发生器控制;

设置这个端口初始电平;

PWM通道中断设置;

设置高低翻转电平对应的计数值;

在这个过程中,PWM自带的计数器值决定一次PWM的周期,电平翻转的两个计数值决定在这一个周期中电平反转的时间从而决定占空比。

void PWM0_Configuration(void)
{
	PWMCFG &= 0xBF;		         //将ETADC位置0,即PWM与ADC不关联
	PWMCFG &= 0x7F;		         //将CBIF位置0,PWM计数器归零中断标志位,需软件清零
	
	P_SW2 |= 0x80;		         //将EAXSFR位置1,以访问PWM在扩展RAM区的特殊功能寄存器
	//对PWM0的初始化部分
	PWM0CR &= 0xEF;	           //将C0_S[1:0]位置0 1,选择PWM0的输出引脚是P1.0
	PWM0CR |= 0x08;	           //将C0_S[1:0]位置0 1,选择PWM0的输出引脚是P1.0
	PWM0CR |= 0x80;			       //将ENC0O位置1,PWM0的端口为PWM输出口,受PWM波形发生器控制	
	PWM0CR &= 0xBF;		         //将C0INI位置0,设置PWM0输出端口的初始电平为低电平
	PWMIF &= 0xFE;		         //将C0IF位置0,PWM0中断标志位,需软件清零
	PWM0CR |= 0x04;	           //将EC0I位置1,使能PWM0中断
	PWM0CR &= 0xFD;	           //将EC0T2SI位置0,关闭T2翻转时中断
	PWM0CR &= 0xFE;	           //将EC0T1SI位置0,关闭T1翻转时中断
	//对PWM0翻转计数器赋初值
	PWM0T1 =1;                 //赋值PWM0第一次翻转计数器值
	PWM0T2 = 0x00FA;           //赋值PWM0第二次翻转计数器值
	
  //对PWM波形发生器时钟源进行初始化
	PWMCKS |= 0x10;		         //将SELT2位置1,PWM时钟源为定时器2溢出脉冲
	PWMC = 0x00FA;             //PWM计数器赋值(同时对PWMCH和PWMCL进行了赋值)
	AUXR |= 0x04;		           //定时器2时钟为Fosc,即1T
	T2L = 0xE0;		             //设定定时初值
	T2H = 0xFE;                //设定定时初值
	AUXR |= 0x10;              //启动定时器2
	P_SW2 &= 0x7F;		         //将EAXSFR位置0,恢复访问XRAM
	
	//PWM外部异常控制寄存器的操作
	PWMFDCR &= 0xDF;		       //将ENFD位置0,关闭PWM外部异常检测功能
	PWMFDCR &= 0xF7;		       //将ENDI位置0,关闭PWM异常检测中断
	PWMFDCR &= 0xFB;		       //将FDCMP位置0,比较器与PWM无关
	PWMFDCR &= 0xFD;		       //将FDIO位置0,P3.5的状态与PWM无关
	PWMFDCR &= 0xFE;		       //将FDIF位置0,PWM异常检测中断标志位,需软件清零
	
	IP2 |= 0x40;		           //将PPWM位置1,使能PWM中断为最高优先级中断
	//使能PWM波形发生器
	PWMCR |= 0x80;		         //将ENPWM位置1,使能PWM波形发生器,PWM计数器开始计数
	PWMCR &= 0xBF;		         //将ECBI位置0,禁止PWM计数器归零中断
}

至于模拟PWM就很简单了,可以直接用计数器产生中断然后通过代码翻转引脚电平即可:

void Timer0Init()	
{
	AUXR |= 0x80;//定时器配置,定时时间1MS,到时间后占空比加一,以实现占空比的调节
	TMOD &= 0xF0;	
	TL0 = 0x40;		
	TH0 = 0xA2;		
	TF0 = 0;		
	TR0 = 1;
	ET0 = 1;
	EA = 1;	
}
void main()
{
	Timer0Init();
	while(1)
	{
		if(num<DR)//循环加一的num与DR比较,判断计数值是否翻转电平
		moter=1;
		else
		moter=0;

		num++;	//计数值加一

		if(num==10001)
		num=0;
	}
}
void TM0_Rountine() interrupt 1
{
	DR++;		 //通过定时中断调节占空比
	if(DR==10001)				   
	DR=0;
}

STM32F103的PWM实现

STM32系列以最基础的F103为代表,STM32的PWM原理几乎与STC系列的8051架构单片机一模一样,只不过是实现方式和调用的硬件不同;STM32的PWM功能只是内部几个定时器的附属功能之一,没有专门的PWM硬件,我们在此不多介绍STM32的定时器(种类繁多,功能繁多,结构复杂),只介绍如何硬件实现;在STM32的定时/计数器硬件电路介绍中有一个寄存器叫捕获/比较寄存器,定时器会根据目前的计数值与比较计数器比较,若计数值小于某通道(STM32一个定时器有四个通道)的比较寄存器值,则对应通道的输出引脚保持高电平,反之则保持为低电平,;当计数器溢出,则装入重装值,对应引脚再恢复高电平。

简单来说,硬件PWM的设置需要以下几小部分:

PWM输出引脚的初始化;

使能要用的计数器的时钟;

选择计数模式(向上就是加计数,向下就是减计数);

设置计数器重装值;

设置时钟分频系数;

配置通道为比较通道;

使能输出比较状态(比较的结果可以产生中断或选择输出到引脚上)

给比较寄存器赋值;

设置比较达到条件后引脚电平的状态;

使能这个通道;

使能预装载寄存器;

这个过程中,计数器的重装值决定一次PWM的周期,比较寄存器的值决定电平翻转的时间从而决定占空比。

void TIM3_PWM_Init(void)
{
	TIM_TimeBaseInitTypeDef			TIM_TimeBaseInitStruct;
	TIM_OCInitTypeDef  TIM_OCInitStructure;

	RCC_APB1PeriphClockCmd( RCC_APB1Periph_TIM3 , ENABLE);          //打开外设TIM3时钟 
	
	TIM_DeInit(TIM3);                                               //将外设TIM3寄存器重设为缺省值  
  
  	//TIM2是通用定时器,需配置TIM_ClockDivision、TIM_CounterMode、TIM_Period和TIM_Prescaler,无需配置TIM_RepetitionCounter
	TIM_TimeBaseInitStruct.TIM_ClockDivision = TIM_CKD_DIV1 ;       //设置了时钟分割(Tck_tim) 
	TIM_TimeBaseInitStruct.TIM_CounterMode = TIM_CounterMode_Up ;   //选择了计数器模式(TIM向上计数模式)  
	TIM_TimeBaseInitStruct.TIM_Period = 999 ;          //设定计数器自动重装值,取值范围0x0000~0xFFFF   
	TIM_TimeBaseInitStruct.TIM_Prescaler = 7199 ;      //设置用来作为TIM3时钟频率除数的预分频值为(7199+1),取值范围0x0000~0xFFFF 
	TIM_TimeBaseInit(TIM3, &TIM_TimeBaseInitStruct ) ;       
	TIM_Cmd(TIM3, ENABLE);                             //使能TIM3外设  
	
  	TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;	              //配置为PWM模式1
  	TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;  	//选择使能输出比较状态
 	 TIM_OCInitStructure.TIM_Pulse = 500;	     //设置待装入捕获比较寄存器的脉冲值,取值范围0x0000~0xFFFF 
  	TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;       //设置定时器输出比较极性高电平
  	TIM_OC1Init(TIM3, &TIM_OCInitStructure);	                      //使能TIM3通道1
  	TIM_OC1PreloadConfig(TIM3, TIM_OCPreload_Enable);               //使能TIM3在CCR1上的预装载寄存器

	TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;	               //配置为PWM模式1
 	TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;  	 //选择使能输出比较状态
  	TIM_OCInitStructure.TIM_Pulse = 250;	      //设置通道2的电平跳变值,输出另外一个占空比的PWM
	TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;  //当定时器计数值小于250时为高电平
 	TIM_OC2Init(TIM3, &TIM_OCInitStructure);	  //使能TIM3通道2
 	TIM_OC2PreloadConfig(TIM3, TIM_OCPreload_Enable);                //使能TIM3在CCR2上的预装载寄存器
}

模拟PWM就很简单了,这里跟上面8051的原理几乎一致,而且在STM32里资源丰富一般是用不到模拟的,这里就不给代码了。

 

 

普通有刷小马达与空心杯电机

先上实物图:

第一张图是最常见的小马达了,在各种玩具中都有见,特点是转速低,扭矩一般,耗电量大,振动幅度大,总之没有一点优点,而且外界负载会很大程度影响运行稳定性和运行电流;好一点的也有这种以线圈为转子,永磁体为定子的有刷驱动方式的其他类型的电机,那种适合于做动量轮和动力电机。

第二张图是空心杯电机,博主手里的型号是720,特点是转速快,扭矩小,耗电量低,转动稳定,一般用作航模螺旋桨电机等不需要太大负载但对转速有要求的场景。下图是博主在四旋翼飞行器上的应用。

 

一种电机驱动的典型电路

这种电路可以作为集基础控制,功耗波动,稳定为一体的理想电路,中间的CMOS管SI2302是博主经过选型和实践后确定,是可以是直接照搬的,多用于在低电压情况下(3.3V~12V)控制上文中那两个类型的电机

控制方面,可以通过PWM控制右端从VCC到GND整体的导通状态,从而控制电机的转动速度,对于电机工作电流有要求的朋友可以将SI2302替换成SI2300,2300内阻比较小,可以容纳大一点的电流。

那个4.7uF的电容也可以不加,也可以替换成合适的稳压二极管,但是测试后觉得电容好像更稳定一些。

单单靠这种电路和上文的两种电机是不能做成闭环控制的,需要有转速传感器或加速度传感器作为反馈才行。此外,这种电路只能实现相对的控制,不能实现精度极高的控制,那样的话需要更为严谨的控制方式和电路,就不能仅仅只靠PWM了。

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值