为什么要引入定时器呢?
因为定时到报表的时候,可以由硬件执行那部分程序,软件部分仍然单独运行。
一、智能垃圾桶需求分析:
当距离小于等于10时,垃圾桶开盖持续两秒钟,否则垃圾桶关闭盖子
当检测到震动时,垃圾桶开盖持续两秒钟,否则垃圾桶关闭盖子
当按下按键时,垃圾桶开盖
二、智能垃圾桶工作原理。
主要是通过超声波测距与舵机转动相结合来实现主功能。超声波采用定时器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;
}