文章目录
- 前期准备:
- 超声波模块
- SG90舵机
- 1、概念
- 舵机代码
- 震动检测模块
- 蜂鸣器
- 定时器和中断
- 项目实物
- 项目代码:
前期准备:
超声波模块
简介:
超声波传感器模块上面通常有两个超声波元器件,一个用于发射,一个用于接收。
硬件
电路板上有4个引脚:
VCC(正级)
Trig(触发)
Echo(回应)
GND(接地-负极)
主要参数:
工作电压与电流:5V、15mA
感测距离:2~400cm
感测角度:不大于15°
被测物体的面积:不要小于50cm²,且尽量平整
具备温度补偿电路
在超声波模块的触发脚位输入10微秒以上的高电位,即可发射超声波,发射超声波之后,与接收到传回的超声波之前,“响应”脚位呈现高电位。因此,程序可以从“响应”脚位的高位脉冲持续时间,换算出被测物的距离。
超声波模块工作原理
超声波时序图
T(发波)
R(接受)
先给 Trig 引脚发送一个 10uS(微秒)的 TTL(高电平)
T就可以发波了
发出的是循环 8 个 40KHz 的脉冲
波发出去后,Echo 引脚就会一直维持高电平,也就是说波在空中传播的过程是一直维持高电平
那么就可以根据Echo 引脚的高电平维持时间,超声波在空气中的物理性质的传输速度,就可以算出障碍物跟发波点的距离
即超声波能在空气中1秒能跑多远,那么就可以通过Echo 引脚的高电平维持时间,换算距离了
代码测试(D5D6灯亮灭):
#include "reg52.h"
sbit D5 = P3^7;
sbit D6 = P3^6;
sbit Trig = P1^5;
sbit Echo = P1^6;
void Delay10us() //@11.0592MHz
{
unsigned char i;
i = 2;
while (--i);
}
//配置定时器1
void Timer1Init(void)
{
TMOD &= 0xF0;
TMOD |= 0x10;
TH1 = 0;
TL1 = 0;
}
void startHc()
{
Trig = 0;
Trig = 1;
Delay10us();
Trig = 0;
}
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 openStatusLight()
{
D5 = 0;
D6 = 1;
}
void closeStatusLight()
{
D5 = 1;
D6 = 0;
}
void main()
{
double dis;
Timer1Init();
while(1){
dis = get_distance();
if(dis < 10){
openStatusLight();
}else{
closeStatusLight();
}
}
}
SG90舵机
接线方法:
红-------------------------VCC
棕色----------------------GND
橙色----------------------信号线
1、概念
PWM 全称是 Pulse WidthModulation,也就是脉冲宽度调制
2、PWM信号图
3、频率
频率就是开关速度,把一次开关算作一个周期,那么频率就是 1 秒内进行了多少次开关
4、占空比
占空比就是一个周期内高电平时间和低电平时间的比例,一个周期内高电平时间越长占空比就越大,反之占空比就越小。占空比用百分之表示,如果一个周期内全是低电平那么占空比就是 0%,如果一个周期内全是高电平那么占空比就是100%。
舵机代码
#include "reg52.h"
sbit sg90_con = P1^1;
int jd;
int cnt = 0;
void Timer0Init(void) //500微秒@11.0592MHz
{
//定时器时钟1T模式
TMOD = 0x01; //设置定时器模式
TL0 = 0x33; //设置定时初值
TH0 = 0xFE; //设置定时初值
TF0 = 0; //清除TF0标志
TR0 = 1; //定时器0开始计时
ET0 = 1; //打开定时器0中断
EA = 1; //打开总中断
}
void Delay2000ms() //@11.0592MHz
{
unsigned char i, j, k;
i = 15;
j = 2;
k = 235;
do
{
do
{
while (--k);
} while (--j);
} while (--i);
}
void Delay300ms() //@11.0592MHz
{
unsigned char i, j, k;
i = 3;
j = 26;
k = 223;
do
{
do
{
while (--k);
} while (--j);
} while (--i);
}
void main()
{
Delay300ms();//让硬件稳定一下
Timer0Init(); //初始化定时器
cnt = 0;
jd = 1;
sg90_con = 1;
//每隔两秒切换一次角度
while(1){
jd = 3; //90度 1.5ms高电平
cnt = 0;
Delay2000ms();
jd = 1; //0度
cnt = 0;
Delay2000ms();
}
}
void TimeOHandler() interrupt 1
{
cnt++;//统计爆表的次数
//重新给初值
TL0 = 0x33; //设置定时初值
TH0 = 0xFE;
if(cnt < jd){
sg90_con = 1;
}else{
sg90_con = 0;
}
if(cnt == 40){//爆表40次,经过了20ms
cnt = 0;
sg90_con = 1;
}
}
震动检测模块
型号:SW-18010P
产品特点
1、采用本公司生产的高灵敏度震动开关,默认用SW-18010P震动传感器
2、比较器输出,信号干净,波形好,驱动能力强,超过15mA
3、工作电压3.3V-5V
4、输出形式:数字开关量输出(0和1)
5、设有固定螺栓孔,方便安装
6、小板PCB尺寸:3.2cm x 1.4cm
7、使用宽电压LM393比较器
接线
1、VCC:接电源正极
2、GND:接电源负极
3、DO:数字量信号输出
4、AO:用此震动传感器此功能无效
注意:电源极性不能反接、否则有可能将芯片烧坏、开关信号指示灯亮时输出低电平、不亮输出高电平、信号输出的电平接近于电源电压
使用方法
1、产品不震动时,震动开关呈断开状态,输出端DO输出高电平,绿色指示灯不亮;
2、产品震动时,震动开关瞬间导通,输出端DO输出低电平,绿色指示灯亮;
3、输出端可以与单片机直接相连,通过单片机来检测高低电平,由此来检测环境是否有震动,起到报警作用
片机直接相连,通过单片机来检测高低电平,由此来检测环境是否有震动,起到报警作用
4、电位器可以调整模块的检测灵敏度
蜂鸣器
定时器和中断
项目实物
项目代码:
#include "reg52.h"
sbit D5 = P3^7;
sbit D6 = P3^6;
sbit Trig = P1^5;
sbit Echo = P1^6;
sbit sg90_con = P1^1;
sbit SW1 = P2^1;
sbit vibrate = P3^2;
sbit beep = P2^0;
char mark_vibrate = 0;
char jd;
char cnt = 0;
char jd_bak;
void Delay150ms() //@11.0592MHz
{
unsigned char i, j, k;
i = 2;
j = 13;
k = 237;
do
{
do
{
while (--k);
} while (--j);
} while (--i);
}
void Delay2000ms() //@11.0592MHz
{
unsigned char i, j, k;
i = 15;
j = 2;
k = 235;
do
{
do
{
while (--k);
} while (--j);
} while (--i);
}
void Delay10us() //@11.0592MHz
{
unsigned char i;
i = 2;
while (--i);
}
//配置定时器0
void Timer0Init(void)
{
//定时器时钟1T模式
TMOD &= 0xF0;
TMOD |= 0x01; //设置定时器模式
TL0 = 0x33; //设置定时初值
TH0 = 0xFE; //设置定时初值
TF0 = 0; //清除TF0标志
TR0 = 1; //定时器0开始计时
ET0 = 1; //打开定时器0中断
EA = 1; //打开总中断
}
//配置定时器1
void Timer1Init(void)
{
TMOD &= 0x0F;
TMOD |= 0x10;
TH1 = 0;
TL1 = 0;
}
void startHc()
{
Trig = 0;
Trig = 1;
Delay10us();
Trig = 0;
}
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 openStatusLight()
{
D5 = 0;
D6 = 1;
}
void closeStatusLight()
{
D5 = 1;
D6 = 0;
}
void initSG90_0()
{
jd = 1;
cnt = 0;
sg90_con = 1;
}
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;//0度
jd_bak = jd;
cnt = 0;
Delay150ms();
}
void EX0_Init()
{
EX0 = 1;
IT0 = 0;
}
void main()
{
double dis;
Timer0Init();
Timer1Init();
EX0_Init();
initSG90_0();
while(1){
//超声波测距
dis = get_distance();
if(dis < 10 || SW1 == 0 || mark_vibrate == 1){
//开盖,灯状态,D5亮
openStatusLight();
openDusbin();
mark_vibrate = 0;
}else{
//关盖,灯状态,D5灭
closeStatusLight();
closeDusbin();
}
}
}
void TimeOHandler() interrupt 1
{
cnt++;//统计爆表的次数
//重新给初值
TL0 = 0x33; //设置定时初值
TH0 = 0xFE;
if(cnt < jd){
sg90_con = 1;
}else{
sg90_con = 0;
}
if(cnt == 40){//爆表40次,经过了20ms
cnt = 0;
sg90_con = 1;
}
}
void Ex0_Handler() interrupt 0 //设置外部中断
{
mark_vibrate = 1;
}