第二章 定时器

定时器/计数器

定时器/计数器0/1

定时器计数器

定时器/计数器0和1相关寄存器

定时器相关寄存器

定时器/计数器控制寄存器TCON

控制寄存器TCON

定时器/计数器工作模式寄存器TMOD

工作模式寄存器TMOD

定时器

简介


C51中的定时器和计数器是同一个硬件电路支持的,通过寄存器配置不同,就可以将他当做定时器
或者计数器使用。
确切的说,定时器和计数器区别是致使他们背后的计数存储器加1的信号不同。当配置为定时器使
用时,每经过1个机器周期,计数存储器的值就加1。而当配置为计数器时,每来一个负跳变信号
(信号从P3.4 或者P3.5引脚输入),就加1,以此达到计数的目的。
标准C51有2个定时器/计数器:T0和T1。他们的使用方法一致。C52相比C51多了一个T2


概念解读

  • 定时器和计数器,电路一样
  • 定时或者计数的本质就是让单片机某个部件数数
  • 当定时器用的时候,靠内部震荡电路数数
  • 当计数器用的时候,数外面的信号,读取针脚的数据

定时器怎么定时

定时器的本质原理: 每经过一个机器周期,就加1 :寄存器


  • 什么是晶振

    晶振(晶体震荡器),又称数字电路的“心脏”,是各种电子产品里面必不可少的频率元器件。数字电
    路的所有工作都离不开时钟,晶振的好坏、晶振电路设计的好坏,会影响到整个系统的稳定性。


  • 什么是时钟周期

    时钟周期也称为[振荡周期](振荡周期_百度百科 (baidu.com)),定义为[时钟频率](时钟频率_百度百科 (baidu.com))的倒数。时钟周期是计算机中最基本的、最小的时间单
    。在一个时钟周期内,CPU仅完成一个最基本的动作。时钟周期是一个时间的量。更小的时钟周
    期就意味着更高的工作频率 。

    • 什么是时钟周期
      时钟周期也称为[振荡周期](振荡周期_百度百科 (baidu.com)),定义为[时钟频率](时钟频率_百度百科 (baidu.com))的倒数。时钟周期是计算机中最基本的、最小的时间单
      。在一个时钟周期内,CPU仅完成一个最基本的动作。时钟周期是一个时间的量。更小的时钟周
      期就意味着更高的工作频率 。

    • 什么是机器周期

      机器周期也称为CPU周期。在计算机中,为了便于管理,常把一条指令的执行过程划分为若干个阶
      段(如取指、译码、执行等),每一阶段完成一个基本操作。完成一个基本操作所需要的时间称为
      机器周期。一般情况下,一个机器周期由若干个时钟周期组成 。

      在这里插入图片描述


    • 加1经过了多长时间

    当晶振频率是11.0592MHz的时候,等于11059.2KHz = 11059200Hz

    机器周期 = 12 x 时钟周期 =12 x (1/时钟频率) 秒 = 12 / 时钟频率 秒 = 12 / 11059200 秒 = 12 000 000
    / 11059200 微秒 = 1.085 微秒


定时器编程

设置相关寄存器:

定时器相关寄存器

  • 选用定时器0进行定时,对寄存器进行相关初始化

  • 采用16位定时器,TL0和TH0全用,最大计数216 = 65536,最多计时65536 x 1.085us = 71ms

  • 如何算出20ms定时器初值

    单片机数1下需要花费1.085us,20ms可以数20ms/1.085us = 18433下;

    那就使得单片机从65536-18433 = 47103(十六进制B7FF,近似B8)下开始计数

    因此 TL0 = 0x00;TH0 = 0xB8;可以使用STC—ISP验证一下
    在这里插入图片描述


关于TCON

TCON寄存器

  • 怎么知道计时溢出

    TCON寄存器的bit5(TF0)能表示溢出:当溢出的时候,硬件会修改bit5(TF0)位上面的数据,改成
    1(置1),如果不用中断,我们代码清零

  • 怎么知道定时器计数爆表了

    TCON寄存器的bit5(TF0)能表示爆表:当爆表的时候,硬件会将bit5(TF0)(置1),如果不用中断,我们代码清零

    • 怎么开始计时

      ​ TCON寄存器的bit4(TR0),通过软件将TR0赋值成1,开始计时

    • 设置定时器模式

      将TMOD的低四位设置成0 1,16位定时器功能。

    • 四个二进制数表示一位的16进制数

    • 8421法进制的转换(方便人类来看,对计算机底层来说,不关心进制010101010)

    • 配寄存器推荐用按位操作,清零的时候,对应的需要清零的位与上0,不需要清零的位与上1

    • 置1的时候,需要置1的位置或1,不需要置一的位置或0


小试牛刀

/*通过定时器0,控制LED亮一秒,灭一秒,晶振11059200Hz*/

#include <reg52.h>

sbit LED1 = P2^0;

void Timer0Init()
{
    TMOD &= 0xF0;	//与 1111 0000 高四位不变,低四位清零
    TMOD |= 0x01;	//或 0000 1111 高位不动,低位全用
    TL0 = 0x00;
    TH0 = 0xB8;		//设置定时器初值为20ms
    TF0 = 0;		//设置定时器溢出标志
    TR0 = 1;		//启动定时器0
}

void main()
{
    char cnt = 0;	
    LED1 = 1;		//上电以后,LED处于高电平灭
    
    Timer0Init();	//定时器0初始化
    
    if(TF0 == 1)	//如果TF0等于1的话,表示已经计数溢出已满一次
    {
        TF0 = 0;	//重新将TF0赋值成0,再次计数
        cnt++;		//每溢出一次,cnt++一次
        TL0 = 0x00;	
        TH0 = 0xB8;		//重新设定初值
  		if(cnt == 50)	//如果cnt++到50次,表示已经过了一秒
        {
            cnt = 0;	//每50次经过1s,给cnt重新赋值,计算下一次的1s
            LED1 = !LED1;	//LED1初始化高电平,取反低电平
        }
    }
}

中断系统

中断系统

中断查询次序

中断结构

中断结构

在这里插入图片描述

中断寄存器

中断寄存器

定时器中断方式控制

CPU能响应定时器0中断的条件:需要配置IE寄存器的bit1: ET0 bit7:EA

  1. ET0中断允许要置1 ET0 = 1
  2. EA总中断要置1 EA = 1
    硬件内部设计逻辑如下图:

定时器0响应中断要求

小试牛刀

/*定时器控制LED1每隔一秒亮一次灭一次,main函数里LED2每隔500ms亮灭一次*/


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

sbit LED1 = P2^0;
sbit LED2 = P2^1;

char cnt = 0;			//定义全局变量

void Timer0Init()
{
    TMOD &= 0xF0;		//与 1111 0000 高四位不变,低四位清零
    TMOD |= 0x01;		//或 0000 1111 高位不动,低位全用
    TL0 = 0x00;
    TH0 = 0xB8;			//设置定时器初值为20ms
    EA = 1;				//开启总中断
    ET0 = 1;			//开启定时器0中断
    TF0 = 0;			//设置定时器溢出标志
    TR0 = 1;			//启动定时器0
}

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

	_nop_();
	i = 4;
	j = 129;
	k = 119;
	do
	{
		do
		{
			while (--k);
		} while (--j);
	} while (--i);
}

void main()
{
    LED1 = 1;
    Timer0Init();			//定时器0相关初始化
    
    while(1)
    {
        LED2 = 0;
        Delay500ms();		//延时500ms
        LED2 = 1;
        Delay500ms();
    }
}

void Timer0 () interrupt 1
{
    cnt++;					//定时器0初始化每调用一次,cnt++一次
    TL0 = 0x00;				
    TH0 = 0xB8;				//溢出一次,重新赋值
    if(cnt == 50)			//溢出50次,表示计数满1s,执行相关操作
    {	
        cnt = 0;			
        LED1 = !LED1;		//对LED1的状态进行取反
    }
}

PWM开发SG90舵机

简介

PWM,英文名Pulse Width Modulation,是脉冲宽度调制缩写,它是通过对一系列脉冲的宽度进
行调制,等效出所需要的波形(包含形状以及幅值),对模拟信号电平进行数字编码,也就是说通
过调节占空比的变化来调节信号、能量等的变化,占空比就是指在一个周期内,信号处于高电平的
时间占据整个信号周期的百分比,例如方波的占空比就是50%.


  • 脉冲宽度调制
  • 通过占空比编码模拟信号
  • 占空比 一个周期内,高电平占据时长的百分比

占空比

如何实现PWM信号输出

  1. 通过芯片内部模块输出,一般观察手册或者芯片IO口都会标明这个是否是PWM口
    如下图增强51,STC15w的CPU

stc15w

  1. 如果没有集成PWM功能,可以通过IO口软件模拟,相对硬件PWM来说精准度略差

控制舵机

什么是舵机

如下图所示,最便宜的舵机sg90,常用三根或者四根接线,黄色为PWM信号控制
用处:垃圾桶项目开盖用、智能小车的全比例转向、摄像头云台、机械臂等
常见的有0-90°、0-180°、0-360°

sg90舵机

红色:VCC 灰色:GND 黄色:PWM信号

怎么控制舵机

向黄色信号线“灌入”PWM信号。
PWM波的频率不能太高,大约50HZ,即周期=1/频率=1/50=0.02s,20ms左右
数据:
0.5ms-------------0度; 2.5% 对应函数中占空比为250
1.0ms------------45度; 5.0% 对应函数中占空比为500
1.5ms------------90度; 7.5% 对应函数中占空比为750
2.0ms-----------135度; 10.0% 对应函数中占空比为1000
2.5ms-----------180度; 12.5% 对应函数中占空比为1250
定时器需要定时20ms, 关心的单位0.5ms, 40个的0.5ms,初值0.5m cnt++
1s = 10ms * 100
20ms = 0.5ms * 40

舵机工作原理

编程实现

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

sbit sg90 = P2^7;				//定义舵机IO口为P2^7

char cnt = 0;					
char angel;						//定义角度

void Timer0Init()
{
	TMOD &= 0xF0;				
	TMOD |= 0x01;				//配置定时器0工作模式为16位计数
	TL0 = 0x33;
	TH0 = 0xFE;					//定义0.5ms初值
	TF0 = 0;					//定时器0溢出标志
	TR0 = 1;					//开启定时器
	EA = 1;						//开启总中断
	ET0 = 1;					//开启定时器0中断
}

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

	_nop_();
	i = 15;
	j = 2;
	k = 235;
	do
	{
		do
		{
			while (--k);
		} while (--j);
	} while (--i);
}

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

	_nop_();
	i = 3;
	j = 26;
	k = 223;
	do
	{
		do
		{
			while (--k);
		} while (--j);
	} while (--i);
}

void Rotate_1()					//定义舵机旋转0°
{
	angel = 1;
	cnt = 0;
}

void Rotate_4()					//定义舵机旋转135°
{
	angel = 4;
	cnt = 0;
}

void SG90_Init()				//舵机IO口,角度初始化
{
	sg90 = 1;
	angel = 1;
	cnt = 0;
}

void main()
{
	Delay300ms();				//模拟PWM脉冲,给300ms延时稳定硬件
	
	SG90_Init();
	Timer0Init();
	
	while(1)
	{
		Rotate_1();
		Delay2000ms();
		Rotate_4();
		Delay2000ms();
	}							//使舵机的角度一直在0°和135°之间切换
}

void Timer0 () interrupt 1
{
	cnt++;						//每执行一次中断函数,cnt++一次
	TL0 = 0x33;				
	TH0 = 0xFE;					//执行一次重新赋值
	if(cnt < angel)
	{
		sg90 = 1;
	}
	else
	{
		sg90 = 0;
	}							//控制单片机给P2^7口发送高低电平模拟PWM脉冲的形成
	if(cnt == 40)				//当cnt=40时经过了20ms,cnt重新开始计数
	{
		cnt = 0;
		sg90 = 1;
	}
}

玩转SG90舵机

/*把之前学过433M无线模块,按键也加进去玩*/
#include <reg52.h>
#include <intrins.h>

sbit sg90 = P2^7;
sbit KEY1 = P2^1;
sbit KEY2 = P2^0;
sbit D0_A = P0^0;
sbit D1_B = P0^1;
sbit D2_C = P0^2;
sbit D3_D = P0^3;

char cnt = 0;
char angel;

void Timer0Init()		//定时器0相关初始化
{
	TMOD &= 0xF0;
	TMOD |= 0x01;
	TL0 = 0x33;
	TH0 = 0xFE;
	TF0 = 0;
	TR0 = 1;
	EA = 1;
	ET0 = 1;
}

void Timer1Init()		//定时器1相关初始化
{
    TMOD &= 0x0F;
    TMOD |= 0x10;		//设置定时器1的工作模式
    ET1 = 1;			//上边已经开启了总中断EA,所以这里只需开启定时器1的中断ET1 = 1
    TF1 = 0;			//定时器1溢出标志
    TR1 = 1;			//定时器1运行控制位
}

void SG90_Init()	//舵机相关初始化
{
	sg90 = 1;		//上电舵机处于高电平
	angel = 1;		//角度是0°
	cnt = 0;		//cnt从0开始计数
}

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

	i = 90;
	j = 163;
	do
	{
		while (--j);
	} while (--i);
}

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

	_nop_();
	i = 3;
	j = 26;
	k = 223;
	do
	{
		do
		{
			while (--k);
		} while (--j);
	} while (--i);
}

void Rotate_1()		//旋转0°
{
	angel = 1;
	cnt = 0;
}

void Rotate_2()		//旋转45°
{
	angel = 2;
	cnt = 0;
}

void Rotate_3()		//旋转90°
{
	angel = 3;
	cnt = 0;
}

void Rotate_4()		//旋转135°
{
	angel = 4;
	cnt = 0;
}

void Rotate_5()		//旋转180°
{
	angel = 5;
	cnt = 0;
}

void KEY1_Rotate()			//按键1相关设置
{
    if(KEY1 == 0)			//按键1按下,可能是误触,延时一段时间再进行判断
    {
        Delay50ms();		//软件消抖
        if(KEY1 == 0)
        {
           Rotate_1();		//当检测到按键1确实是被按下后,旋转0°
        }
    }
}

void KEY2_Rotate()			//按键2相关设置
{
    if(KEY2 == 0)			//操作同上
    {
        Delay50ms();
        if(KEY2 == 0)
        {
            Rotate_4();		//当检测到按键2确实是被按下后,旋转135°
        }
    }
}

void main()
{
	Delay300ms();
	
	SG90_Init();
	Timer0Init();
	Timer1Init();
	
	while(1)
	{
         KEY1_Rotate();
         KEY2_Rotate();
	}
}

void Timer0 () interrupt 1
{
	cnt++;						//每执行一次中断函数,cnt++一次
	TL0 = 0x33;				
	TH0 = 0xFE;					//执行一次重新赋值
	if(cnt < angel)
	{
		sg90 = 1;
	}
	else
	{
		sg90 = 0;
	}							//控制单片机给P2^7口发送高低电平模拟PWM脉冲的形成
	if(cnt == 40)				//当cnt=40时经过了20ms,cnt重新开始计数
	{
		cnt = 0;
		sg90 = 1;
	}
}

void Timer1 () interrupt 3		//定时器1相关中断函数
{
	if(D0_A == 1)				//当遥控器的按键A被按下后,旋转45°
	{
		Rotate_2();
	}
	if(D1_B == 1)				//当遥控器的按键B被按下后,旋转90°
	{
		Rotate_3();
	}
	if(D2_C == 1)				//当遥控器的按键C被按下后,旋转135°
	{
		Rotate_4();
	}
	if(D3_D == 1)				//当遥控器的按键D被按下后,旋转180°
	{
		Rotate_5();
	}
}								//当每次遥控器按键被按下后,可以按按键1回到初始0°

超声波测距

简介

型号:HC-SR04

引脚:VCC和GND接开发板的5V和GND,Trig作为发送波的引脚,Echo作为接收波的引脚。

HC-SR04

超声波测距模块是用来测量距离的一种产品,通过发送和收超声波,利用时间差和声音传播速度,
计算出模块到前方障碍物的距离。


如何使用

  • 怎么让它发送波
    Trig ,给Trig端口至少10us的高电平
  • 怎么知道它开始发了
    Echo信号,由低电平跳转到高电平,表示开始发送波
  • 怎么知道接收了返回波
    Echo,由高电平跳转回低电平,表示波回来了
  • 怎么算时间
    Echo引脚维持高电平的时间!
    波发出去的那一下,开始启动定时器
    波回来的拿一下,我们开始停止定时器,计算出中间经过多少时间
  • 怎么算距离
    距离 = 速度 (340m/s)* 时间/2

超声波的时序图

超声波时序图

编程实现

/*距离小于10cm,LED1亮,LED2灭,风扇开始转,反之相反现象,电机用L9110电机驱动模块*/

#include <reg52.h>

sbit LED1 	 = P3^7;
sbit LED2 	 = P3^6;
sbit Trig  	 = P0^5;
sbit Echo	 = P0^4;
sbit Motor_A = P0^6;
sbit Motor_B = P0^7;	//定义IO口

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

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

void Timer1Init()		//定时器1相关初始化
{
	TMOD &= 0x0F;		
	TMOD |= 0x10;		//配置定时器1为16位计数模式
	TL1 = 0;
	TH1 = 0;			//从0开始计数
}

void MotorInit()			//电机初始化
{
   //电机定义两个IO口,当两个IO电平不相同时,电机就会转动,正转和反转与所给IO口的电平有关
	Motor_A = 1;		
	Motor_B = 1;		//上电电机不转动
}

void HC_START()			//给Trig一个10us的高电平
{
	Trig = 0;			
	Trig = 1;
	Delay10us();
	Trig = 0;			//先让Trig处于低电平,然后给一个高电平维持10us,再跳转回低电平
}

void Nearby_Handler()	//当dis<10 的时候的操作
{
	LED1 = 0;
	LED2 = 1;			//距离小于10,LED1亮,LED2灭
	Motor_A = 0;
	Motor_B = 1;		//电机开始转动
}

void Far_Handler()		//当dis>=10 的时候的操作
{
	LED1 = 1;
	LED2 = 0;			//距离大于或等于10,LED1灭,LED2亮
	Motor_A = 1;
	Motor_B = 1;
}

double Get_distance()	//测量距离
{
	double time;
	
	TL1 = 0;			//每次调用都让定时器1从0开始计数
	TH1 = 0;
	
	HC_START();			//给Trig10us的高电平,开始发送波
	
	while(Echo == 0);	
	TR1 = 1;			//Echo由低电平跳转到高电平代表开始发送波,这时启动定时器1开始计数
	while(Echo == 1);
	TR1 = 0;			//Echo由高电平跳转到低电平表示接收到波,这时定时器1停止计数
	
	time = (TH1*256+TL1)*1.085;	//总共计数高位加低位*1.085us/下 = 超声波在空气中经过的时间(来回)
    
    /*
    	十进制2左移1位,变成20。相当于乘以10
		二进制1左移1位,变成10(2)。相当于乘以2的1次方,左移8位,乘以2的8次方=256;
    */
	
	return (time * 0.017);	//距离 = 时间(来回)* 速度/2
}

void main()
{
	double dis;
	
	Timer1Init();
	MotorInit();
    
	while(1)
	{
		dis = Get_distance();
		if(dis < 10)
		{
			Nearby_Handler();		
		}	
		else
		{
			Far_Handler();	
		}
	}
}

感应开盖垃圾桶

项目概述

  • 检测靠近时,垃圾桶自动开盖并伴随滴一声,2秒后关盖
  • 发生震动时,垃圾桶自动开盖并伴随滴一声,2秒后关盖
  • 按下按键时,垃圾桶自动开盖并伴随滴一声,2秒后关盖
  • 硬件说明
    SG90舵机,超声波模块,震动传感器,蜂鸣器
  • 接线说明
    舵机控制口 P2.7;超声波Trig接 P0.1 ,Echo接 P0.0 ;蜂鸣器接 P0.2 口; 震动传感器接 P3.2口(外部中断0)

编程实现

开发步骤:

  1. 舵机和超声波代码整合
    舵机用定时器0
    超声波用定时器1
    实现物体靠近后,自动开盖,2秒后关盖
  2. 查询的方式添加按键控制
  3. 查询的方式添加震动控制
  4. 使用外部中断0配合震动控制

代码:

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

sbit LED1 	 = P3^7;
sbit LED2 	 = P3^6;
sbit sg90 	 = P2^7;
sbit Trig 	 = P0^1;
sbit Echo 	 = P0^0;
sbit KEY1 	 = P2^1;
sbit BEEP	 = P0^2;
sbit vibrate = P3^2;		//定义IO口

char cnt = 0;				
char angel;
char angel_back;		//定义一个备份来保存角度值
char mark = 0;			//定义震动传感器响应标志位

void Timer0Init()		//定时器0用来控制舵机的相关初始化
{
    TMOD &= 0xF0;
    TMOD |= 0x01;
    TL0 = 0x33;
    TH0 = 0xFE;
    TF0 = 0;
    TR0 = 1;
    EA = 1;
    ET0 = 1;
}

void Timer1Init()		//定时器1用来控制超声波的相关初始化
{
    TMOD &= 0x0F;
    TMOD |= 0x10;
    TL1 = 0;
    TH1 = 0;
}

void INT0Init()			//使用外部中断0来控制震动传感器
{
    EX0 = 1;			//允许外部中断0中断
    IT0 = 0;			//IT0 = 0表示低电平触发
}

void SG90_Init()		//舵机相关初始化
{
    sg90 = 1;
    angel = 1;
    cnt = 0;
}

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

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

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

	_nop_();
	i = 15;
	j = 2;
	k = 235;
	do
	{
		do
		{
			while (--k);
		} while (--j);
	} while (--i);
}

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

	_nop_();
	i = 3;
	j = 26;
	k = 223;
	do
	{
		do
		{
			while (--k);
		} while (--j);
	} while (--i);
}

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

	i = 180;
	j = 73;
	do
	{
		while (--j);
	} while (--i);
}


void HC_START()			//给Trig一个10us的高电平
{
	Trig = 0;			
	Trig = 1;
	Delay10us();
	Trig = 0;			//先让Trig处于低电平,然后给一个高电平维持10us,再跳转回低电平
}

double Get_distance()	//测量距离
{
	double time;
	
	TL1 = 0;			//每次调用都让定时器1从0开始计数
	TH1 = 0;
	
	HC_START();			//给Trig10us的高电平,开始发送波
	
	while(Echo == 0);	
	TR1 = 1;			//Echo由低电平跳转到高电平代表开始发送波,这时启动定时器1开始计数
	while(Echo == 1);
	TR1 = 0;			//Echo由高电平跳转到低电平表示接收到波,这时定时器1停止计数
	
	time = (TH1*256+TL1)*1.085;	//总共计数高位加低位*1.085us/下 = 超声波在空气中经过的时间(来回)
    
    /*
    	十进制2左移1位,变成20。相当于乘以10
		二进制1左移1位,变成10(2)。相当于乘以2的1次方,左移8位,乘以2的8次方=256;
    */
	
	return (time * 0.017);	//距离 = 时间(来回)* 速度/2
}

void OpenLight()			//开盖时LED1亮,LED2灭
{
    LED1 = 0;
    LED2 = 1;
}

void CloseLight()			//关盖时LED1灭,LED2亮
{
    LED1 = 1;
    LED2 = 0;
}

void OpenLid()				//当角度旋转135°时开盖
{
    /*
    	如果备份角度和角度不相同的话,那就执行括号里的,如果相同,跳出if,防止舵机一直判断cnt的值
    	导致舵机抽搐
    */
    angel = 4;				
    if(angel_back != angel)	
    {
        cnt = 0;
        BEEP = 0;
        Delay300ms();
        BEEP = 1;
        Delay2000ms();		
    }
    angel_back = angel;			//上电执行一次以后,将angel的值备份,如果一直满足舵机旋转135°的条件,就								不再判断cnt的值
}

void CloseLid()
{
    angel = 1;
    angel_back = angel;			//将angel的值备份,防止因angel的值改变导致舵机抽搐
    cnt = 0;
    Delay100ms();
}

void main()
{
    double dis;
    
    Timer0Init();
    Timer1Init();
    INT0Init();
    SG90_Init();
    while(1)
    {
        dis = Get_distance();
        if(dis < 10 || KEY1 == 0 || mark == 1)		
        {	
            //如果距离小于10或者按键1被按下或者mark的值等于1的时候,垃圾桶开盖,否则关盖
            OpenLight();
            OpenLid();
            mark = 0;		//将mark重新赋值
        }
   		else
        {
            CloseLight();
            CloseLid();
        }
    }
}

void Timer0 () interrupt 1
{
	cnt++;						//每执行一次中断函数,cnt++一次
	TL0 = 0x33;				
	TH0 = 0xFE;					//执行一次重新赋值
	if(cnt < angel)
	{
		sg90 = 1;
	}
	else
	{
		sg90 = 0;
	}							//控制单片机给P2^7口发送高低电平模拟PWM脉冲的形成
	if(cnt == 40)				//当cnt=40时经过了20ms,cnt重新开始计数
	{
		cnt = 0;
		sg90 = 1;
	}
}

void INT0_Handler () interrupt 0
{
    mark = 1;		//使用外部中断0改变mark的值,使之成为垃圾桶开盖的条件
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

日落星野

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

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

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

打赏作者

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

抵扣说明:

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

余额充值