所用模块知识
超声波模块、舵机模块、震动模块
主控芯片:STC89C52RC
1.震动模块
2.蜂鸣器
3.舵机
如下图所示,最便宜的舵机
sg90
,常用三根或者四根接线,黄色为
PWM
信号控制
用处:垃圾桶项目开盖用、智能小车的全比例转向、摄像头云台、机械臂等
常见的有
0-90°
、
0-180°
、
0-360°
![](https://img-blog.csdnimg.cn/a55552b2118e40398ba31e005fe0463e.png)
向黄色信号线
“
灌入
”PWM
信号。
PWM
波的频率不能太高,大约
50HZ
,即周期
=1/
频率
=1/50=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
定时器需要定时
20ms,
关心的单位
0.5ms, 40
个的
0.5ms,
初值
0.5m cnt++
1s = 10ms * 100
20ms = 0.5ms * 40
![](https://img-blog.csdnimg.cn/4445debb2acc4d01b4029315c43b9fbb.png)
编程实现
#include"reg52.h"
#include<intrins.h>
sbit sg_90con=P1^1;
int jd;
int cnt=0;
void Time0Init()
{
//1.配置定时器0工作模式位16位计时
TMOD=0x01;
//2.给初值,定一个10ms出来
TL0 = 0x33; //设置定时初始值
TH0 = 0xFE;
//3.打开总中断EA;
EA=1;
//4.打开定时器0中断
ET0=1;
//5.开始计时,定时器”数数“
TR0=1;
TF0=0;
}
void Delay300ms() //@11.0592MHz
{
unsigned char data i, j, k;
i = 3;
j = 26;
k = 223;
do
{
do
{
while (--k);
} while (--j);
} while (--i);
}
void Delay2000ms() //@11.0592MHz
{
unsigned char data 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度,0.5ms,溢出1就是0.5,高电平
cnt=0;
sg_90con=1;//一开始从高电平开始
//每隔两秒切换一次角度
while(1)
{
jd=4;//135度 2ms高电平
cnt=0;
Delay2000ms();
jd=1;//0度
cnt=0;
Delay2000ms();
}
}
void Time0Handler() interrupt 1
{
cnt++;//统计爆表的次数. cnt=1的时候,报表了1
TL0 = 0x33; //设置定时初始值
TH0 = 0xFE;
if(cnt<jd)//控制PWM波
{
sg_90con=1;
}
else
{
sg_90con=0;
}
if(cnt==40)//爆表40次,经过了20ms
{
cnt=0;
sg_90con=1;
}
}
4.超声波测距
型号:
HC-SR04
接线参考:模块除了两个电源引脚外,还有
TRIG
,
ECHO
引脚,这两个引脚分别接我们开发板的
P1.5
和
P1.6
端口
![](https://img-blog.csdnimg.cn/3ab367fe972f42a9a0810cac6a4df713.png)
//超声波测距模块是用来测量距离的一种产品,通过发送和收超声波,利用时间差和声音传播速度, 计算出模块到前方障碍物的距离。
怎么让它发送波
Trig
,给
Trig
端口至少
10us
的高电平
怎么知道它开始发了
Echo
信号,由低电平跳转到高电平,表示开始发送波
怎么知道接收了返回波
Echo
,由高电平跳转回低电平,表示波回来了
怎么算时间
Echo
引脚维持高电平的时间!
波发出去的那一下,开始启动定时器
波回来的拿一下,我们开始停止定时器,计算出中间经过多少时间
怎么算距离
距离
=
速度 (
340m/s
)
*
时间
/2
下面是代码实现:
#include"reg52.h"
//距离小于10cm,D5亮,D6灭,反之相反现象;
sbit D5=P3^7;//根据原理图(电路图),设备变量led1指向P3组IO口的第7口
sbit D6=P3^6;//根据原理图(电路图),设备变量led2指向P3组IO口的第6口
sbit Trig=P1^5;
sbit Echo=P1^6;
void Delay10us() //@11.0592MHz
{
unsigned char data i;
i = 2;
while (--i);
}
void Time0Init()
{
TMOD &=0xF0; //设置定时器模式
TMOD |=0x01;
TH0=0;
TL0=0;
//设置定时器0工作模式1,初始值设定0开始数数,不着急启动定时器
}
void startHC()
{
Trig=0;
Trig=1;
Delay10us();
Trig=0;
}
void Delay200ms() //@11.0592MHz
{
unsigned char data i, j, k;
i = 2;
j = 103;
k = 147;
do
{
do
{
while (--k);
} while (--j);
} while (--i);
}
void main()
{
double time;
double dis;
Time0Init();
while(1)
{
Delay200ms();
//1. Trig ,给Trig端口至少10us的高电平
startHC();
//2. echo由低电平跳转到高电平,表示开始发送波
while(Echo==0);
//波发出去的那一下,开始启动定时器
TR0=1;
//3. 由高电平跳转回低电平,表示波回来了
while(Echo==1);
//波回来的那一下,我们开始停止定时器
TR0=0;
//4. 计算出中间经过多少时间
time=(TH0*256+TL0)*1.085;//us为单位
//5. 距离 = 速度 (340m/s)* 时间/2
dis=time*0.017;
if(dis<10)
{
D5=0;
D6=1;
}
else
{
D5=1;
D6=0;
}
//定时器数据清零,以便下一次测距
TH0=0;
TL0=0;
}
}
项目概述
功能描述
检测靠近时,垃圾桶自动开盖并伴随滴一声,
2
秒后关盖
发生震动时,垃圾桶自动开盖并伴随滴一声,
2
秒后关盖
按下按键时,垃圾桶自动开盖并伴随滴一声,
2
秒后关盖
硬件说明
SG90
舵机,超声波模块,震动传感器,蜂鸣器
接线说明
舵机控制口
P1.1
;超声波
Trig
接
P1.5
,Echo
接
P1.6
;蜂鸣器接
P2.0
口
;
震动传感器接
P3.2`
口
(
外部中断0)
编程实现
开发步骤:
1.
舵机和超声波代码整合
舵机用定时器
0
超声波用定时器
1
实现物体靠近后,自动开盖,
2
秒后关盖
2.
查询的方式添加按键控制
3.
查询的方式添加震动控制
4.
使用外部中断
0
配合震动控制
代码:
#include"reg52.h"
//距离小于10cm,D5亮,D6灭,反之相反现象;
sbit D5 =P3^7;//根据原理图(电路图),设备变量led1指向P3组IO口的第7口
sbit D6 =P3^6;//根据原理图(电路图),设备变量led2指向P3组IO口的第6口
sbit Trig =P1^5;
sbit Echo =P1^6;
sbit sg_90con =P1^1;
sbit vibrate =P3^2;
sbit beep =P2^0;
sbit sw1 =P2^1;
int jd;
int jd_bak;
int cnt=0;
int mark_vibrate=0;
void Delay10us() //@11.0592MHz
{
unsigned char data i;
i = 2;
while (--i);
}
void Time0Init()
{
//1.配置定时器0工作模式位16位计时
TMOD=0x01;
//2.给初值,定一个10ms出来
TL0 = 0x33; //设置定时初始值
TH0 = 0xFE;
//3.打开总中断EA;
EA=1;
//4.打开定时器0中断
ET0=1;
//5.开始计时,定时器”数数“
TR0=1;
TF0=0;
}
void Time1Init()
{
TMOD &=0x0F; //设置定时器模式
TMOD |=0x10;
TH1=0;
TL1=0;
//设置定时器0工作模式1,初始值设定0开始数数,不着急启动定时器
}
void startHC()
{
Trig=0;
Trig=1;
Delay10us();
Trig=0;
}
void Delay150ms() //@11.0592MHz
{
unsigned char data i, j, k;
i = 2;
j = 13;
k = 237;
do
{
do
{
while (--k);
} while (--j);
} while (--i);
}
double get_distance()
{
double time;
//定时器数据清零,以便下一次测距
TH1=0;
TL1=0;
//1. Trig ,给Trig端口至少10us的高电平
startHC();
//2. echo由低电平跳转到高电平,表示开始发送波
while(Echo==0);
//波发出去的那一下,开始启动定时器
TR1=1;
//3. 由高电平跳转回低电平,表示波回来了
while(Echo==1);
//波回来的那一下,我们开始停止定时器
TR1=0;
//4. 计算出中间经过多少时间
time=(TH1*256+TL1)*1.085;//us为单位
//5. 距离 = 速度 (340m/s)* 时间/2
return (time*0.017);
}
void Delay2000ms() //@11.0592MHz
{
unsigned char data i, j, k;
i = 15;
j = 2;
k = 235;
do
{
do
{
while (--k);
} while (--j);
} while (--i);
}
void openStatusLight()
{
D5=0;
D6=1;
}
void closeStatusLight()
{
D5=1;
D6=0;
}
void openDusbin()
{
char n;
jd=3;
if(jd_bak!=jd)
{
cnt=0;
beep=0;
for(n=0;n<2;n++)
{
Delay150ms();
}
beep=1;
Delay2000ms();
}
jd_bak=jd;
}
void closeDusbin()
{
jd=1;
jd_bak=jd;
cnt=0;
Delay150ms();
}
void EX0_Init()
{
EX0=1;
IT0=0;
}
void initsg90_0()
{
jd=1;//初始角度是0度,0.5ms,溢出1就是0.5,高电平
cnt=0;
sg_90con=1;//一开始从高电平开始
}
void main()
{
double dis;
Time0Init();//初始化定时器
Time1Init();
EX0_Init();
initsg90_0();
while(1)
{
//Delay150ms();
dis=get_distance();
if(dis<10||sw1==0||mark_vibrate==1)
{
openStatusLight();
openDusbin();
mark_vibrate=0;
}
else
{
closeStatusLight();
closeDusbin();
}
}
}
void Time0Handler() interrupt 1
{
cnt++;//统计爆表的次数. cnt=1的时候,报表了1
TL0 = 0x33; //设置定时初始值
TH0 = 0xFE;
if(cnt<jd)//控制PWM波
{
sg_90con=1;
}
else
{
sg_90con=0;
}
if(cnt==40)//爆表40次,经过了20ms
{
cnt=0;
sg_90con=1;
}
}
void Ex0_Handler() interrupt 0
{
mark_vibrate=1;
}