https://mp.weixin.qq.com/s?__biz=Mzg4Mzc3NDUxOQ==&mid=2247484130&idx=1&sn=742e1776817dd6af6dcfac495a6f8f00&chksm=cf4307baf8348eac7fc5f527773f820d90ff77dd19c1aae5690b56baadfb3af5d55870d8ce12&token=1731405569&lang=zh_CN#rdhttps://mp.weixin.qq.com/s?__biz=Mzg4Mzc3NDUxOQ==&mid=2247484130&idx=1&sn=742e1776817dd6af6dcfac495a6f8f00&chksm=cf4307baf8348eac7fc5f527773f820d90ff77dd19c1aae5690b56baadfb3af5d55870d8ce12&token=1731405569&lang=zh_CN#rd
当按下开关时,舵机的角度分别运行到0°,45°,90°,135°,180°,0°(最后停止位置),其中每转动一个角度时间延时1s。
AT89C52,sg90舵机,三根杜邦线公对母,两支按键
由直流电机、减速齿轮组、传感器(可变电阻)和控制电路组成的一套自动控制系统。
直流电机是一圈圈转动的,舵机只能在一定角度内转动(有最大旋转角度比如:180度),不能一圈圈转。
外部中断:
STC89C52有4个外部中断;
STC89C52的外部中断有两种触发方式:
下降沿触发和低电平触发
下降沿触发:当按键按下不松手时只触发一次
低电平触发:当按键按下不松手时会持续触发
中断号:
由定时器和中断系统这张图来分析,可以得到定时器0的初始代码如下:
void Init_Timer0()
{
TMOD = 0x01;
TL0 = 0x33; //设置定时初值
TH0 = 0xFE; //设置定时初值
EA = 1;
ET0 = 1;
TR0 = 1;
PT0 = 1;
TF0=0;
}
PWM(Pulse Width Modulation)即脉冲宽度调制,在具有惯性的系统中,可以通过对一系列脉冲的宽度进行调制,来等效地获得所需要的模拟参量,常应用于电机控速、开关电源等领域
PWM重要参数:
频率 = 1 / TS 占空比 = TON / TS 精度 = 占空比变化步距
例子:在制作LED呼吸灯时,如果想要让LED亮的时间更长,只需要提高比较值。
舵机的输入线共有三条:
红色线——电源正线(需接5V电源才能驱动)
棕色线——电源地线
黄色线——信号线(本项目使用P2^7端口)
本文采用的是定时器0来计时,初始值设为0.5ms,每次定时器溢出是0.5ms,设置一个计数值count=0,每一个0.5ms count都会自增1,加了40次就20ms,是舵机控制的一个周期。
所以0.5ms是自增一次,1ms是自增两次,1.5ms是自增三次,2ms是自增四次,2.5ms是自增五次。
无按键自转代码:
#include
sbit Sg90_com = P2^7;
unsigned char compare=0,count=0; //compare比较值控制占空比大小,控制舵机转动的角度
void Delay1ms(unsigned int num) //@11.0592MHz
{
unsigned char i, j;
while(num--)
{
i = 2;
j = 199;
do
{
while (--j);
} while (--i);
}
}
void Init_Timer0()
{
TMOD = 0x01;
TL0 = 0x33; //设置定时初值
TH0 = 0xFE; //设置定时初值
EA = 1;
ET0 = 1;
TR0 = 1;
PT0 = 1;
TF0=0;
}
void main()
{
Init_Timer0();
while(1)
{
compare = 1; //0度
Delay1ms(1000);
compare = 2; //45度
Delay1ms(1000);
compare = 3; //90度
Delay1ms(1000);
compare = 4; //135度
Delay1ms(1000);
compare = 5; //180度
Delay1ms(1000);
}
}
void Timer0_Rountine() interrupt 1 //每次定时器溢出时是0.5ms
{
TL0 = 0x33; //设置定时初值
TH0 = 0xFE; //设置定时初值
count++;
//PWM控制
if(count < 40) //每一个0.5mscount都会++,加了40次就20ms,是舵机控制的一个周期
{
if(count < compare) //通过比较值控制高电平占据周期的时间,也就是占空比大小
{
Sg90_com = 1;
}
else
{
Sg90_com = 0;
}
}
else //count加到40后清零
{
count = 0;
Sg90_com = 1;
}
}
按键自转代码:
#include
sbit Sg90_com = P2^7;
sbit key1 = P3^1; //独立按键1
sbit key2 = P3^0; //独立按键2
unsigned char compare=0,count=0; //compare比较值控制占空比大小,控制舵机转动的角度
void Delay1ms(unsigned int num) //@11.0592MHz
{
unsigned char i, j;
while(num--)
{
i = 2;
j = 199;
do
{
while (--j);
} while (--i);
}
}
void Init_Timer0()
{
TMOD = 0x01;
TL0 = 0x33; //设置定时初值
TH0 = 0xFE; //设置定时初值
EA = 1;
ET0 = 1;
TR0 = 1;
PT0 = 1;
TF0=0;
}
void main()
{
Init_Timer0();
while(1)
{
while(key1==0){
compare = 1; //0度
Delay1ms(1000);
}
while(key2==0){
compare = 5; //180度
Delay1ms(1000);
}
}
}
void Timer0_Rountine() interrupt 1 //每次定时器溢出时是0.5ms
{
TL0 = 0x33; //设置定时初值
TH0 = 0xFE; //设置定时初值
count++;
//PWM控制
if(count < 40) //每一个0.5mscount都会++,加了40次就20ms,是舵机控制的一个周期
{
if(count < compare) //通过比较值控制高电平占据周期的时间,也就是占空比大小
{
Sg90_com = 1;
}
else
{
Sg90_com = 0;
}
}
else //count加到40后清零
{
count = 0;
Sg90_com = 1;
}
}
Q1:代码超出版本限制如何解决?如图:
A1:用注册机对KEIL5软件进行重新破解,破解步骤链接:
Q2:延时函数如何快速自动生成?
A2:在STC-ISP中根据红色方框进行设计
Q3:单片机计时器TH0 和TL0初值的计算方法
A3:首先计算计数值:
例如:计数值=10000us(10ms转换成微秒)* 11.0592(晶振大小)/12 计算结果=9216
TH0=(65536-9216)/256 =DC
TL0=(65536-9216)%256 =00
//8位逢256进位,整除的结果为高位,取余的结果为低位
Q4:单片机计时器TMOD设置
A4:通常情况下,定时器0的TMOD=0x01,工作模式1——16位计时计数器 (65536)
下面两张图是工作模式1和2的对比流程图: