第四篇 小项目整合-感应开盖垃圾桶v3.0

目录

 

一、项目概述

1.功能描述

2.所需硬件

3.接线说明

二、开发步骤

1.SG90和HC-SR04代码整合

2.添加按键控制(433M)和开盖滴滴声(蜂鸣器)

3.添加震动控制(外部中断配合)

🔖再识中断 - 外部中断

①外部中断触发

②外部中断相关寄存器

③中断优先级

三、参考代码(v1.0)

 🔖BUG处理

四、成品展示


 说明:前面已经做过两版垃圾桶(arduino板和树莓派),现在用51来做v3.0版。对比前面,arduino和树莓派都提供了可调用的API,方便且快速开发。在v3.0的51版本,可以说更加底层和接近原理,是作为学习51基础知识(定时器、中断等)不错的小项目。

一、项目概述

1.功能描述

🔖检测靠近时,垃圾桶自动开盖并伴随滴一声,2秒后关盖

🔖发生震动时,垃圾桶自动开盖并伴随滴一声,2秒后关盖

🔖按下按键时,垃圾桶自动开盖并伴随滴一声,2秒后关盖

2.所需硬件

🔖SG90舵机

🔖HC-SR04超声波模块

🔖震动传感器、蜂鸣器

🔖433M射频模块等

3.接线说明

需要注意的是,接入震动传感器要使用到外部中断,需要接到特定的引脚(P3^2、P3^3、P4^2)

二、开发步骤

1.SG90和HC-SR04代码整合

这里要做的是整合前面第三篇的代码(第三篇 SG90舵机和HC-SR04测距)

需要修改的是:(SG90用定时器0、HC-SR04用定时器1

2.添加按键控制(433M)和开盖滴滴声(蜂鸣器)

普通I/O口的开发,较简单略

3.添加震动控制(外部中断配合)

说明:在前面的代码中,已经使用到了定时器中断,这里添加震动传感器来实现震动开盖的功能,也是为了学习一下外部中断。在此处,如果不使用外部中断,由于震动传感器检测到震动时的高电平不稳定,可能因为CPU在执行软件延时的时候难以被捕获,无法实现开盖或造成响应不灵敏的问题。

🔖再识中断 - 外部中断

外部中断触发

📓通过阅读芯片手册,我们可以知道外部中断的触发行为有两种:下降沿、低电平

📓从原理图可以知道,能触发外部中断的引脚有P3^2、P3^3、P4^2

外部中断相关寄存器

 (前面篇已经稍详细介绍如何使用中断(第二篇 定时器和定时器中断)此处省略)

​​​​​​​③中断优先级

三、参考代码(v1.0

#include "reg52.h"
#include <intrins.h>

sbit Trig		=  P1^0;
sbit Echo		=  P1^1;
sbit buzzer		=  P1^2;
sbit servo		=  P1^3;
sbit removeCtrl =  P1^4;
sbit vibrator	=  P3^2;
sbit led1		=  P3^6;
sbit key1		=  P2^1;

char cnt = 0;
char angle = 1;
char vibrator_mark = 0;		//震动传感器标志位

/*********软件延时10us(启动HC-SR04用)******/
void Delay10us(){	
	unsigned char i;
	i = 2;
	while (--i);
}

/**********软件延时1.5s***********/
void Delay1500ms(){
	unsigned char i, j, k;
	_nop_();
	i = 11;
	j = 130;
	k = 111;
	do{
		do{
			while (--k);
		} while (--j);
	} while (--i);
}

/**********软件延时0.3s(蜂鸣器用)***********/
void Delay300ms(){
	unsigned char i, j, k;
	_nop_();
	i = 3;
	j = 26;
	k = 223;
	do{
		do{
			while (--k);
		} while (--j);
	} while (--i);
}

/**********定时器1初始化(测距用)***********/
void time1Init(){
	TMOD |= 0x01<<4;
	TMOD &= ~(0x01<<5); 
	TL1 = 0;
	TH1 = 0;
}

/**********定时器0初始化(模拟PWM用)***********/
void time0Init(){
	TMOD |= 0x01<<0;
	TMOD &= ~(0x01<<1);
	TL0 = 0x33;		//设置定时初始值
	TH0 = 0xFE;		//设置定时初始值
	TR0 = 1;		//定时器0开始计时
	TF0 = 0;		//清除TF0标志
	ET0 = 1;		//定时器中断
	EA = 1;			//总中断
}

/*********外部中断0初始化**********/
void ext0Init(){
	IE |= 0x01<<0;
	IT0 = 0;
}

/*********向Trig发送一个10us的脉冲信号************/
void startHC(){
	Trig = 0;
	Trig = 1;
	Delay10us();
	Trig = 0;
}

/********测距实现***********/
double getDistance(){
	double distance;
	startHC();
	while(Echo != 1);			//echo非高电平时,循环等待 -- 等待波开始发送
	TCON |= 0x1<<6;				//执行到这里说明echo为高电平,波开始发送 -- 开启定时器
	while(Echo != 0);			//echo非低电平时,循环等待 -- 等待波的返回
	TCON &= ~(0x1<<6);		//到这里说明波已经返回
	distance = (((TH1<<8) + TL1) * 1.085)*0.034;
	TH1 = 0;		//重新从0计数
	TL1 = 0;
	return 	distance;	//定时器得到时间,计算得到距离(已知速度340m/s)
}

/***********各模块初始化*************/
void moduleInit(){
	led1       = 1;
	buzzer     = 1;
	servo      = 1;
	vibrator   = 1;
}

void main(void){
	double distance;
	Delay300ms();
	time1Init();
	time0Init();
	ext0Init();
	moduleInit();
	while(1){
		distance = getDistance();
		if((distance/2) < 10 || key1 == 0 || removeCtrl == 1 || vibrator_mark == 1){
			led1 = 0;
			angle = 4;
			buzzer = 0;
			Delay300ms();
			buzzer = 1;
			Delay1500ms();
			vibrator_mark = 0;
		}else{
			buzzer = 1;
			led1   = 1;
			angle  = 1;
		}
	}
}

/***********定时器0中断处理************/
void timeInterruptHandler() interrupt 1{
	cnt++;
	TL0 = 0x33;		//重新设置定时初始值
	TH0 = 0xFE;		//重新设置定时初始值
	if(cnt < angle){	//若此时angle=4(转至135°),cnt=0时拉高电平到cnt=4时不满足拉低,即获得2ms的高电平
		servo = 1;			//若此时angle=1(转至0°),cnt=0时拉高到cnt=1时不满足拉低,即获得0.5ms的高电平
	}else{
		servo = 0;
	}
	if(cnt == 40){		//PWM的周期20ms
		cnt = 0;
		servo = 1;
	}
}

/***********外部中断0处理函数**********/
void ext0InterruptHandler() interrupt 0{
	vibrator_mark = 1;
}

 🔖BUG处理

以上参考代码会出现小bug,当超声波测距持续检测到距离小于10,条件恒成立,一直执行开盖部分的代码,舵机会出现一抖一抖的现象,需要进行处理。(具体修改略)

四、成品展示

  • 3
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

AF_INET6

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值