目录
一、超声波测距传感器认知
二、从零编程实现超声波测距
三、项目——感应开关盖垃圾桶
1、开发步骤
2、感应开关盖垃圾桶代码测试
一、超声波测距传感器认知
超声波测距模块是用来测量距离的一种产品,通过发送和接收超声波,利用时间差和声音传播速度,计算出模块到前方障碍物的距离
接线参考:模块除了两个电源引脚外,还有TRIG、ECHO引脚,这两个引脚分别接我们开发板的P1.5和P1.6端口
TRIG引脚: 发送波的引脚
ECHO引脚:接收波的引脚
怎么让它发送波
Trig,给Trig端口至少10μs的高电平
怎么知道开始发波
Echo,由低电平跳转到高电平,表示开始发送波
怎么让它接收了返回波
Echo,由高电平转回低电平,表示波回来了
怎么算时间
波发出去的那一下,开始启动定时器
波回来的那一下,我们停止定时器,计算出中间经过多少时间
怎么算距离
距离 = (速度(340m/s)* 高电平时间)/ 2
超声波的时序图
二、从零编程实现超声波测距
#include "reg52.h"
//距离小于10cm,D5亮,D6灭,反之相反现象
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);
}
void Time0Init(){
TMOD &= 0xF0; //设置定时器模式
TMOD |= 0x01; //设置定时器模式
TL0 = 0; //设置定时初值
TH0 = 0; //设置定时初值
//设置定时器0工作模式1,初始值设定0开始数数
}
void startHC(){
Trig = 0;
Trig = 1;
Delay10us();
Trig = 0;
}
void main()
{
double time;
double dis;
Time0Init();
while(1){
//1、给Trig端口至少10μs的高电平
startHC();
//2、由低电平跳转到高电平,表示开始发送波
while(Echo == 0);
//3、波发出去时,开启定时器
TR0 = 1;
//4、由高电平跳转到低电平,表示接收波
while(Echo == 1);
//5、波回来那一下,我们停止定时器
TR0 = 0;
//6、计算出中间经过多长时间
time = (TH0 * 256 + TL0) * 1.085; //μs为单位
//7、距离 = 速度(340m/s)* 时间 /2
//dis= 340m/s = 34000cm/s = 34cm/ms = 0.034cm/μs
dis = time * (0.034/2);
if(dis < 10){
D5 = 0;
D6 = 1;
}else{
D5 = 1;
D6 = 0;
}
//定时器数据清零,以便下次测距
TL0 = 0; //设置定时初值
TH0 = 0; //设置定时初值
}
}
三、项目——感应开关盖垃圾桶
1、开发步骤
1、舵机和超声波代码整合
舵机用定时器0
超声波用定时器1
实现物体靠近后,自动开盖,2秒后关盖
2、查询的方式添加按键控制
3、查询的方式添加震动控制
4、使用外部中断0配合震动控制
2、感应开关盖垃圾桶代码测试
#include "reg52.h"
//距离小于10cm,D5亮,D6灭,反之相反现象
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 jd;
char jd_bak; //记录上一个角度标记
char cnt = 0;
char mark_vibrate = 0; //添加一个标记
void Delay2000ms() //@11.0592MHz
{
unsigned char i, j, k;
i = 15;
j = 2;
k = 235;
do
{
do
{
while (--k);
} while (--j);
} while (--i);
}
void Delay150ms() //@11.0592MHz
{
unsigned char i, j, k;
i = 2;
j = 13;
k = 237;
do
{
do
{
while (--k);
} while (--j);
} while (--i);
}
void Delay10us() //@11.0592MHz
{
unsigned char i;
i = 2;
while (--i);
}
void Time0Init(){
//1、配置定时器0工作模式位16位计时
TMOD &= 0xF0; //设置定时器模式
TMOD |= 0x01; //设置定时器模式
//2、给定时器一个初值,每个周期都等于0.5ms
TL0 = 0x33;
TH0 = 0xFE;
//3、定时器开始计时
TR0 = 1;
TF0 = 0;
//4、打开中断定时器
ET0 = 1;
//5、设置总中断定时器
EA = 1;
}
void Time1Init(){
TMOD &= 0x0F; //设置定时器模式
TMOD |= 0x10; //设置定时器模式
TL1 = 0; //设置定时初值
TH1 = 0; //设置定时初值
//设置定时器0工作模式1,初始值设定0开始数数
}
void startHC(){
Trig = 0;
Trig = 1;
Delay10us();
Trig = 0;
}
double get_distance(){
double time;
//定时器数据清零,以便下次测距
TL1 = 0; //设置定时初值
TH1 = 0; //设置定时初值
//1、给Trig端口至少10μs的高电平
startHC();
//2、由低电平跳转到高电平,表示开始发送波
while(Echo == 0);
//3、波发出去时,开启定时器
TR1 = 1;
//4、由高电平跳转到低电平,表示接收波
while(Echo == 1);
//5、波回来那一下,我们停止定时器
TR1 = 0;
//6、计算出中间经过多长时间
time = (TH1 * 256 + TL1) * 1.085; //μs为单位
//7、距离 = 速度(340m/s)* 时间 /2
//dis= 340m/s = 34000cm/s = 34cm/ms = 0.034cm/μs
return (time * (0.034/2));
}
void openStatusLight(){
D5 = 0;
D6 = 1;
}
void closeStatusLight(){
D5 = 1;
D6 = 0;
}
void initSG90_0(){
jd = 1; //初始角度是0度,什么时候0度,刚好是0.5ms的高电平,也是定时器溢出1次
cnt = 0;
sg90_con = 1; //刚开始给PWM信号一个高电平
}
void openDusbin(){ //舵机开盖
char n;
jd = 3; //90度,1.5ms的高电平
if(jd_bak != jd){
cnt = 0; //每切换一次角度,都要重置cnt的值
beep = 0;
for(n=0;n<2;n++);
Delay150ms();
beep = 1;
Delay2000ms();
}
jd_bak = jd;
}
void closeDusbin(){ //舵机关盖
jd = 1; //0度,1.5ms的高电平
cnt = 0; //每切换一次角度,都要重置cnt的值
jd_bak = jd;
Delay150ms();
}
void EX0_Init(){ //打开外部中断函数
//打开外部中断
EX0 = 1;
//低电平触发
IT0 = 0;
}
void main()
{
double dis;
Time0Init();
Time1Init();
EX0_Init();
//舵机的初始位置
initSG90_0();
while(1){
//超声波测距
dis = get_distance();
if(dis < 10 || SW1 == 0 || mark_vibrate == 1){ //如果小于10cm,或者SW1按键被按下,或者vibrate震动
//开盖,灯状态,D5亮
openStatusLight();
//舵机开盖
openDusbin();
mark_vibrate = 0;
}else{
//关盖,灯状态,D5灭
closeStatusLight();
//舵机关盖
closeDusbin();
}
}
}
void Time0Handler() interrupt 1 //定时器0的硬件中断号为 interrupt 1
{
cnt ++; //统计爆表的次数
//给定时器重新定义初值,每个周期都等于0.5ms
TL0 = 0x33;
TH0 = 0xFE;
//控制PWM波形
if(cnt < jd){
sg90_con = 1;
}else{
sg90_con = 0;
}
if(cnt == 40){ //要爆表40次,经过了20ms
cnt = 0; //当100次表示1s,重新让cnt从0开始,计算下一次的1s
sg90_con = 1;
}
}
void Ex0_Handler() interrupt 0 //外部中断号为 interrupt 0
{
mark_vibrate = 1;
}
垃圾桶实体演示