资讯详情

【51单片机STC89C52】舵机控制综合篇

一、项目概述

1、功能描述

按钮控制超声波模块、振动传感器SG90舵机

当检测靠近时,垃圾桶会自动打开盖子,并伴有滴水声。 2 秒后关盖
当发生振动时,垃圾桶自动打开盖子,并伴有滴水声, 2 秒后关盖
按下按钮时,垃圾桶会自动打开盖子,滴一声, 2 秒后关盖

2、硬件部分

SG90舵机、超声波模块、振动传感器、蜂鸣器

3、接线说明

舵机(PWM)信号线 —> P1.1(定时器0) 超声波HC-SR04 Trig —> P1.5 、Echo —> P1.6 (定时器1) 震动传感器 —> P3.(外部中断0) 蜂鸣器 —> P2.0

二、基础参考

【51单片机STC89C52控制定时器(中断)LED_大头1213

【51单片机STC89C52】IO口模拟PWM控制SG90舵机_大头1213

【51单片机STC89C52】HC-SR04超声模块测距_大头1213

三、部分代码

1、接线部分

sbit D5       = P3^7.//根据原理图(电路图)设备变量led1指向P3组IO口的第7口 sbit D6       = P3^6.//根据原理图(电路图),设备变量led2指向P3组IO口的第6口 sbit KEY1     = P2^1;//按键KEY1 sbit Trig     = P1^5; sbit Echo     = P1^6; sbit sg90_con = P1^1; sbit vibrate  = P3^2; sbit beep     = P2^0;

2.超声波测距

double get_distance() {   double time;   ///定时器数据清零,以便下次测距   TH1 = 0;   TL1 = 0;      //1. 让它发送波:给Trig端口至少10us的高电平   startHC();   //2. 开始发送波:Echo信号从低电平跳转到高电平   while(Echo == 0);   //   开始发送波,启动定时器   TR1 = 1;   //3. 接收返回波:Echo信号从高电平跳转到低电平   while(Echo == 1);   //   接收返回波,停止定时器   TR1 = 0;   //4. 计算时间   time = (TH1 * 256   TL1)*1.085;//us为单位   //5. 距离 = 速度 (340m/s)* 时间/2   return  (time * 0.017); }

3.舵机-定时器0中断服务函数

void Time0Handler() interrupt 1 {  cnt  ;       //统计溢出次数  ///重新给初值  TL0 = 0x33;  TH0 = 0xFE;    //控制PWM波  if(cnt < angle){   sg90_con = 1;  }else{   sg90_con = 0;  }    if(cnt == 40){    //当溢出40次时,经过了20ms   cnt = 0;         sg90_con = 1;  }   }

4.振动传感器-外部中断0

打开外部中断

void EX0_Init() {  EX0 = 1.//打开外部中断  IT0 = 0;///低电平触发 }

中断服务函数

void Ex0_Handler() interrupt 0 {  mark_vibrate = 1; }

5.开关盖函数

void openDustbin() {  char n;  angle = 3; //90度 1.5ms高电平  //舵机开盖  if(angle_bak != angle){   cnt = 0;   beep = 0;   Delay150ms();         Delay150ms();   beep = 1;   Delay2000ms();  }    angle_bak = angle;   }  void closeDustbin() {  //关盖  angle = 1; //0度  angle_bak = angle;  cnt = 0;  Delay150ms(); } 

四、整体代码

#include "reg52.h" #include "intrins.h"  sbit D5       = P3^7.//根据原理图(电路图)设备变量led1指向P3组IO口的第7口 sbit D6       = P3^6;//根据原理图(电路图),设备变量led2指向P3组IO口的第6口 sbit KEY1      = P2^1;//按键KEY1 sbit Trig     = P1^5; sbit Echo     = P1^6; sbit sg90_con = P1^1; sbit vibrate  = P3^2; sbit beep     = P2^0;  char angle; char angle_bak; char cnt = 0; char mark_vibrate = 0;  void Delay150ms()  //@11.0592MHz {  unsigned char i, j, k;   _nop_();  i = 2;  j = 13;  k = 237;  do  {   do   {    while (--k);   } while (--j);  } 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 Delay10us()  //@11.0592MHz {  unsigned char i;   i = 2;  while (--i); }  void Timer0Init(void)  //500微秒@11.0592MHz {  //AUXR &= 0x7F;    TMOD &= 0xF0; ///设置定时器模式16位  TMOD |= 0x01; //设置定时器模式  TL0 = 0x33;  //设置定时初始值0.5ms  TH0 = 0xFE;  //设置定时初始值  TF0 = 0;  //清除TF0标志  TR0 = 1;  ///定时器0开始计时  ET0 = 1;  ///打开定时器0中断  EA  = 1;  ///打开总中断EA }  void Timer1Init()  //设置定时器0工作模式1,初始值设置0开始数,不急着启动定时器 {   TMOD &= 0x0F;  //设置定时器模式  TMOD |= 0x10;  TH1 = 0;  TL1 = 0; }  void startHC() {  Trig = 0;  Trig = 1;  Delay10us();  Trig = 0; }  double get_distance() {   double time;   ///定时器数据清零,以便下次测距   TH1 = 0;   TL1 = 0;      //1. 让它发送波:给Trig端口至少10us的高电平   startHC();   //2. 开始发送波:Echo信号从低电平跳转到高电平   while(Echo == 0);   //   开始发送波,启动定时器   TR1 = 1;   //3. 接收返回波:Echo信号从高电平跳转到低电平   while(Echo == 1);   //   接收返回波,停止定时器   TR1 = 0;   //4. 计算时间   time = (TH1 * 256   TL1)*1.085;//us为单位   //5. 距离 = 速度 (340m/s)* 时间/2   return  (time * 0.017); }  void openStatusLight() {  D5 = 0;  D6 = 1; } void closeStatusLight() {  D5 = 1;  D6 = 0; }  void initSG90_0() {  angle = 1;      ///初始角度为0度,0.5ms,溢出1就是0.5ms高电平  cnt = 0;  sg90_con = 1;//一开始从高电平开始 }  void openDustbin() {  char n;  angle = 3; //90 1.5ms高电平
	//舵机开盖
	if(angle_bak != angle){
		cnt = 0;
		beep = 0;
		for(n = 0; n < 2; n++)
			Delay150ms();
		beep = 1;
		Delay2000ms();
	}
	angle_bak = angle;
}

void closeDustbin()
{
	//关盖
	angle = 1; //0度
	angle_bak = angle;
	cnt = 0;
	Delay150ms();
}

void EX0_Init()
{
	EX0 = 1;//打开外部中断
	IT0 = 0;//低电平触发
}

void main()
{
	double dis;
	
	Timer0Init();
	Timer1Init();
	EX0_Init();
	
	initSG90_0();//舵机的初始位置
	
	while(1){
		
		dis = get_distance();//超声波测距
		if(dis < 10 || KEY1 == 0 || mark_vibrate == 1){
			//开盖,灯状态,D5亮
			openStatusLight();
			openDustbin();
			mark_vibrate = 0;
		}else{
			//关盖,灯状态,D5灭
			closeStatusLight();
			closeDustbin();
		}
	}
}

void Time0Handler() interrupt 1
{
	cnt++;  					//统计溢出的次数
	//重新给初值
	TL0 = 0x33;
	TH0 = 0xFE;
	
	//控制PWM波
	if(cnt < angle){
		sg90_con = 1;
	}else{
		sg90_con = 0;
	}
	
	if(cnt == 40){				//当溢出40次,经过了20ms
		cnt = 0;  				
		sg90_con = 1;
	}		
}

void Ex0_Handler() interrupt 0
{
	mark_vibrate = 1;
}

标签: 11ea开关传感器

锐单商城拥有海量元器件数据手册IC替代型号,打造 电子元器件IC百科大全!

锐单商城 - 一站式电子元器件采购平台