PWM控制SG90舵机
PWM可以对一系列脉冲的宽度进行调制,等效出所需要的波形
占空比为一个周期内,高电平占据时长的百分比。上图中一个周期为4ms,而高电平占据1ms因此占空比为25%
如何实现PWM信号输出
1.对于自带PWM口的芯片来说,可以直接通过芯片内部模块输出
2.如果没有集成PWM功能,可以通过IO口软件模拟相对硬件PWM来说精准度略低。即用软件代码结合定时器来实现波形的变换,来模拟PWM信号。
如何控制舵机
定时器需要定时20ms,最小使用单位为0.5ms,因此将初值设置为0.5ms,利用cnt记录爆表次数
编程实现
根据波形图调整角度变量jd即可
#include "reg52.h"
#include <intrins.h>
sbit sg90_con = P1^1;
int jd;
int cnt = 0;//用来记录爆表的次数
void Time0Init()
{
//1.配置定时器0工作模式为16位计时
//TMOD = 0x01;
TMOD &= 0xF0; //将低四位清零,且不改变高四位的值
TMOD |= 0x01; //将低四位修改,且不改变高四位的值
//2.给初值,定一个0.5ms出来
TL0 = 0x33;
TH0 = 0xFE;
//3.开始计时
TR0 = 1;
TF0 = 0;
//4.打开定时器0中断
ET0 = 1;
//5.打开总中断EA
EA = 1;
}
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 main()
{
Delay300ms();//让硬件稳定一下
Time0Init();//初始化定时器
jd = 1;//初始化角度,0.5ms高电平
cnt = 0;
sg90_con = 1;//一开始从高电平开始
//4.爆表了,操作led吗,累计到1s再操作led,每次爆表变量+1,变量到100再操作led
while(1){
jd = 1;//0°根据波形图来看
cnt = 0;
Delay2000ms();
jd = 4;//135°
cnt = 0;
Delay2000ms();
}
}
void Time0Handler() interrupt 1 //爆表了就进入该中断服务程序
{
cnt++;
//重新给初值
TL0 = 0x33;
TH0 = 0xFE;
if(cnt < jd){
//cnt=1的时候爆表1次,经过0.5ms
sg90_con = 1;
}else{
sg90_con = 0;
}
sg90_con = 1;
if(cnt == 40){
//爆表了40次经过了20ms
cnt = 0;
sg90_con = 1;
}
}
超声波测距模块
型号:HC-SR04
超声波模块除了VCC和GND两个接口之外,还有TRIG和ECHO引脚,测距原理就是让波发出去接收回来,统计时间得出距离。
那么如何使波发出去呢?
给Trig口至少10微秒的高电平
怎么知道波开始发送了
Echo信号由低电平跳转到高电平,表示开始发送波
怎么知道波回来了
Echo引脚由高电平跳转回低电平 表示波回来了
怎么算时间
Echo引脚维持高电平的时间
波出去的那一刻,开始启动定时器
波回来的那一刻,停止定时器,计算中间的时间
怎么算距离
距离 = 速度(340m/s) * 时间 / 2
超声波时序图如下:
利用距离控制小灯和蜂鸣器代码如下:
#include "reg52.h"
#include <intrins.h>
sbit D5 = P3^7;
sbit D6 = P3^6;
sbit Trig = P1^5;
sbit Echo = P1^6;
sbit sounder = P1^0;
void Delay10us() //@11.0592MHz
{
unsigned char i;
i = 2;
while (--i);
}