找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 1190|回复: 0
打印 上一主题 下一主题
收起左侧

51单片机ADC0832采集光照强度,DHT11采集温度湿度,分为手动自动控制电机正反转仿真程序

[复制链接]
跳转到指定楼层
楼主
当手动控制时:可以控制电机手动反转,手动正转,并伴随有正反转的LED灯亮。
并且加有正反转限位开关,当按下限位开关后,电机将不能相同方向的正反转。

调整为自动模式时:根据检测的光照强度和温度来控制电机的运动。

达到百叶窗的效果。
Proteus仿真图:





单片机程序:
  1. /*****头文件声明*****/
  2. #include <reg51.h>   
  3. #include "lcd.h"
  4. #include "ds1302.h"
  5. #include <intrins.h>
  6. /*数据类型声明定义*/
  7. typedef unsigned int u16;      
  8. typedef unsigned char u8;
  9. /*******I/O口定义*******/
  10. sbit IN1 = P3^0;
  11. sbit IN2 = P3^1;
  12. sbit LED1 = P3^2;
  13. sbit LED2 = P3^3;
  14. sbit LED3 = P3^4;
  15. sbit K1 = P3^5;
  16. sbit K2 = P3^6;
  17. sbit K3 = P3^7;
  18. sbit K4 = P1^5;

  19. sbit MOTOR = P2^4;
  20. sbit Data = P2^0;//定义DHT11数据线
  21. sbit CS  = P1^0;//片选使能端
  22. sbit DI  = P1^1;//数据信号输入端
  23. sbit DO  = P1^1;//数据输出端
  24. sbit CLK = P1^2;//时钟脉冲
  25. sbit YS = P1^3;
  26. /*******变量定义*******/
  27. u8 TEMP,HUMI;//DHT11采集值
  28. u16 Flag_num;
  29. u16 Flag_n=3;
  30. bit Flag_t;
  31. u16 LDR_Val;//测量的电压值
  32. bit Flag_Auto;
  33. bit Flag_DHT;
  34. bit Flag_MOTOR;
  35. bit Flag_ZHUAN;

  36. /*******程序段*******/
  37. void delay(u16 i)//延时函数
  38. {
  39.     while(i--);   
  40. }
  41. void DHT11_delay_ms(u16 z)
  42. {
  43.    u16 i,j;
  44.    for(i=z;i>0;i--)
  45.       for(j=110;j>0;j--);
  46. }
  47. void DHT11_delay_us(u8 n)
  48. {
  49.     while(--n);
  50. }
  51. void DHT11_start()
  52. {
  53.    Data=1;
  54.    DHT11_delay_us(2);
  55.    Data=0;
  56.    DHT11_delay_ms(30);   //延时18ms以上
  57.    Data=1;
  58.    DHT11_delay_us(30);
  59. }
  60. u8 DHT11_rec_byte()      //接收一个字节
  61. {
  62.    u8 i,dat=0;
  63.    for(i=0;i<8;i++)    //从高到低依次接收8位数据
  64.    {         
  65.       while(!Data);   ////等待50us低电平过去
  66.       DHT11_delay_us(8);     //延时60us,如果还为高则数据为1,否则为0
  67.       dat<<=1;           //移位使正确接收8位数据,数据为0时直接移位
  68.       if(Data==1)    //数据为1时,使dat加1来接收数据1
  69.          dat+=1;
  70.       while(Data);  //等待数据线拉低   
  71.     }  
  72.     return dat;
  73. }

  74. void DHT11_Receive()      //接收40位的数据
  75. {
  76.     u8 R_H,R_L,T_H,T_L,RH,RL,TH,TL,revise;
  77.     DHT11_start();
  78.     if(Data==0)
  79.     {
  80.         while(Data==0);   //等待拉高   
  81.         DHT11_delay_us(40);  //拉高后延时80us
  82.         R_H=DHT11_rec_byte();    //接收湿度高八位
  83.         R_L=DHT11_rec_byte();    //接收湿度低八位
  84.         T_H=DHT11_rec_byte();    //接收温度高八位
  85.         T_L=DHT11_rec_byte();    //接收温度低八位
  86.         revise=DHT11_rec_byte(); //接收校正位
  87.         DHT11_delay_us(25);    //结束
  88.         if((R_H+R_L+T_H+T_L)==revise)      //校正
  89.         {
  90.             RH=R_H;
  91.             RL=R_L;
  92.             TH=T_H;
  93.             TL=T_L;
  94.         }
  95.         TEMP=TH;//温度
  96.         HUMI=RH;//湿度
  97.     }
  98. }
  99. /***读ADC0832函数***/
  100. unsigned int Get_ADC0832(unsigned char CHAANEL)  //AD转换,返回结果
  101. {
  102.     unsigned long Volt;//测量的电压值
  103.     u8 i=0;  
  104.     u8 j;
  105.     u16 dat=0;   //正向输入
  106.     u8 ndat=0;   //反向输入
  107.     if(CHAANEL==0)CHAANEL=2;   
  108.     if(CHAANEL==1)CHAANEL=3;   
  109.     DI=1; _nop_();_nop_();     //发起始位,固定为1(1位)
  110.     CS=0; _nop_();_nop_();     //拉低CS端,让ADC0832使能
  111.     CLK=1;_nop_();_nop_();   //拉高CLK端,DI端的数据移入ADC0832内部的多路移位寄存器
  112.     CLK=0;_nop_();_nop_();    //拉低CLK端,形成下降沿1,第一个周期开始
  113.     CLK=1;           //拉高CLK端,在第一个时钟周期内,DI为高电平,表示启动位
  114.     DI=CHAANEL&0x1;_nop_();_nop_(); //假设选取通道0,则10&01=0,即SGL/DIF=0,为差分输入(2位)
  115.     CLK=0;_nop_();_nop_();    //拉低CLK端,形成下降沿2,第二个周期开始
  116.     CLK=1;                                //拉高CLK端
  117.     DI=(CHAANEL>>1)&0x1;_nop_();_nop_();  //选取通道0,则01&01=1,ODD/EVEN=1,表示通道0
  118.     CLK=0; //拉低CLK端
  119.     DI=1;_nop_();_nop_();      
  120.     dat=0;
  121.     for(i=0;i<8;i++)   //每一个CLK下降沿输出一位数,先输出高位
  122.     {
  123.      dat|=DO;
  124.      CLK=1;_nop_();_nop_();
  125.      CLK=0;_nop_();_nop_();   
  126.      dat<<=1;
  127.      if(i==7)dat|=DO;
  128.     }   
  129.     for(i=0;i<8;i++)  //每一个CLK下降沿输出一位数,先输出低位
  130.     {
  131.      j=0;
  132.      j=j|DO;    //收数据
  133.      CLK=1;_nop_();_nop_();
  134.      CLK=0;_nop_();_nop_();    //形成一次时钟脉冲
  135.      j=j<<7;
  136.      ndat=ndat|j;
  137.      if(i<7)ndat>>=1;
  138.     }
  139.     CS=1;     //拉低CS端口
  140.     CLK=0;    //拉低CLK端口
  141.     DO=1;     //拉高数据端
  142.     dat<<=8;
  143.     dat|=ndat;
  144.     Volt=dat*0.0763;//8位
  145.     return(Volt); //返回数据
  146. }
  147. void Key_Control(void)
  148. {
  149. }
  150. void Conotrol(void)
  151. {
  152. }
  153. void Init_Timer0()
  154. {
  155.     TMOD|=0X01;//选择为定时器0模式,工作方式1,仅用TR0打开启动。
  156.     TH0 = 0xD8;//给定时器赋初值,定时10ms
  157.   TL0 = 0xF0;
  158.     ET0=1;//打开定时器1中断允许
  159.     EA=1;//打开总中断
  160.     TR0=1;//打开定时器        
  161. }
  162. void main(void)
  163. {
  164.     LcdInit();
  165.     Init_Timer0();
  166.     MOTOR=1;
  167.     LDR_Val=Get_ADC0832(0);//关照检测
  168.     Flag_num=LDR_Val;
  169.     LcdWriteCom(0x01);
  170.     DisplayListChar(0,0,"T:"); DisplayOneChar(6,0,'C'); DisplayListChar(8,0,"H:"); DisplayOneChar(14,0,'%');//T:25C H:85%
  171.     DisplayListChar(0,1,"LUX:");
  172.     while(1)
  173.     {
  174.         Key_Control();
  175.         Conotrol();
  176.         if(Flag_DHT == 1)
  177.         {
  178.             TR0=0;        
  179.                 DHT11_Receive();//温湿度采集
  180.                     DisplayOneChar(3,0,TEMP/10+'0');
  181.                     DisplayOneChar(4,0,TEMP%10+'0');
  182.                     DisplayOneChar(11,0,HUMI/10+'0');
  183.                     DisplayOneChar(12,0,HUMI%10+'0');
  184.                 LDR_Val=Get_ADC0832(0);//关照检测
  185.                     DisplayOneChar(4,1,LDR_Val/1000+'0');
  186.                     DisplayOneChar(5,1,LDR_Val%1000/100+'0');
  187.                     DisplayOneChar(6,1,LDR_Val%100/10+'0');
  188.                     DisplayOneChar(7,1,LDR_Val%10+'0');
  189.             TR0=1;
  190.         }
  191.         if(YS == 0)
  192.         {
  193.             DisplayListChar(9,1,"No Auto");
  194.             if(K1 == 0)
  195.             {        
  196.                 Flag_ZHUAN=1;//正转
  197.                 if(Flag_n==1)
  198.                 {
  199.                 Flag_n=Flag_n;
  200.                 }else{Flag_n=3;Flag_MOTOR=1;   
  201.                 }
  202.                         
  203.                 while(!K1);
  204.             }
  205.                         if(K2 == 0)
  206.             {            
  207.                 Flag_ZHUAN=0;//反转
  208.                                 if(Flag_n==0)
  209.                 {
  210.                 Flag_n=Flag_n;
  211.                 }else{Flag_n=3;Flag_MOTOR=1;
  212.                 }
  213.                 while(!K2);
  214.             }
  215.     if(K3 == 0)
  216.     {        
  217.         Flag_MOTOR=0;
  218.         Flag_n=0;
  219.         while(!K3);
  220.     }
  221.         if(K4 == 0)
  222.     {        
  223.         Flag_n=1;
  224.         Flag_MOTOR=0;
  225.         
  226.         while(!K4);
  227.     }
  228.         }else{
  229.             DisplayListChar(9,1,"!! Auto");
  230.             if(Flag_num!=LDR_Val)
  231.             {Flag_n=3;
  232.                 if(Flag_num>LDR_Val)
  233.                 {
  234.                                 Flag_MOTOR=1;
  235.                 Flag_ZHUAN=0;//反转
  236.                 }
  237.                                 if(Flag_num<LDR_Val)
  238.                 {
  239.                                     Flag_MOTOR=1;   
  240.                 Flag_ZHUAN=1;//正转
  241.                 }
  242.                 Flag_num=LDR_Val;
  243.                 }
  244.         }
  245.         
  246.     }               
  247. }
  248. void Timer0() interrupt 1//定时器0的中断函数
  249. {
  250.     static u16 p,t;
  251.     TH0 = 0xD8;//定时10ms
  252.     TL0 = 0xF0;
  253.     p++;
  254.     if(P == 50)
  255.     {
  256.         p=0;
  257.         Flag_DHT=1;
  258.     }
  259.     if(Flag_MOTOR == 1)//旋转信号
  260.     {
  261.         t++;
  262.         if(Flag_ZHUAN == 0&&(Flag_n==3||Flag_n==0))
  263.         {
  264.             LED1=1;LED2=0;    LED3=1;
  265.             IN1 = 0;IN2 = 1;//反转
  266.         }else{
  267.             LED1=0;LED2=1;LED3=1;
  268.             IN1 = 1;IN2 = 0;//正转
  269.         }
  270.         if(YS == 0)
  271.         {
  272.         if(t==100)
  273.         {
  274.             t=0;
  275.             LED3=0;
  276.                 LED1=1;LED2=1;
  277.             IN1 = 0;IN2 = 0;//停止
  278.             Flag_MOTOR=0;
  279.         }
  280.                 }else
  281.         {
  282.                 if(t==10)
  283.         {
  284.             t=0;
  285.             LED3=0;
  286.                 LED1=1;LED2=1;
  287.             IN1 = 0;IN2 = 0;//停止
  288.             Flag_MOTOR=0;
  289.         }
  290.         }

  291.     }
  292.     else{
  293.             t=0;
  294.             LED3=0;
  295.             LED1=1;LED2=1;
  296.             IN1 = 0;IN2 = 0;//停止
  297.             Flag_MOTOR=0;
  298.     }

  299. }
复制代码
Keil代码与Proteus8.13仿真下载:
百叶扇带DHT11.7z (483.04 KB, 下载次数: 86)

评分

参与人数 1黑币 +50 收起 理由
admin + 50 共享资料的黑币奖励!

查看全部评分

分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏1 分享淘帖 顶 踩
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表