当手动控制时:可以控制电机手动反转,手动正转,并伴随有正反转的LED灯亮。
并且加有正反转限位开关,当按下限位开关后,电机将不能相同方向的正反转。
调整为自动模式时:根据检测的光照强度和温度来控制电机的运动。
达到百叶窗的效果。
Proteus仿真图:
单片机程序:
- /*****头文件声明*****/
- #include <reg51.h>
- #include "lcd.h"
- #include "ds1302.h"
- #include <intrins.h>
- /*数据类型声明定义*/
- typedef unsigned int u16;
- typedef unsigned char u8;
- /*******I/O口定义*******/
- sbit IN1 = P3^0;
- sbit IN2 = P3^1;
- sbit LED1 = P3^2;
- sbit LED2 = P3^3;
- sbit LED3 = P3^4;
- sbit K1 = P3^5;
- sbit K2 = P3^6;
- sbit K3 = P3^7;
- sbit K4 = P1^5;
- sbit MOTOR = P2^4;
- sbit Data = P2^0;//定义DHT11数据线
- sbit CS = P1^0;//片选使能端
- sbit DI = P1^1;//数据信号输入端
- sbit DO = P1^1;//数据输出端
- sbit CLK = P1^2;//时钟脉冲
- sbit YS = P1^3;
- /*******变量定义*******/
- u8 TEMP,HUMI;//DHT11采集值
- u16 Flag_num;
- u16 Flag_n=3;
- bit Flag_t;
- u16 LDR_Val;//测量的电压值
- bit Flag_Auto;
- bit Flag_DHT;
- bit Flag_MOTOR;
- bit Flag_ZHUAN;
- /*******程序段*******/
- void delay(u16 i)//延时函数
- {
- while(i--);
- }
- void DHT11_delay_ms(u16 z)
- {
- u16 i,j;
- for(i=z;i>0;i--)
- for(j=110;j>0;j--);
- }
- void DHT11_delay_us(u8 n)
- {
- while(--n);
- }
- void DHT11_start()
- {
- Data=1;
- DHT11_delay_us(2);
- Data=0;
- DHT11_delay_ms(30); //延时18ms以上
- Data=1;
- DHT11_delay_us(30);
- }
- u8 DHT11_rec_byte() //接收一个字节
- {
- u8 i,dat=0;
- for(i=0;i<8;i++) //从高到低依次接收8位数据
- {
- while(!Data); ////等待50us低电平过去
- DHT11_delay_us(8); //延时60us,如果还为高则数据为1,否则为0
- dat<<=1; //移位使正确接收8位数据,数据为0时直接移位
- if(Data==1) //数据为1时,使dat加1来接收数据1
- dat+=1;
- while(Data); //等待数据线拉低
- }
- return dat;
- }
- void DHT11_Receive() //接收40位的数据
- {
- u8 R_H,R_L,T_H,T_L,RH,RL,TH,TL,revise;
- DHT11_start();
- if(Data==0)
- {
- while(Data==0); //等待拉高
- DHT11_delay_us(40); //拉高后延时80us
- R_H=DHT11_rec_byte(); //接收湿度高八位
- R_L=DHT11_rec_byte(); //接收湿度低八位
- T_H=DHT11_rec_byte(); //接收温度高八位
- T_L=DHT11_rec_byte(); //接收温度低八位
- revise=DHT11_rec_byte(); //接收校正位
- DHT11_delay_us(25); //结束
- if((R_H+R_L+T_H+T_L)==revise) //校正
- {
- RH=R_H;
- RL=R_L;
- TH=T_H;
- TL=T_L;
- }
- TEMP=TH;//温度
- HUMI=RH;//湿度
- }
- }
- /***读ADC0832函数***/
- unsigned int Get_ADC0832(unsigned char CHAANEL) //AD转换,返回结果
- {
- unsigned long Volt;//测量的电压值
- u8 i=0;
- u8 j;
- u16 dat=0; //正向输入
- u8 ndat=0; //反向输入
- if(CHAANEL==0)CHAANEL=2;
- if(CHAANEL==1)CHAANEL=3;
- DI=1; _nop_();_nop_(); //发起始位,固定为1(1位)
- CS=0; _nop_();_nop_(); //拉低CS端,让ADC0832使能
- CLK=1;_nop_();_nop_(); //拉高CLK端,DI端的数据移入ADC0832内部的多路移位寄存器
- CLK=0;_nop_();_nop_(); //拉低CLK端,形成下降沿1,第一个周期开始
- CLK=1; //拉高CLK端,在第一个时钟周期内,DI为高电平,表示启动位
- DI=CHAANEL&0x1;_nop_();_nop_(); //假设选取通道0,则10&01=0,即SGL/DIF=0,为差分输入(2位)
- CLK=0;_nop_();_nop_(); //拉低CLK端,形成下降沿2,第二个周期开始
- CLK=1; //拉高CLK端
- DI=(CHAANEL>>1)&0x1;_nop_();_nop_(); //选取通道0,则01&01=1,ODD/EVEN=1,表示通道0
- CLK=0; //拉低CLK端
- DI=1;_nop_();_nop_();
- dat=0;
- for(i=0;i<8;i++) //每一个CLK下降沿输出一位数,先输出高位
- {
- dat|=DO;
- CLK=1;_nop_();_nop_();
- CLK=0;_nop_();_nop_();
- dat<<=1;
- if(i==7)dat|=DO;
- }
- for(i=0;i<8;i++) //每一个CLK下降沿输出一位数,先输出低位
- {
- j=0;
- j=j|DO; //收数据
- CLK=1;_nop_();_nop_();
- CLK=0;_nop_();_nop_(); //形成一次时钟脉冲
- j=j<<7;
- ndat=ndat|j;
- if(i<7)ndat>>=1;
- }
- CS=1; //拉低CS端口
- CLK=0; //拉低CLK端口
- DO=1; //拉高数据端
- dat<<=8;
- dat|=ndat;
- Volt=dat*0.0763;//8位
- return(Volt); //返回数据
- }
- void Key_Control(void)
- {
- }
- void Conotrol(void)
- {
- }
- void Init_Timer0()
- {
- TMOD|=0X01;//选择为定时器0模式,工作方式1,仅用TR0打开启动。
- TH0 = 0xD8;//给定时器赋初值,定时10ms
- TL0 = 0xF0;
- ET0=1;//打开定时器1中断允许
- EA=1;//打开总中断
- TR0=1;//打开定时器
- }
- void main(void)
- {
- LcdInit();
- Init_Timer0();
- MOTOR=1;
- LDR_Val=Get_ADC0832(0);//关照检测
- Flag_num=LDR_Val;
- LcdWriteCom(0x01);
- DisplayListChar(0,0,"T:"); DisplayOneChar(6,0,'C'); DisplayListChar(8,0,"H:"); DisplayOneChar(14,0,'%');//T:25C H:85%
- DisplayListChar(0,1,"LUX:");
- while(1)
- {
- Key_Control();
- Conotrol();
- if(Flag_DHT == 1)
- {
- TR0=0;
- DHT11_Receive();//温湿度采集
- DisplayOneChar(3,0,TEMP/10+'0');
- DisplayOneChar(4,0,TEMP%10+'0');
- DisplayOneChar(11,0,HUMI/10+'0');
- DisplayOneChar(12,0,HUMI%10+'0');
- LDR_Val=Get_ADC0832(0);//关照检测
- DisplayOneChar(4,1,LDR_Val/1000+'0');
- DisplayOneChar(5,1,LDR_Val%1000/100+'0');
- DisplayOneChar(6,1,LDR_Val%100/10+'0');
- DisplayOneChar(7,1,LDR_Val%10+'0');
- TR0=1;
- }
- if(YS == 0)
- {
- DisplayListChar(9,1,"No Auto");
- if(K1 == 0)
- {
- Flag_ZHUAN=1;//正转
- if(Flag_n==1)
- {
- Flag_n=Flag_n;
- }else{Flag_n=3;Flag_MOTOR=1;
- }
-
- while(!K1);
- }
- if(K2 == 0)
- {
- Flag_ZHUAN=0;//反转
- if(Flag_n==0)
- {
- Flag_n=Flag_n;
- }else{Flag_n=3;Flag_MOTOR=1;
- }
- while(!K2);
- }
- if(K3 == 0)
- {
- Flag_MOTOR=0;
- Flag_n=0;
- while(!K3);
- }
- if(K4 == 0)
- {
- Flag_n=1;
- Flag_MOTOR=0;
-
- while(!K4);
- }
- }else{
- DisplayListChar(9,1,"!! Auto");
- if(Flag_num!=LDR_Val)
- {Flag_n=3;
- if(Flag_num>LDR_Val)
- {
- Flag_MOTOR=1;
- Flag_ZHUAN=0;//反转
- }
- if(Flag_num<LDR_Val)
- {
- Flag_MOTOR=1;
- Flag_ZHUAN=1;//正转
- }
- Flag_num=LDR_Val;
- }
- }
-
- }
- }
- void Timer0() interrupt 1//定时器0的中断函数
- {
- static u16 p,t;
- TH0 = 0xD8;//定时10ms
- TL0 = 0xF0;
- p++;
- if(P == 50)
- {
- p=0;
- Flag_DHT=1;
- }
- if(Flag_MOTOR == 1)//旋转信号
- {
- t++;
- if(Flag_ZHUAN == 0&&(Flag_n==3||Flag_n==0))
- {
- LED1=1;LED2=0; LED3=1;
- IN1 = 0;IN2 = 1;//反转
- }else{
- LED1=0;LED2=1;LED3=1;
- IN1 = 1;IN2 = 0;//正转
- }
- if(YS == 0)
- {
- if(t==100)
- {
- t=0;
- LED3=0;
- LED1=1;LED2=1;
- IN1 = 0;IN2 = 0;//停止
- Flag_MOTOR=0;
- }
- }else
- {
- if(t==10)
- {
- t=0;
- LED3=0;
- LED1=1;LED2=1;
- IN1 = 0;IN2 = 0;//停止
- Flag_MOTOR=0;
- }
- }
- }
- else{
- t=0;
- LED3=0;
- LED1=1;LED2=1;
- IN1 = 0;IN2 = 0;//停止
- Flag_MOTOR=0;
- }
- }
复制代码 Keil代码与Proteus8.13仿真下载:
百叶扇带DHT11.7z
(483.04 KB, 下载次数: 95)
|