基于51单片机来开发的智能感应开盖垃圾桶

为什么要引入定时器呢?
因为定时到报表的时候,可以由硬件执行那部分程序,软件部分仍然单独运行。
一、智能垃圾桶需求分析:
当距离小于等于10时,垃圾桶开盖持续两秒钟,否则垃圾桶关闭盖子
当检测到震动时,垃圾桶开盖持续两秒钟,否则垃圾桶关闭盖子
当按下按键时,垃圾桶开盖
基于51单片机来开发的智能感应开盖垃圾桶_第1张图片
基于51单片机来开发的智能感应开盖垃圾桶_第2张图片
二、智能垃圾桶工作原理。
基于51单片机来开发的智能感应开盖垃圾桶_第3张图片
主要是通过超声波测距与舵机转动相结合来实现主功能。超声波采用定时器1进行定时,实现无难度;舵机转动我们要通过定时器0来实现中断,从而确定最小定时单位0.5ms,这里我们确定一个标志位,jd,从而来决定是否让舵机进行转动,例如,提前声明jd=3,当定时器开始计数时,跑到这里jd=3,定时器0不断进行中断操作,从而确定是否进行转动(这里定义PWM波时一定要一个周期循环定义)。当震动传感器震动时,cpu先对舵机进行的延时,从而不对震动传感器的响应进行操作,这里需要我们把这个震动传感器定义到中端口P3^2,打开外部中断EX,并且把ET0设置为低电平触发,当震动传感器震动时,cpu(即晶振,单片机的心脏)停止对舵机进行计时,优先处理震动。

#include "reg52.h"

sbit LED1 = P3^7;//根据原理图(电路图),设备变量led1指向P3组IO口的第7口
sbit LED2 = P3^6;//根据原理图(电路图),设备变量led2指向P3组IO口的第6口
sbit Trig = P1^5;
sbit Echo = P1^6;
sbit SG90 = P1^4;
sbit Virbate = P3^2;//3.2口是外部中断口,当有电压来临时,中断其他服务程序,执行此程序。
sfr AUXR=0x8E;

int cnt=0;
int jd;
int mark_vibrate=0;
double dis;
double time;
void Timer0Init(void)		//500微秒@11.0592MHz
{
	AUXR &= 0x7F;		//定时器时钟12T模式
	TMOD &= 0xF0;		//设置定时器模式
	TMOD |= 0x01;		//设置定时器模式
	TL0 = 0x33;		//设置定时初值
	TH0 = 0xFE;		//设置定时初值
	TF0 = 0;		//清除TF0标志
	TR0 = 1;		//定时器0开始计时
	EA = 1;//打开总中断
	ET0 = 1;//打开定 时器0的中断
}//计时器0管舵机,主要记录0.5ms时间

void Timer1Init(void)		//71.111毫秒@11.0592MHz
{
	AUXR &= 0xBF;		//定时器时钟12T模式
	TMOD &= 0x0F;		//设置定时器模式
	TMOD |= 0x10;		//设置定时器模式
	TL1 = 0x00;		//设置定时初值
	TH1 = 0x00;		//设置定时初值
}//计时器1管超声波收发时间

void Delay10us()		//@11.0592MHz
{
	unsigned char i;

	i = 2;
	while (--i);
}

void Delay200ms()		//@11.0592MHz
{
	unsigned char i, j, k;

	i = 2;
	j = 103;
	k = 147;
	do
	{
		do
		{
			while (--k);
		} while (--j);
	} while (--i);
}


void Delay600ms()		//@11.0592MHz
{
	unsigned char i, j, k;

	i = 5;
	j = 52;
	k = 195;
	do
	{
		do
		{
			while (--k);
		} while (--j);
	} while (--i);
}


void Trigbegin()//超声波开始发送波
{
	Trig = 0;
	Trig = 1;
	Delay10us();
	Trig = 0;
}
void OpenLight()//开盖灯
{
	LED1 = 0;
	LED2 = 1;
}
void CloseLight()//关盖灯
{
	LED1 = 1;
	LED2 = 0;
}
void SG90Init()//舵机初始化
{
	cnt = 0;//开盖关盖从0计时
	jd = 1;//初始化舵机为关盖状态
	SG90=1;
}
void SG90_0()//舵机中断关盖
{
	jd = 1;
	cnt = 0;
	Delay200ms();
}
void SG90_90()//舵机中断开盖
{
	jd = 3;
	if(jd_back!=jd)//下次进来如果还和标志位相等,就不用延时,直接90°
	{
		cnt = 0;
		Delay600ms();//在这600ms里PWM波不断地让舵机重复90°,所以舵机臂不下降
	}
	jd_back=jd;//把标志位赋值给他,下次若手未动,则不延时,舵机直接90°不动。
}


double getdis()
{
	Trigbegin();
	while(Echo == 0);
	TR1=1;//开始计时
	while(Echo == 1);
	TR1=0;//停止计时
	time=(TH1*256+TL1)*1.085/1000000;//以S为单位计时
	TH1=0x00;
	TL1=0x00;
	Delay200ms();
	return (time*17000);
}
void ExInit()外部中断P3^2初始化
{
	EX0 = 1;//打开外部中断
	IT0 =0;//低电平触发中断
}
void main()
{
	Timer0Init();//舵机开始计时,中断时跳到定时器0中断函数处
	Timer1Init();
	ExInit();
	SG90Init();
	while(1)
	{
		dis=getdis();//从获取距离这一刻开始计时
			if(dis<=10||mark_vibrate == 1)
		{
			OpenLight();
			SG90_90();
			mark_vibrate = 0;
		}
		else
		{
			CloseLight();
			SG90_0();
		}
	}
}
void Timer0() interrupt 1//定时器0中断,由硬件调用,软件部分继续执行
{
	cnt++;
	TL0 = 0x33;		
	TH0 = 0xFE;	
	if(cnt < jd)
	{
		SG90 = 1;
	}	
	else
	{
		SG90 = 0;
	}
	if(cnt == 40)
	{
		cnt = 0;
		SG90=1;//又开始进入下一个周期,从头开始
		
		
		TL0 = 0x33;		
		TH0 = 0xFE;
	}
}
void Ex0_Handler() interrupt 0//外部中断
{									//中断cpu计数,小技巧
	mark_vibrate = 1;
}

你可能感兴趣的:(8个项目玩转单片机,51单片机)