找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 378|回复: 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 单片机教程网

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