找回密码
 立即注册

QQ登录

只需一步,快速开始

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

单片机教室灯光控制系统程序与Proteus仿真图(手动与自动模式)

[复制链接]
跳转到指定楼层
#
仿真原理图如下(proteus仿真工程文件可到本帖附件中下载)


单片机源程序如下:
  1. #include <reg51.h>
  2. #include <intrins.h>
  3. #define uchar unsigned char
  4. #define uint unsigned int

  5. uchar time_data[7];
  6. uchar code write_add[7]={0x8c,0x8a,0x88,0x86,0x84,0x82,0x80};       //数据的地址
  7. uchar code read_add[7]={0x8d,0x8b,0x89,0x87,0x85,0x83,0x81};

  8. uchar code table1[]="C: 00|2000/00/00";
  9. uchar code table2[]="T: 00|00:00:00 0";
  10. uchar code table3[]="                ";                         //清屏内容
  11. uchar code table4[]="  Set Real Time ";
  12. uchar code table5[]="  Set Open Time ";
  13. uchar code table6[]="   Start Time:  ";
  14. uchar code table7[]="    00:00:00    ";
  15. uchar code table8[]="    End Time:   ";
  16. uchar code table9[]="Date: 2000/00/00";
  17. uchar code table0[]="Time: 00:00:00 0";

  18. bit Adjust;                          //调节标志位,=1表示进入调节模式,=0是正常模式
  19. bit Auto_flg;                  //自动模式标志位,=1表示手动模式,=0是自动模式
  20. sbit rs=P2^7;                  //LCD1602
  21. // sbit rw=P1^1;                   //LCD1602
  22. sbit e=P2^6;                  //LCD1602
  23. sbit sck=P2^0;                  //时钟端口
  24. sbit io=P2^1;                  //时钟端口
  25. sbit rst=P2^2;                  //时钟端口
  26. sbit SELT =P1^6;          //选择键
  27. sbit ENTER=P1^7;          //确认键
  28. sbit UP   =P3^0;          //加键
  29. sbit DOWN =P3^1;          //减键
  30. sbit MODE =P3^2;          //切换按键接口
  31. sbit SWITCH=P3^3;          //手动开关
  32. sbit AUTO_LED=P2^4;          //自动模式灯接口
  33. sbit HAND_LED=P2^3;          //手动灯接口
  34. sbit LAMP1=P3^4;          //灯接口
  35. sbit LAMP2=P3^5;          //灯接口
  36. sbit LAMP3=P3^6;          //灯接口
  37. sbit LAMP4=P3^7;          //灯接口
  38. sbit LIGHT1=P1^0;          //光线检测端口
  39. sbit IN1=P1^1;
  40. sbit OUT1=P1^2;
  41. sbit DQ=P1^5;                  //温度数据口
  42. uchar Select_num;          //选择按键按下次数
  43. uchar Enter_num;          //确认按键按下次数
  44. uchar Switch_num;          //手动开关按键按下次数
  45. float Year,Month,Day,Hour,Minute,Second;                        //时间设置值
  46. uchar Week;               
  47. float Hour_H,Minute_H,Second_H;                                          //设置开始时间
  48. float Hour_L,Minute_L,Second_L;                                          //设置结束时间
  49. int Value1;                                                                                        //人数
  50. uchar IN1_flag=0;
  51. uchar OUT1_flag=0;
  52. uint Count;           //T0定时器中断计数次数
  53. uchar Miao;

  54. int temperature;                                                                        //全局变量 温度

  55. void read_rtc();

  56. /**************************************************LCD1602显示*******************************************************************/
  57. void delay1(uint z)                          //延时函数
  58. {
  59.         uint x,y;
  60.         for(x=z;x>0;x--)
  61.                 for(y=10;y>0;y--);
  62. }


  63. void init()                                                    //初始化函数
  64. {        
  65.         uchar num;
  66.         Year=17;
  67.         Month=1;
  68.         Day=1;
  69.         Hour=15;
  70.         Minute=30;
  71.         Second=50;
  72.         Week=1;
  73.         Hour_H=22;
  74.         Minute_H=0;
  75.         Second_H=0;
  76.         Hour_L=18;
  77.         Minute_L=0;
  78.         Second_L=0;
  79.         e=0;                                                    // 时序表e初始为0
  80.         write_com(0x38);                        //设置16*2显示,5*7点阵,8位数据接口
  81.         write_com(0x0c);                                //设置光标
  82.         write_com(0x06);                                //光标自动加1,光标输入方式
  83.         write_com(0x01);                                //清屏
  84.         write_com(0x80);                                //设置初始显示位置
  85.         for(num=0;num<16;num++)
  86.         {
  87.                 write_date(table1[num]);
  88.                 delay1(5);
  89.         }
  90.         write_com(0x80+0x40);
  91.         for(num=0;num<16;num++)
  92.         {
  93.                 write_date(table2[num]);
  94.                 delay1(5);
  95.         }                                          
  96. }

  97. void SetTime_dispaly(uchar add,uchar dat)         //第一个:参数的地址,第二个:参数的内容
  98. {
  99.         uchar shi,ge;
  100.         shi=dat/10;                                                        //把十位提取出来
  101.         ge=dat%10;                                                        //把个位提取出来
  102.         write_com(add);                                                    //要写的地址
  103.         write_date(0x30+shi);                                //十位的内容   1602字符库
  104.         write_date(0x30+ge);                                //个位的内容   1602字符库
  105. }

  106. void Week_dispaly(uchar add,uchar dat)        //第一个:参数的地址,第二个:参数的内容
  107. {
  108.         write_com(add);                                                //要写的地址
  109.         if (dat == 0)
  110.     {
  111.         write_date(0x30+7);                                //十位的内容   1602字符库
  112.     }
  113.     else
  114.     {
  115.         write_date(0x30+dat);                                //十位的内容   1602字符库
  116.     }

  117. }
  118. void Date_dispaly(uchar add,uchar dat)         //第一个:参数的地址,第二个:参数的内容
  119. {
  120.         uchar shi,ge;
  121.         shi=dat/16;                                                        //把十位提取出来
  122.         ge=dat%16;                                                        //把个位提取出来
  123.         write_com(add+3);                                            //要写的地址
  124.         write_date(0x30+shi);                                //十位的内容   1602字符库
  125.         write_date(0x30+ge);                                //个位的内容   1602字符库                                   
  126. }

  127. void LCD_Clean(uchar i)                                        //液晶屏清除显示
  128. {
  129.         uchar num;
  130.         if(i==1)
  131.         {
  132.                 write_com(0x80);                                //设置初始显示位置
  133.                 for(num=0;num<16;num++)                        //显示第一行内容
  134.                 {
  135.                         write_date(table3[num]);
  136.                         delay1(1);
  137.                 }
  138.         }
  139.         if(i==2)
  140.         {
  141.                 write_com(0x80+0x40);
  142.                 for(num=0;num<16;num++)                        //显示第二行内容
  143.                 {
  144.                         write_date(table3[num]);
  145.                         delay1(1);
  146.                 }
  147.         }
  148. }

  149. void LCD_Display_String(unsigned char line,unsigned char *string)
  150. {                                                                                 //液晶屏显示内容,把要显示的内容写到对应的位置
  151.         unsigned char i;
  152.         unsigned char address=0;
  153.         if(line==1)
  154.         {
  155.                 address=0x80;                                         //0X80是第1行的第1个位置  ,0x81第2位
  156.         }
  157.         else if(line==2)
  158.         {
  159.                 address=0x80+0x40;                          //0X80+0x40是第2行的第1个位置  ,0X80+0x40+1是第2行第2位
  160.         }
  161.         
  162.         for(i=0;i<16;i++)
  163.         {
  164.                 write_com(address);
  165.                 write_date(string[i]);
  166.                 address++;
  167.         }
  168. }
  169. /**********************************DS1302时钟***************************************/
  170. void Time_Display(void)
  171. {
  172.         read_rtc();
  173.         Date_dispaly(0x80+0x40+9,time_data[6]);  //显示秒
  174.         Date_dispaly(0x80+0x40+6,time_data[5]);         //显示分
  175.         Date_dispaly(0x80+0x40+3,time_data[4]);         //显示时
  176.         Date_dispaly(0x80+11,time_data[3]);                 //显示日
  177.         Date_dispaly(0x80+8,time_data[2]);                 //显示月
  178.         Week_dispaly(0x80+0x40+15,time_data[1]-1); //显示周
  179.         Date_dispaly(0x80+5,time_data[0]);                 //显示年
  180.                                            //        Year/10*16+Year%10
  181.         Hour=time_data[4]/16*10+time_data[4]%16;;
  182.         Minute=time_data[5]/16*10+time_data[5]%16;;
  183.         Second=time_data[6]/16*10+time_data[6]%16;;
  184. }


  185. void write_ds1302_byte(uchar dat)
  186. {
  187.         uchar i;
  188.         for(i=0;i<8;i++)
  189.         {
  190.                 sck=0;
  191.                 io=dat&0x01;                                           //准备数据,从最低位开始
  192.                 dat=dat>>1;
  193.                 sck=1;
  194.         }
  195. }

  196. void write_ds1302(uchar add,uchar dat)
  197. {
  198.         rst=0;
  199.         _nop_();                                                  //CPU原地踏步
  200.         sck=0;
  201.         _nop_();
  202.         rst=1;
  203.         _nop_();
  204.         write_ds1302_byte(add);                    //传地址
  205.         write_ds1302_byte(dat);                    //传数据
  206.         rst=0;                                                     //不受其他影响
  207.         _nop_();
  208.         io=1;                                                   //释放
  209.         sck=1;
  210. }


  211. void set_rtc()                                  //设置时间
  212. {
  213.         uchar i,j;
  214.         for(i=0;i<7;i++)                         //转换BCD码
  215.         {
  216.                 j=time_data[i]/10;
  217.                 time_data[i]=time_data[i]%10;
  218.                 time_data[i]=time_data[i]+j*16;
  219.         }
  220.         write_ds1302(0x8e,0x00);          //去除写保护
  221.         for(i=0;i<7;i++)
  222.         {
  223.                 write_ds1302(write_add[i],time_data[i]);
  224.         }
  225.         write_ds1302(0x8e,0x80);      //加写保护
  226. }

  227. void read_rtc()
  228. {
  229.         uchar i;
  230.         for(i=0;i<7;i++)
  231.         {
  232.                 time_data[i]=read_ds1302(read_add[i]);        //最终读出来的数 16进制
  233.         }
  234.     Year=time_data[0]/16*10+time_data[0]%16;
  235.         Month=time_data[2]/16*10+time_data[2]%16;
  236.         Day=time_data[3]/16*10+time_data[3]%16;
  237.         Hour=time_data[4]/16*10+time_data[4]%16;
  238.         Minute=time_data[5]/16*10+time_data[5]%16;
  239.         Second=time_data[6]/16*10+time_data[6]%16;
  240.         Week=time_data[1]/16*10+time_data[1]%16-1;
  241.     if (Week == 0)
  242.     {
  243.         Week = 7;
  244.     }
  245. }

  246. /*************************************************按键****************************************************************/
  247. void Keyscan(void)
  248. {
  249.         if(SELT==0)
  250.         {
  251.                 delay1(2);
  252.                 if(SELT==0)
  253.                 {
  254.                         while(!SELT);
  255.                         Select_num++;                                        //选择键按下一次
  256.                         Adjust=1;                                                //进入调节模式                        
  257.                 }
  258.                 if(Select_num==1)
  259.                 {
  260.                         LCD_Clean(1);
  261.                         LCD_Clean(2);
  262.                         LCD_Display_String(1,table4);
  263.                         LCD_Display_String(2,table5);
  264.                         write_com(0x80+0);                                //写 >>
  265.                         write_date(0x3e);
  266.                         write_com(0x80+1);                                //写 >>
  267.                         write_date(0x3e);
  268.                         Enter_num=0;
  269.                 }
  270.                 if(Select_num==2)
  271.                 {
  272.                         LCD_Clean(1);
  273.                         LCD_Clean(2);
  274.                         LCD_Display_String(1,table4);
  275.                         LCD_Display_String(2,table5);
  276.                         write_com(0x80+0x40+0);                                //写 >>
  277.                         write_date(0x3e);
  278.                         write_com(0x80+0x40+1);                                //写 >>
  279.                         write_date(0x3e);
  280.                         Enter_num=0;
  281.                 }
  282.                 if(Select_num==3)
  283.                 {
  284.                         LCD_Clean(1);
  285.                         LCD_Clean(2);
  286.                         LCD_Display_String(1,table1);
  287.                         LCD_Display_String(2,table2);
  288.                         Select_num=0;
  289.                         Enter_num=0;                                       
  290.                         Adjust=0;
  291.                 }
  292.                 write_com(0x0c);                                                                        //光标不再闪烁
  293.                 Enter_num=0;
  294.         }
  295.         
  296.         if(ENTER==0)
  297.         {
  298.                 delay1(2);
  299.                 if(ENTER==0)
  300.                 {
  301.                         while(!ENTER);
  302.                         Enter_num++;
  303.                 }
  304.                 if(Select_num==1)                                        //设置实时时间
  305.                 {
  306.                         if(Enter_num==1)
  307.                         {
  308.                                 LCD_Clean(1);
  309.                                 LCD_Clean(2);
  310.                                 LCD_Display_String(1,table9);
  311.                                 LCD_Display_String(2,table0);
  312.                                 SetTime_dispaly(0x80+8,Year);
  313.                                 SetTime_dispaly(0x80+11,Month);
  314.                                 SetTime_dispaly(0x80+14,Day);
  315.                                 SetTime_dispaly(0x80+0x40+6,Hour);
  316.                                 SetTime_dispaly(0x80+0x40+9,Minute);
  317.                                 SetTime_dispaly(0x80+0x40+12,Second);
  318.                                 Week_dispaly(0x80+0x40+15,Week);
  319.                                 write_com(0x80+8);                        //光标闪烁地址,停留在年的位置上                                       
  320.                                 write_com(0x0f);                        //光标闪烁
  321.                         }
  322.                         if(Enter_num==2)
  323.                         {
  324.                                 write_com(0x80+11);                        //光标闪烁地址,停留在月的位置上                                       
  325.                                 write_com(0x0f);                        //光标闪烁
  326.                         }
  327.                         if(Enter_num==3)
  328.                         {
  329.                                 write_com(0x80+14);                        //光标闪烁地址,停留在日的位置上                                       
  330.                                 write_com(0x0f);                        //光标闪烁
  331.                         }
  332.                         if(Enter_num==4)
  333.                         {
  334.                                 write_com(0x80+0x40+6);                //光标闪烁地址,停留在时的位置上                                       
  335.                                 write_com(0x0f);                        //光标闪烁
  336.                         }
  337.                         if(Enter_num==5)
  338.                         {
  339.                                 write_com(0x80+0x40+9);                //光标闪烁地址,停留在分的位置上                                       
  340.                                 write_com(0x0f);                        //光标闪烁
  341.                         }
  342.                         if(Enter_num==6)
  343.                         {
  344.                                 write_com(0x80+0x40+12);        //光标闪烁地址,停留在秒的位置上                                       
  345.                                 write_com(0x0f);                        //光标闪烁
  346.                         }
  347.                         if(Enter_num==7)
  348.                         {
  349.                                 write_com(0x80+0x40+15);        //光标闪烁地址,停留在星期的位置上                                       
  350.                                 write_com(0x0f);                        //光标闪烁
  351.                         }
  352.                         if(Enter_num==8)
  353.                         {
  354.                                 Enter_num=0;
  355.                                 write_com(0x0c);                        //光标不再闪烁
  356.                                 LCD_Clean(1);
  357.                                 LCD_Clean(2);
  358.                                 LCD_Display_String(1,table1);
  359.                                 LCD_Display_String(2,table2);
  360.                                 time_data[0]=Year;///10*16+Year%10;
  361.                                 time_data[1]=Week+1;///10*16+Week%10;
  362.                                 time_data[2]=Month;///10*16+Month%10;
  363.                                 time_data[3]=Day;///10*16+Day%10;
  364.                                 time_data[4]=Hour;///10*16+Hour%10;
  365.                                 time_data[5]=Minute;///10*16+Minute%10;
  366.                                 time_data[6]=Second;///10*16+Second%10;
  367.                                 set_rtc();                                         //设置时间
  368.                                 Select_num=0;
  369.                                 Adjust=0;
  370.                         }
  371.                 }

  372.                 if(Select_num==2)                                        //设置开关锁时间
  373.                 {
  374.                         if(Enter_num==1)
  375.                         {
  376.                                 LCD_Clean(1);
  377.                                 LCD_Clean(2);
  378.                                 LCD_Display_String(1,table6);
  379.                                 LCD_Display_String(2,table7);
  380.                                 SetTime_dispaly(0x80+0x40+4,Hour_L);
  381.                                 SetTime_dispaly(0x80+0x40+7,Minute_L);
  382.                                 SetTime_dispaly(0x80+0x40+10,Second_L);
  383.                                 write_com(0x80+0x40+4);                //光标闪烁地址,停留在时的位置上                                       
  384.                                 write_com(0x0f);                        //光标闪烁
  385.                         }
  386.                         if(Enter_num==2)
  387.                         {
  388.                                 write_com(0x80+0x40+7);                //光标闪烁地址,停留在分的位置上                                       
  389.                                 write_com(0x0f);                        //光标闪烁
  390.                         }
  391.                         if(Enter_num==3)
  392.                         {
  393.                                 write_com(0x80+0x40+10);        //光标闪烁地址,停留在秒的位置上                                       
  394.                                 write_com(0x0f);                        //光标闪烁
  395.                         }
  396.                         if(Enter_num==4)
  397.                         {
  398.                                 write_com(0x0c);                        //光标不再闪烁
  399.                                 LCD_Clean(1);
  400.                                 LCD_Clean(2);
  401.                                 LCD_Display_String(1,table8);
  402.                                 LCD_Display_String(2,table7);        
  403.                                 SetTime_dispaly(0x80+0x40+4,Hour_H);
  404.                                 SetTime_dispaly(0x80+0x40+7,Minute_H);
  405.                                 SetTime_dispaly(0x80+0x40+10,Second_H);
  406.                                 write_com(0x80+0x40+4);                //光标闪烁地址,停留在时的位置上                                       
  407.                                 write_com(0x0f);                        //光标闪烁
  408.                         }
  409.                         if(Enter_num==5)
  410.                         {
  411.                                 write_com(0x80+0x40+7);                //光标闪烁地址,停留在分的位置上                                       
  412.                                 write_com(0x0f);                        //光标闪烁
  413.                         }
  414.                         if(Enter_num==6)
  415.                         {
  416.                                 write_com(0x80+0x40+10);        //光标闪烁地址,停留在秒的位置上                                       
  417.                                 write_com(0x0f);                        //光标闪烁
  418.                         }               
  419.                         if(Enter_num==7)
  420.                         {
  421.                                 Enter_num=0;
  422.                                 write_com(0x0c);                        //光标不再闪烁
  423.                                 LCD_Clean(1);
  424.                                 LCD_Clean(2);
  425.                                 LCD_Display_String(1,table1);
  426.                                 LCD_Display_String(2,table2);
  427.                                 Select_num=0;
  428.                                 Adjust=0;
  429.                         }
  430.                 }

  431.         }


  432.         if(MODE==0)                                                        //切换按键按下
  433.         {
  434.                 delay1(2);                                                        //消抖
  435.                 if(MODE==0)
  436.                 {
  437.                         while(!MODE);                                        //按键释放
  438.                         Auto_flg=~Auto_flg;                                //模式切换
  439.                         if(Auto_flg==0)                                        //自动模式
  440.                         {
  441.                                 AUTO_LED=0;                                        //自动灯亮
  442.                                 HAND_LED=1;
  443.                         }
  444.                         if(Auto_flg==1)                                        //手动模式
  445.                         {
  446.                                 AUTO_LED=1;                                       
  447.                                 HAND_LED=0;                                        //手动灯亮
  448.                                 LAMP1=1;                                        //关灯
  449.                                 LAMP2=1;
  450.                                 LAMP3=1;
  451.                                 LAMP4=1;
  452.                         }
  453.                 }
  454.         }
  455.         if(Auto_flg==1)                                                        //手动模式
  456.         {
  457.                 if(SWITCH==0)                                                //灯开关按键按下
  458.                 {
  459.                         delay1(2);                                                //消抖
  460.                         if(SWITCH==0)
  461.                         {
  462.                                 while(!SWITCH);                                //按键释放
  463.                                 Switch_num++;                                //按下次数增加
  464.                                 if(Switch_num==1)                        //按下一次,开一盏灯
  465.                                 {
  466.                                         LAMP1=0;
  467.                                         LAMP2=1;
  468.                                         LAMP3=1;
  469.                                         LAMP4=1;
  470.                                 }
  471.                                 if(Switch_num==2)                        //按下二次,开二盏灯
  472.                                 {
  473.                                         LAMP1=0;
  474.                                         LAMP2=0;
  475.                                         LAMP3=1;
  476.                                         LAMP4=1;
  477.                                 }
  478.                                 if(Switch_num==3)                        //按下3次,开3盏灯
  479.                                 {
  480.                                         LAMP1=0;
  481.                                         LAMP2=0;
  482.                                         LAMP3=0;
  483.                                         LAMP4=1;
  484.                                 }
  485.                                 if(Switch_num==4)                        //按下4次,开4盏灯
  486.                                 {
  487.                                         LAMP1=0;
  488.                                         LAMP2=0;
  489.                                         LAMP3=0;
  490.                                         LAMP4=0;
  491.                                 }
  492.                                 if(Switch_num==5)                        //按下5次,开0盏灯
  493.                                 {
  494.                                         LAMP1=1;
  495.                                         LAMP2=1;
  496.                                         LAMP3=1;
  497.                                         LAMP4=1;
  498.                                         Switch_num=0;                        //次数清除
  499.                                 }
  500.                         }
  501.                 }
  502.         }
  503. }

  504. void Open(void)
  505. {
  506.         float Now;
  507.         float Set_L,Set_H;
  508.         Now=Hour+Minute/60+Second/3600;                                                  //把实时时间化成小时为单位
  509.         Set_L=Hour_L+Minute_L/60+Second_L/3600;                                  //把设置下限时间化成小时为单位
  510.         Set_H=Hour_H+Minute_H/60+Second_H/3600;                                  //把设置上限时间化成小时为单位
  511.         if(Auto_flg==0)                                                                                //自动模式
  512.         {
  513.                 if((Now>=Set_L)&(Now<=Set_H))                                          //实时时间在上下限时间范围内
  514.                 {
  515.                         if(LIGHT1==0)                                                            //光线不足
  516.                         {
  517.                                 if(Value1==0)
  518.                                 {
  519.                                         LAMP1=1;                                                        //全灭
  520.                                         LAMP2=1;
  521.                                         LAMP3=1;
  522.                                         LAMP4=1;
  523.                                 }
  524.                                 if((Value1>0)&(Value1<10))
  525.                                 {
  526.                                         LAMP1=0;                                                        //亮一个灯
  527.                                         LAMP2=1;
  528.                                         LAMP3=1;
  529.                                         LAMP4=1;
  530.                                 }
  531.                                 if((Value1>=10)&(Value1<20))
  532.                                 {
  533.                                         LAMP1=0;                                                        //亮二个灯
  534.                                         LAMP2=0;
  535.                                         LAMP3=1;
  536.                                         LAMP4=1;
  537.                                 }
  538.                                 if((Value1>=20)&(Value1<30))
  539.                                 {
  540.                                         LAMP1=0;                                                        //亮三个灯
  541.                                         LAMP2=0;
  542.                                         LAMP3=0;
  543.                                         LAMP4=1;
  544.                                 }
  545.                                 if(Value1>=30)
  546.                                 {
  547.                                         LAMP1=0;                                                        //亮四个灯
  548.                                         LAMP2=0;
  549.                                         LAMP3=0;
  550.                                         LAMP4=0;
  551.                                 }
  552.                         }
  553.                         if(LIGHT1==1)                                                            //光线强烈
  554.                         {
  555.                                 LAMP1=1;                                                                //全灭
  556.                                 LAMP2=1;
  557.                                 LAMP3=1;
  558.                                 LAMP4=1;
  559.                         }
  560.                 }
  561.         
  562.                 if((Now<Set_L)|(Now>Set_H))                                                  //实时时间不在范围内
  563.                 {
  564.                         LAMP1=1;                                                                        //全灭
  565.                         LAMP2=1;
  566.                         LAMP3=1;
  567.                         LAMP4=1;
  568.                 }
  569.         }
  570. }

  571. /*******************************************************************************************************/
  572. void Count_Value(void)
  573. {
  574.         SetTime_dispaly(0x80+3,Value1);
  575.         if(IN1==0)
  576.         {
  577.                 delay1(1);
  578.                 if(IN1==0)
  579.                 {
  580.                         while(!IN1);
  581.                         if(OUT1_flag==0)
  582.                         {
  583.                                 IN1_flag=1;
  584.                                 TR0=1;                                         //开启定时器 防止误触发
  585.                         }
  586.                         if(OUT1_flag==1)
  587.                         {
  588.                                 
  589.                                 Value1++;                                 //人数增加
  590.                                 if(Value1>=99)                         //如果人数计数到99,变为最大99
  591.                                 Value1=99;
  592.                                 OUT1_flag=0;                         //清零
  593.                                 IN1_flag=0;
  594.                                 TR0=0;                                         //关闭定时器
  595.                                 Count=0;
  596.                                 Miao=0;
  597.                         }
  598.                 }
  599.         }
  600.         if(OUT1==0)
  601.         {
  602.                 delay1(1);
  603.                 if(OUT1==0)
  604.                 {
  605.                         while(!OUT1);
  606.                         if(IN1_flag==0)
  607.                         {
  608.                                 OUT1_flag=1;
  609.                                 TR0=1;                                         //开启定时器 防止误触发
  610.                         }
  611.                         if(IN1_flag==1)
  612.                         {
  613.                                 Value1--;                                //人数减少
  614.                                 if(Value1<0)                        //如果人数计数小于0,变为最小0
  615.                                 Value1=0;
  616.                                 IN1_flag=0;                                //清零
  617.                                 OUT1_flag=0;
  618.                                 TR0=0;                                         //关闭定时器
  619.                                 Count=0;
  620.                                 Miao=0;
  621.                         }
  622.                 }
  623.         }
  624. }
  625. /****************************************温度************************************************************/
  626. void delay(uint y)                                                                           //DS18B20延时函数(仿真用)
  627. {
  628.         while(y--);
  629. }

  630. /*void delay(uint z)                                                                                  //DS18B20延时函数(实物用)
  631. {
  632.         uint x,y;
  633.         for(x=z;x>0;x--)
  634.                 for(y=1;y>0;y--);
  635. }  
  636. */
  637. void write_byte(uint dat)                        //写一个字节
  638. {
  639.         uchar i;
  640.         for(i=0;i<8;i++)                        //循环八次          共有八位
  641.         {
  642.                 DQ=0;                                                //写零
  643.                 DQ=dat&0x01;                //向总线写位数据,从最低位写起
  644.                 delay(4);
  645.                 DQ=1;                                                //写一
  646.                 dat>>=1;                                    //下次写作准备,移位数据
  647.         }
  648.         delay(4);
  649. }                                    

  650. uchar read_byte(void)                                //读一个字节,返回值
  651. {
  652.         uchar i;
  653.         uint value;
  654.         for(i=0;i<8;i++)                        //循环八次          共有八位
  655.         {
  656.                 DQ=0;
  657.                 value>>=1;
  658.                 DQ=1;                                                //释放总线
  659.                 if(DQ)
  660.                 value|=0x80;                            //DQ=1,value取1
  661.                 delay(4);
  662.         }
  663.         return value;
  664. }

  665. void ds18b20_init()                                    //初始化函数
  666. {
  667.         uint n;
  668.         DQ=1;
  669.         delay(8);                                          
  670.         DQ=0;
  671.         delay(80);                                            //低电平480——960us
  672.         DQ=1;                                                        //总线释放
  673.         delay(8);                                            //等待50——100us
  674.         n=DQ;                                                    //读取复位状态
  675.         delay(4);
  676. }

  677. int readtemperature()                                //读整数部分
  678. {        
  679.     int a,b;                                                //高八位,低八位
  680.         ds18b20_init();
  681.         write_byte(0xcc);                            //跳过rom匹配,跳过读序列号的操作,可节省操作时间
  682.         write_byte(0x44);                            //启动温度检测
  683.         delay(300);                                            //测温度
  684.         ds18b20_init();                                    //开始操作前需要复位
  685.         write_byte(0xcc);                                //跳过rom匹配
  686.         write_byte(0xbe);                            //写读寄存器中温度值的命令
  687.         a=read_byte();                                    //low          低位开始读取
  688.         b=read_byte();                                    //high          高位开始读取
  689.         b<<=8;                                                        //把高位左移八位
  690.         b=b|a;                                                        //高八位与第八位进行或运算,得到总和
  691.         if(b>=0)                                                //如果温度大于等于0
  692.         {
  693.                 b=b*0.0625;                                        //直接乘以0.0625
  694.                 write_com(0x80+0x40+2);                //在LCD1602对应的位置不写内容
  695.                 write_date(0x20);
  696.         }
  697.     else                                                        //温度小于0
  698.         {        
  699.                 b=~b+1;                                                //取反码再加一
  700.                 b=b*0.0625;                                        //再运算
  701.                 write_com(0x80+0x40+2);                //在LCD1602对应的位置写一个负号
  702.                 write_date(0x2d);
  703.         }
  704.         return b;                                                //返回b,此时以表示温度
  705. }
  706. void temperature_dispaly(char add,char dat)                         //温度显示函数:第一个:参数的地址,第二个:参数的内容
  707. {
  708.         uchar shi,ge;
  709.         shi=dat/10;                                                                                 //把温度的十位提取出来
  710.         ge=dat%10;                                                                                 //把温度的个位提取出来
  711.         write_com(0x80+0x40+add);                                                    //要写的地址
  712.         write_date(0x30+shi);                                                            //十位的内容   1602字符库
  713.         write_date(0x30+ge);                                                     //个位的内容        1602字符库
  714. }
  715. /*****************************************定时器初始化和主函数***********************************************************/
  716. void T0_init(void)
  717. {
  718.         TMOD=0x11;                                              //设置定时器0为工作方式1
  719.         TH0=(65536-50000)/256;              //50MS定时
  720.         TL0=(65536-50000)%256;
  721.         EA=1;                                                      //开定时器T0的中断        总中断
  722.         ET0=1;                                                   //允许T0中断
  723. //        TR0=1;                                                   //开启定时器
  724. }
  725. void main()
  726. {
  727.         AUTO_LED=0;                                         //默认自动模式
  728.         temperature=readtemperature();
  729.         init();                                                 //液晶初始化
  730.         T0_init();                                         //定时器初始化
  731.     write_ds1302(0x80,0x00);
  732.         delay1(8000);
  733.         while(1)
  734.         {
  735.                 if(Adjust==0)                         //非调节模式下显示时间人数和温度
  736.                 {        
  737.                         temperature=readtemperature();                        //读取温度
  738.                         temperature_dispaly(3,temperature);                //显示温度
  739.                         Time_Display();                 //显示时间
  740.                         Open();                                  //动作判断,根据光线和人数
  741.                         Count_Value();                 //计算人数
  742.                 }
  743.                 Keyscan();                                 //扫描键盘
  744.         }
  745. }
  746. void Timer0() interrupt 1                                        //定时器T0中断函数
  747. {
  748.         TH1=0x3c;                                        //赋初值=50ms
  749.         TL1=0xb0;                                        //TH0=3C,TL0=B0
  750.         Count++;                                                                //每中断一次,Count加一,计数20次,表示1s的时间到
  751.         if(Count>=20)                                                        //1s到
  752.         {
  753.                 Count=0;
  754.                 Miao++;
  755.                 if(Miao>=3)                                                        //3秒内无触发另一个,全部清零
  756.                 {
  757.                         Miao=0;
  758.                         OUT1_flag=0;                                         //清零
  759.                         IN1_flag=0;
  760.                         TR1=0;                                                         //关闭定时器
  761.                 }
  762.         }

  763. }
复制代码

原理图: 无
仿真: 硬件.rar (351.18 KB, 下载次数: 16)
代码: 软件.rar (73.75 KB, 下载次数: 13)

评分

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

查看全部评分

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

使用道具 举报

楼主
ID:166646 发表于 2024-4-28 10:15 | 只看该作者
非常感谢,非常好的参考资料
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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