欧美极品高清xxxxhd,国产日产欧美最新,无码AV国产东京热AV无码,国产精品人与动性XXX,国产传媒亚洲综合一区二区,四库影院永久国产精品,毛片免费免费高清视频,福利所导航夜趣136

 找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

搜索
查看: 287|回復: 2
收起左側

基于51單片機智能垃圾桶源程序Proteus仿真原理圖設計

[復制鏈接]
ID:578150 發表于 2025-11-25 10:00 | 顯示全部樓層 |閱讀模式
這個51單片機做的智能垃圾桶具備以下功能:
自動感應開蓋:通過紅外傳感器(來人檢測)感應人體,觸發箱蓋開關電路自動打開箱蓋。
箱滿檢測:另一路紅外傳感器(箱滿檢測)識別桶內垃圾是否裝滿,滿時會觸發提示。
語音提示:支持 3 種語音播報:
提示垃圾分類
提示垃圾桶已滿
提示正在消毒
消毒功能:通過消毒泵電路,可對桶內進行消毒操作。
參數設置:借助按鍵電路(設置 / 增加 / 減小),可調整系統參數。
顯示功能:通過 LCD 顯示電路,展示時間、狀態等信息(搭配時鐘電路提供時間基準)。
上位機交互:支持與模擬上位機通信,可傳輸數據或接收控制指令。

仿真原理圖如下(proteus仿真工程文件可到本帖附件中下載)
51hei.png

單片機源程序如下:
  1. //宏定義
  2. #define uint unsigned int
  3. #define uchar unsigned char
  4. //程序頭函數
  5. #include <reg52.h>
  6. #include <string.H>
  7. #include <intrins.h>
  8. #include "Data.h"
  9. #include "DS1302.h"
  10. //顯示函數
  11. #include <display.h>

  12. bit flag1s = 0;           //1s定時標志
  13. unsigned char T0RH = 0;  //T0重載值的高字節
  14. unsigned char T0RL = 0;  //T0重載值的低字節

  15. void ConfigTimer0(unsigned int ms);

  16. //按鍵
  17. sbit Key1=P3^5;         //設置鍵
  18. sbit Key2=P3^6;         //加按鍵
  19. sbit Key3=P3^7;         //減按鍵

  20. sbit beng=P2^3;          //消毒泵

  21. sbit yuyin_1=P3^2;        //請垃圾分類
  22. sbit yuyin_2=P3^3;         //垃圾桶已滿
  23. sbit yuyin_3=P3^4;        //垃圾桶正在消毒
  24. sbit HW1=P2^6;            //紅外1
  25. sbit HW2=P2^7;            //紅外2   垃圾箱滿標志

  26. uchar set;                    //設置狀態
  27. uchar kaigai_yanshi;

  28. bit full=0;         //箱滿標志

  29. bit flag1=0;  //
  30. bit flag2=0;  //  //開關門標志
  31. bit flag3=0;   //
  32. bit flag4=0;   //
  33. bit flag5=0;  // 正反轉
  34. /*******************************定義全局變量********************************/

  35. //電機部分

  36. unsigned char code Z_BeatCode[8] = { 0x1, 0x3, 0x2, 0x6, 0x4, 0xc, 0x8, 0x9};   //正向步進電機節拍對應的IO控制代碼
  37. unsigned char code F_BeatCode[8] = { 0x9, 0x8, 0xc, 0x4, 0x6, 0x2, 0x3, 0x1};   //反向步進電機節拍對應的IO控制代碼
  38. unsigned long beats = 0;  //電機轉動節拍總數
  39. void StartMotor(unsigned long angle);
  40. //函數聲明

  41. void Key();
  42. //毫秒延時**************************
  43. void delay_nms(unsigned int k)        
  44. {                                                
  45. unsigned int i,j;                                
  46. for(i=0;i<k;i++)
  47. {                        
  48. for(j=0;j<121;j++)                        
  49. {;}}                                                
  50. }


  51. void Key()                          //按鍵函數
  52. {

  53.         if(Key1==0)                        //設置鍵按下時
  54.         {
  55.                 while(Key1==0);        //檢測按鍵是否釋放
  56.                  set++;                        //設置狀態標志加                                 
  57.         }
  58.         if(set==1)                        //設置時
  59.         {
  60.                 write_com(0x38);//屏幕初始化
  61.                 write_com(0x80+1);//選中的位置
  62.                    write_com(0x0f);//打開顯示 無光標 光標閃爍
  63.                    write_com(0x06);//當讀或寫一個字符是指針后一一位        
  64.         }
  65.         else if(set==2)                        //設置時
  66.         {
  67.                 write_com(0x38);//屏幕初始化
  68.                 write_com(0x80+4);//選中的位置
  69.                    write_com(0x0f);//打開顯示 無光標 光標閃爍
  70.                    write_com(0x06);//當讀或寫一個字符是指針后一一位         
  71.         }
  72.         else if(set==3)                        //設置時
  73.         {
  74.                 write_com(0x38);//屏幕初始化
  75.                 write_com(0x80+7);//選中的位置
  76.                    write_com(0x0f);//打開顯示 無光標 光標閃爍
  77.                    write_com(0x06);//當讀或寫一個字符是指針后一一位        
  78.         }
  79.         else if(set==4)                        //設置時
  80.         {
  81.                 write_com(0x38);//屏幕初始化
  82.                 write_com(0x80+0x40+1);//選中的位置
  83.                    write_com(0x0f);//打開顯示 無光標 光標閃爍
  84.                    write_com(0x06);//當讀或寫一個字符是指針后一一位         
  85.         }
  86.         else if(set==5)                        //設置時
  87.         {
  88.                 write_com(0x38);//屏幕初始化
  89.                 write_com(0x80+0x40+4);//選中的位置
  90.                    write_com(0x0f);//打開顯示 無光標 光標閃爍
  91.                    write_com(0x06);//當讀或寫一個字符是指針后一一位         
  92.         }
  93.         else if(set==6)                        //設置時
  94.         {
  95.                 write_com(0x38);//屏幕初始化
  96.                 write_com(0x80+0x40+7);//選中的位置
  97.                    write_com(0x0f);//打開顯示 無光標 光標閃爍
  98.                    write_com(0x06);//當讀或寫一個字符是指針后一一位
  99.         }
  100.         else if(set>=7)                //再按一下設置鍵時,退出設置
  101.         {
  102.                 set=0;                        //設置狀態清零                                
  103.                 Ds1302_Write_Time();  //保存時間
  104.                 Init1602();           //初始化顯示  
  105.                 write_com(0x38);//屏幕初始化
  106.                 write_com(0x0c);//打開顯示 無光標 無光標閃爍
  107.         }
  108.         if(Key2==0&&set!=0)        //當在設置狀態時,按下加鍵時
  109.         {
  110.                 while(Key2==0);        //按鍵釋放         ++        
  111.                                 //年
  112.                                 if(set==1)
  113.                                 {
  114.                                         time_buf1[1]++;
  115.                                         if(time_buf1[1]>=100)
  116.                                                 time_buf1[1]=0;
  117. ...........
  118. ............
  119.         }
  120. }
  121. /* 步進電機啟動函數,angle-需轉過的角度 */
  122. void StartMotor(unsigned long angle)
  123. {
  124.     //在計算前關閉中斷,完成后再打開,以避免中斷打斷計算過程而造成錯誤
  125.    // EA = 0;
  126.     beats = (angle * 4076) / 360; //實測為4076拍轉動一圈
  127.    // EA = 1;
  128. }
  129. /* 配置并啟動T0,ms-T0定時時間 */
  130. void ConfigTimer0(unsigned int ms)
  131. {
  132.     unsigned long tmp;  //臨時變量

  133.     TMOD=0x21;//定時器1操作模式2:8位自動重載定時器  
  134.         TH1=0xfd;//裝入初值,波特率9600
  135.         TL1=0xfd;
  136.         
  137.         TR1=1;//打開定時器
  138.         SM0=0;//設置串行通訊工作模式,(10為一部發送,波特率可變,由定時器1的溢出率控制)
  139.         SM1=1;//(同上)在此模式下,定時器溢出一次就發送一個位的數據
  140.         REN=1;//串行接收允許位(要先設置sm0sm1再開串行允許)
  141.         ES=1;//開串行口中斷        

  142.     tmp = 11059200 / 12;      //定時器計數頻率
  143.     tmp = (tmp * ms) / 1000;  //計算所需的計數值
  144.     tmp = 65536 - tmp;        //計算定時器重載值
  145.     tmp = tmp + 12;           //補償中斷響應延時造成的誤差
  146.     T0RH = (unsigned char)(tmp>>8);  //定時器重載值拆分為高低字節
  147.     T0RL = (unsigned char)tmp;

  148.     TH0 = T0RH;     //加載T0重載值
  149.     TL0 = T0RL;
  150.     ET0 = 1;        //使能T0中斷
  151.     TR0 = 1;        //啟動T0
  152. }
  153. /* T0中斷服務函數,執行2ms定時 */
  154. void InterruptTimer0() interrupt 1
  155. {
  156.     static unsigned int tmr1000ms = 0;
  157.     static unsigned int tmr50ms = 0;
  158.     unsigned char tmp;  //臨時變量
  159.     static unsigned char index = 0;  //節拍輸出索引

  160.     TH0 = T0RH;  //重新加載重載值
  161.     TL0 = T0RL;
  162.     tmr1000ms++;
  163.     if (tmr1000ms >= 500)  //定時1s
  164.     {
  165.         tmr1000ms = 0;
  166.         flag1s = 1;
  167.     }         
  168.         // StartMotor(180);          //半圈
  169.         //電機部分
  170.     if (beats != 0)  //節拍數不為0則產生一個驅動節拍
  171.     {
  172.          
  173.         tmp = P1;                    //用tmp把P1口當前值暫存
  174.         tmp = tmp & 0xF0;            //用&操作清零低4位
  175.                 if(flag5==1)
  176.                 {
  177.           tmp = tmp | Z_BeatCode[index]; //用|操作把節拍代碼寫到低4位
  178.                 }
  179.                 else
  180.                 {
  181.                   tmp = tmp | F_BeatCode[index]; //用|操作把節拍代碼寫到低4位
  182.                 }
  183.         P1  = tmp;                   //把低4位的節拍代碼和高4位的原值送回P1
  184.         index++;                     //節拍輸出索引遞增
  185.         index = index & 0x07;        //用&操作實現到8歸零
  186.         beats--;                     //總節拍數-1
  187.     }
  188.     else  //節拍數為0則關閉電機所有的相
  189.     {
  190.        // P1 = P1 | 0x0F;
  191.            P1 = P1 & 0xF0;
  192.            if(flag5==1)          //反轉 并停止時
  193.            {   
  194.                tmr50ms++;
  195.                    if(tmr50ms>=500)
  196.                    {
  197.                         tmr50ms=0;
  198.                     flag1=0;   //箱蓋關閉標志
  199.                    }
  200.            }
  201.     }
  202. }

  203. /*串行通訊中斷,收發完成將進入該中斷*/
  204. void Serial_interrupt() interrupt 4
  205. {
  206.         unsigned char temp_rec_data_uart0;        
  207.         temp_rec_data_uart0 = SBUF;//讀取接收數據               
  208.         RI=0;//接收中斷信號清零,表示將繼續接收                        

  209. }
  210. void Uart1Send(uchar c)
  211. {
  212.         SBUF=c;
  213.         while(!TI);//等待發送完成信號(TI=1)出現
  214.         TI=0;        
  215. }

  216. //延時函數大概是1s鐘
  217. void DelaySec(int sec)
  218. {
  219.         uint i , j= 0;
  220.         for(i=0; i<sec; i++)
  221.         {
  222.                 for(j=0; j<40000; j++)
  223.                 {
  224.                         
  225.                 }
  226.         }
  227. }

  228. void main()          //主函數
  229. {
  230.         uchar i = 0;
  231.          EA = 1;            //開總中斷
  232.     ConfigTimer0(2);  //配置T0定時2ms
  233.         
  234.         Ds1302_Init();
  235.         Init1602();//初始化顯示
  236.         
  237.         HW1=1;  // 紅外檢測
  238.         yuyin_1=1;
  239.         yuyin_2=1;
  240.         yuyin_3=1;
  241.         beng=1;
  242.     DelaySec(1);//延時約1秒
  243.            
  244.         while(1)   //進入循環
  245.         {
  246.            if(set==0)                                           //只有在非設置狀態時,
  247.                   {                                   
  248.                      Ds1302_Read_Time();        
  249.                          display_NYR(time_buf1,full,flag2);
  250.                   }
  251.                   else         //if(set==1)
  252.                   {        
  253.                            delay_nms(180);              //延時180ms        
  254.                            display_NYR(time_buf1,full,flag2);
  255.                   }

  256.   if(flag1s==1)  //1s延時
  257.         {
  258.            flag1s=0;

  259.       if(yuyin_1==0)
  260.          {                  
  261.            yuyin_1=1;
  262.          }
  263.          if(yuyin_2==0)
  264.          {                  
  265.            yuyin_2=1;
  266.          }   
  267.      if(yuyin_3==0)
  268.          {                  
  269.            yuyin_3=1;
  270.          }                  
  271.           if((flag1==1)&&(flag2==1))         //   
  272.           {
  273.             kaigai_yanshi++;  //開蓋延時
  274.                 if(kaigai_yanshi>10)
  275.                  {
  276.                    kaigai_yanshi=0;                  
  277.                             flag2=0;    //  箱蓋關閉標志                    
  278.                      StartMotor(180);         //關閉箱蓋                           
  279.                     flag5=1;           //電機反傳         
  280.                  }
  281.           }         
  282.              if(HW2==0)         //垃圾桶已滿  通知上位機
  283.                    {               
  284.                           Uart1Send('F');
  285.                           Uart1Send('U');
  286.                           Uart1Send('L');
  287.                           Uart1Send('L');
  288.                           Uart1Send('\r');
  289.                           Uart1Send('\n');
  290.                    }                                                   
  291.         }

  292.    if(HW2==0)         //垃圾桶已滿
  293.    {
  294.           full=1;
  295.    }
  296.    else
  297.    {
  298.           full=0;
  299.    }

  300. if((HW2==1)&&(beng==1))          //垃圾桶未滿并且沒有消毒
  301. {
  302.    if(flag1==0)
  303.    {
  304.           if(HW1==0)         //有人倒垃圾
  305.            {
  306.               flag5=0;           //電機正傳         
  307.                   yuyin_1=0;  //語音垃圾分類         
  308.                   flag1=1;    //  箱蓋打開標志
  309.                   flag2=1;    //  箱蓋打開標志
  310.         
  311.                   StartMotor(180);         //打開箱蓋
  312.            }
  313.         }
  314. }

  315. if(HW2==0)          //垃圾桶滿
  316. {   
  317.           if(HW1==0)         //有人倒垃圾
  318.            {                       
  319.                   yuyin_2=0;  //垃圾桶已滿                           
  320.            }        
  321. }


  322.          if(time_buf1[5]==59)
  323.          {
  324.                  beng=0;         //啟動消毒泵 1分鐘
  325.          }
  326.          else
  327.          {
  328.                    beng=1;          //關閉消毒泵
  329.          }

  330.    if(beng==0)
  331.    {
  332.               if(HW1==0)         //有人倒垃圾
  333.            {                       
  334.                   yuyin_3=0;  //垃圾桶消毒                           
  335.            }
  336.    }

  337.         Key();                                                   //掃描按鍵
  338.         

  339.                                                 
  340.         }
  341. }


復制代碼

Proteus仿真和Keil程序下載: 見2樓

評分

參與人數 1黑幣 +50 收起 理由
admin + 50 共享資料的獎勵!

查看全部評分

回復

使用道具 舉報

ID:578150 發表于 2025-11-25 10:04 | 顯示全部樓層
補資料

基于51單片機的智能垃圾桶設計.7z

227.1 KB, 下載次數: 0, 下載積分: 黑幣 -5

回復

使用道具 舉報

ID:1160028 發表于 2025-11-26 09:23 | 顯示全部樓層
收藏起來,作為參考。
回復

使用道具 舉報

您需要登錄后才可以回帖 登錄 | 立即注冊

本版積分規則

小黑屋|51黑電子論壇 |51黑電子論壇6群 QQ 管理員QQ:125739409;技術交流QQ群281945664

Powered by 單片機教程網

快速回復 返回頂部 返回列表