一.PWM介绍
1.PWM概念
英文名Pulse Width Modulation,是脉冲宽度调制缩写,它是通过对一系列脉冲的宽度进
行调制,等效出所需要的波形(包含形状以及幅值),对模拟信号电平进行数字编码,也就是说通
过调节占空比的变化来调节信号、能量等的变化,占空比就是指在一个周期内,信号处于高电平的
时间占据整个信号周期的百分比,例如方波的占空比就是50%.
2.要点概括
1.2.1:他可以调节脉冲的宽度
1.2.2:通过占空比模拟编码信号
1.2.3:占空比:在一个周期内,高电平占全部周期的百分比
二、实现PWM的方法
1.芯片模块块内部自带的PWM输出,一般可以通过软件手册查询是否支持
2.芯片模块没有自带:可以通过指定的IO端口模拟PWM信号,但是精度相较于芯片自带的比较差
三.如何控制舵机
1.对于舵机而言,一般有三根线,其中两条是电源线,另外一条是PWM信号线,通过给PWM信号线输入信号,使得舵机旋转相应的角度,进而控制舵机
2.其中PWM的频率不能太高,通常情况下,一般为50Hz,也就是0.02s,就是20ms为一个周期
高电平时间 | 舵机旋转的角度 | 函数对应的占空比 |
0.5ms | 0度 | 2.5%占空比250 |
1.0ms | 45度 | 5.0%占空比500 |
1.5ms | 90度 | 7.5%占空比750 |
2.0ms | 135度 | 10.0%占空比1000 |
2.5ms | 180度 | 12.5%占空比1250 |
不同的舵机有可能旋转角度不同,具体的根据舵机手册查询
四.编程实现
1.编程思路:
通过上面的表格可以发现,高电平都是基于0.5ms的,也就是说所有的都是以0.5ms为基础来进行,我们可以通过设定一个0.5ms也就是500微秒的定时器,通过统计定时器的爆表次数来控制PWM信号,比如想让电机旋转90度,那么高电平就是1.5ms,通过定时器爆表3次(1.5ms是0.5ms的3倍),如果定时器爆表次数小于3,则将定义的PWM管脚输出高电平,其余输出低电平,这样就输出一个可以使电机旋转90度的PWM信号。当爆表次数到达40次之后,将计数归零,重新开始计数。
2.程序代码
#include <regx52.h>
#include <intrins.h>
sbit SG90_PWM = P1^0;
int ctu;
int angle;
void Delay300ms() //@11.0592MHz
{
unsigned char i, j, k;
_nop_();
i = 3;
j = 26;
k = 223;
do
{
do
{
while (--k);
} while (--j);
} while (--i);
}
void Delay2000ms() //@11.0592MHz
{
unsigned char i, j, k;
_nop_();
i = 15;
j = 2;
k = 235;
do
{
do
{
while (--k);
} while (--j);
} while (--i);
}
/*定时器初始化函数*/
void Timer0Init(void)
{
AUXR &= 0x7F;
TMOD &= 0xF0;
TMOD |= 0x01;
TL0 = 0x33;
TH0 = 0xFE;
TF0 = 0;
TR0 = 1;
EA = 1;
}
/*主函数调用部分*/
void main()
{
Delay300ms();
Timer0Init(void);
while(1)
{
angle = 3;
ctu = 0;
Delay2000ms();
angle = 1;
ctu = 0;
Delay2000ms();
}
}
void Time0Handler() interrupt 1
{
ctu++; //每次经过0.5ms,计数值就自动加一
TL0=0x33;
TH0=0xFE;
if( ctu< angle)
{
sg90_PWM = 1;
}
else
{
sg90_PWM = 0;
}
if(ctu == 40)
{
ctu = 0;
sg90_PWM = 1;
}
}
3.可能产生的疑问
(1)定义“angle”的意义:定义angle是为了更方便的控制电机旋转的角度,电机控制的角度不在是一个固定值
(2)angle = 3;
ctu = 0;
Delay2000ms();
angle = 1;
ctu = 0;
Delay2000ms();
以上代码的含义是:给出确定的角度,当电机每次发生一次跳变时,便会将计数值归零一次,防止产生误差