找回密码
 立即注册

QQ登录

只需一步,快速开始

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

单片机传送带计数器(LED显示)仿真+程序源码+设计报告

[复制链接]
跳转到指定楼层
楼主


全部资料51hei下载地址:
传送带计数器.rar (336.62 KB, 下载次数: 102)


摘要
    本设计采用89C51单片机作为主控制器,用独立按键设置传送带产品计数目标值,用继电器控制电机的启动,通过超声波模块检测距离变化得到的的计数值通过缓冲器74LS244 送到4位7段LED数码管,以实现对产品的计数显示。当计数值达到预置值时,停止计数且电机停止运转。文中详细论述了传送带产品计数器的设计原理,电路原理图和程序设计方案。

目录

题目1
任务设计1
21   设计目的1
22   设计要求1
三.系统硬件设计1
31   传送带计数器(LED显示)电路原理图1
32   单片机模块1
33   电源模块2
34   LED显示模块2
35   按键模块3
36   超声波模块3
37   电机控制模块3
四.软件系统设计 3
41   C51程序4
仿真即调试13
51   仿真图13
52   PCB图14
53   3D效果图14
六.总结15
七.参考文献15


一.
题目

设计题目:传送带计数器(LED显示)

二.任务设计:

2.1   设计目的

    传送带产品计数器广泛应用于工业生产中对各种产品的成件计数,确保了计数的准确性,减少了人为计数的误差,提高了生产效率。在工业生产中对产品的成批包装,管理具有很强的实用性,特别是对批量产品的计数有非常重要的意义。

2.2   设计要求

用AT89C51系列单片机作为控制器;采用4位LED进行计数显示;采用超声波传感器计数;用独立按键控制传送带电机的启停和计数,计数到预定值时,传送带停止,按键后传送带继续运行。

  • 系统硬件设计

硬件电路是系统设计的主要组成部分,各个部分硬件电路的组成就是整个系统各个功能模块的组成。

3.1   传送带计数器(LED显示)电路原理图

硬件原理图如下图所示,包括电源模块,显示模块,按键模块,超声波模块和电机控制模块。


3.2   单片机模块(AT89C51)

AT89C51是一种带4K字节FLASH存储器(FPEROM—Flash Programmable and Erasable Read Only Memory)的低电压、高性能CMOS 8位微处理器,俗称单片机。AT89C2051是一种带2K字节闪存可编程可擦除只读存储器的单片机。单片机的可擦除只读存储器可以反复擦除1000次。该器件采用ATMEL高密度非易失存储器制造技术制造,与工业标准的MCS-51指令集和输出管脚相兼容。由于将多功能8位CPU和闪速存储器组合在单个芯片中,ATMEL的AT89C51是一种高效微控制器,AT89C051是它的一种精简版本。AT89C51单片机为很多嵌入式控制系统提供了一种灵活性高且价廉的方案。(图3-1)

                图3-1     

                                                           图3-2

3.3   电源模块                                       

电源部分采用5v直流稳压电源,晶振电路提供时钟信号,复位电路使程序计数器清零。

(图3-2)

3.4    LED显示模块
使用4位7段数码管来显示数字,通过74LS244来驱动数码管。



3.5   按键模块
每个按键各接一根输入线,一根输入线上的按键工作状态不会影响其他输入线上的输入状态。软件设计采用查询方式和外部中断相结合的方法来设计,低电平有效。按键直接与89C51的I/O口线相连接,通过读I/O口的电平状态,即可识别出按下的按键。                                                                     


3.6   超声波模块

通过超声波模块测距计数,距离小于5且信号灯未亮时代表检测到货并计数,大于6且信号灯亮起时代表货物已经过去了,然后在检测到5以下就又会计数。(允许误差和延时)



3.7   电机控制模块

利用三极管放大电流,继电器来控制电机以控制传送带的启停。



  • 软件系统设计

软件设计就是编写能使单片机运行并控制外围电路的程序,然后把程序导入单片机,对单片机进行控制,以完成硬件的功能。利用软件完成了各个按键要实现的功能、控制了继电器的断开和闭合以及显示电路显示结果,最后把所有的子程序揉合到一块就控制了整个系统的运行。



  • 仿真即调试

5.1   仿真图

5.2   PCB图

                                   布线层打印效果

5.3   3D效果图

  • 总结

    本设计是关于传送带产品计数器的设计。在设计中,以AT89C51单片机作为主控制器,可以通过独立按键进行预置数,方便灵活,并且可以在4位LED上显示当前计数值,通过按键来控制传送带电机的启动,操作灵活,可以精确的对产品进行计数。由于使用了超声波模块进行测距,所以控制起来很安全,不会发生意外事故。由于采用的是独立按键进行预置数,所以计数范围需要手动设置,这是本设计的一个不足之处,不能够进行大范围计数(手会累),但是对于小批量的产品计数具有很好的实用性。

虽然,在硬件电路设计中我们遇到了很多问题,但通过我们的努力,最终都一一解决了。最困难的我想应该是PCB板的制作和软件编程。PCB板的制作是以前我们没有接触太多的,这次为了能制作出实物图,我们就又认真学了PCB的制作,中间有很多不懂的问题,都通过询问老师同学和反复实践解决了,最后我们终于制作出了很好的板子。如果说硬件电路是躯体的话,那么软件就是血液,软件编程的正确与否,直接导致了硬件电路功能的实现。程序调试过程中,出现了设置过程中数码管不能闪动、出现误计数的现象。这些都通过增大延时解决了。

    我们所做的有关传送带计数包装的设计虽然满足了基本的要求,但还存在着一些不足,比如用独立按键进行预置数,每次按键值增加一个数值会耗费大量时间;我们不经过计时再设计,无法保证货物是否到位,而且如果货物之间的间隔不规则,也将会无法控制。另外,我们也没有考虑掉点保护和单片机抗干扰问题。由于能力有限,很多想法就没有体现在设计中。



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

  5. sbit seg_1=P3^4;//定义数码管的位选
  6. sbit seg_2=P3^5;
  7. sbit seg_3=P3^6;
  8. sbit seg_4=P3^7;

  9. sbit TX=P2^5;        //超声波传感器的接口
  10. sbit RX=P2^6;

  11. sbit LED=P2^7; //指示灯接口
  12. sbit motor=P1^5; //传送带电机接口

  13. sbit K1=P1^0; //按键接口
  14. sbit K2=P1^1;
  15. sbit K3=P1^2;
  16. sbit K4=P1^3;
  17. sbit K5=P1^4;


  18. uchar code SEG_Table[]= {0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71}; //CC共阴
  19. char dis_data_buf[4]= {0,0,0,0};
  20. uchar counter_buf[4]= {0,0,0,0};
  21. long int set_num=0;
  22. unsigned long int counter_num=0;
  23. uchar start_flag=0;          //开始标志
  24. uchar set_flag=0;//设定计数值得标志                 
  25. uchar key_num=0;  //按键值

  26. unsigned int  time=0;  //声波时间
  27. unsigned int   S=0;          //距离

  28. void Delay_1ms(uint i)//1ms延时
  29. {
  30.   uchar x,j;
  31.   for(j=0; j<i; j++)
  32.     for(x=0; x<=148; x++);
  33. }

  34. //*********************************
  35. //按键扫描程序
  36. //mode:0,不支持连续按;1,支持连续按;
  37. //*********************************
  38. uchar KEY_Scan(uchar mode)
  39. {
  40.   static uchar key_up=1;//按键按松开标志
  41.   if(mode)key_up=1;  //支持连按
  42.   if(key_up&&(K1==0||K2==0||K3==0||K4==0||K5==0))
  43.   {
  44.     //Delay_1ms(10);//去抖动
  45.     key_up=0;
  46.     if(K1==0)return 1;
  47.     else if(K2==0)return 2;
  48.     else if(K3==0)return 3;
  49.     else if(K4==0)return 4;
  50.     else if(K5==0)return 5;
  51.    
  52.   } else if(K1==1&&K2==1&&K3==1&&K4==1&&K5==1)key_up=1;
  53.   return 0;// 无按键按下
  54. }
  55. void diplay(uchar *dis_p)
  56. {
  57.   static uchar temp_num=0;
  58.   static uint flash_time=0;
  59.   P0=SEG_Table[*(dis_p+temp_num)]; //查数组得到数码管段吗
  60.   switch(temp_num)
  61.   {
  62.   case 0:
  63.     if(set_flag) //如果是设定状态下就闪烁
  64.     {
  65.       if(flash_time<50)
  66.       {
  67.         seg_1=0;
  68.         seg_2=1;
  69.         seg_3=1;
  70.         seg_4=1;
  71.       }
  72.       else if(flash_time<100)
  73.       {
  74.         seg_1=1;
  75.         seg_2=1;
  76.         seg_3=1;
  77.         seg_4=1;
  78.       }
  79.       else
  80.       {
  81.         flash_time=0;
  82.       }
  83.     }
  84.     else  //正常显示千位
  85.     {
  86.       seg_1=0;
  87.       seg_2=1;
  88.       seg_3=1;
  89.       seg_4=1;
  90.     }
  91.     break;
  92.   case 1: //显示百位
  93.     if(set_flag)
  94.     {
  95.       if(        flash_time<50)
  96.       {
  97.         seg_1=1;
  98.         seg_2=0;
  99.         seg_3=1;
  100.         seg_4=1;
  101.       }
  102.       else if(flash_time<100)
  103.       {
  104.         seg_1=1;
  105.         seg_2=1;
  106.         seg_3=1;
  107.         seg_4=1;
  108.       }
  109.       else
  110.       {
  111.         flash_time=0;
  112.       }
  113.     }
  114.     else
  115.     {
  116.       seg_1=1;
  117.       seg_2=0;
  118.       seg_3=1;
  119.       seg_4=1;
  120.     }
  121.     break;
  122.   case 2://显示十位
  123.     if(set_flag)
  124.     {
  125.       if(        flash_time<50)
  126.       {
  127.         seg_1=1;
  128.         seg_2=1;
  129.         seg_3=0;
  130.         seg_4=1;
  131.       }
  132.       else if(flash_time<100)
  133.       {
  134.         seg_1=1;
  135.         seg_2=1;
  136.         seg_3=1;
  137.         seg_4=1;
  138.       }
  139.       else
  140.       {
  141.         flash_time=0;
  142.       }
  143.     }
  144.     else
  145.     {
  146.       seg_1=1;
  147.       seg_2=1;
  148.       seg_3=0;
  149.       seg_4=1;
  150.     }
  151.     break;
  152.   case 3://显示个位
  153.     if(set_flag)
  154.     {
  155.       if(        flash_time<50)
  156.       {
  157.         seg_1=1;
  158.         seg_2=1;
  159.         seg_3=1;
  160.         seg_4=0;
  161.       }
  162.       else if(flash_time<100)
  163.       {
  164.         seg_1=1;
  165.         seg_2=1;
  166.         seg_3=1;
  167.         seg_4=1;
  168.       }
  169.       else
  170.       {
  171.         flash_time=0;
  172.       }
  173.     }
  174.     else
  175.     {
  176.       seg_1=1;
  177.       seg_2=1;
  178.       seg_3=1;
  179.       seg_4=0;
  180.     }
  181.     break;
  182.   }
  183.   Delay_1ms(5);
  184.   
  185.   temp_num++; //循环扫描
  186.   if(temp_num>3) temp_num=0;
  187.   
  188.   flash_time++;           //闪烁的标志
  189.   if(set_flag==0)flash_time=0;

  190.   seg_1=1;          //关闭所有数码管准备下次显示
  191.   seg_2=1;
  192.   seg_3=1;
  193.   seg_4=1;
  194. }
  195. void delayms(unsigned int ms)        //延时函数
  196. {
  197.   unsigned char i=100,j;
  198.   for(;ms;ms--)
  199.   {
  200.     while(--i)
  201.     {
  202.       j=10;
  203.       while(--j);
  204.     }
  205.   }
  206. }
  207. void Conut(void)  //计算距离的函数
  208. {
  209.   static uchar  temp1=0,temp2=0,temp3=0;
  210.   time=(TH0<<8)+TL0;
  211.   TH0=0;
  212.   TL0=0;
  213.   S=time/58;     //算出来是CM
  214.   delayms(10);

  215.         if(start_flag)//开始键按下的时候才开始计数
  216.         {
  217.             if(S<5)// 距离小于5cm就认为有物体了,要计数
  218.          {
  219.                           
  220.                  temp1++;
  221.                 temp3=0;
  222.                 if(temp1>1)
  223.                 {
  224.                         temp1 =0;
  225.                         if(temp2==0)
  226.                         {
  227.                                 LED=1;//关闭指示灯
  228.                                 temp2=1;
  229.                                 counter_num++;
  230.                                 if(counter_num>9999)counter_num=0; //把计数值分解到数码管上显示
  231.                                 counter_buf[0]=counter_num%10000/1000;
  232.                                 counter_buf[1]=counter_num%1000/100;
  233.                                 counter_buf[2]=counter_num%100/10;
  234.                                 counter_buf[3]=counter_num%10;
  235.                         }       
  236.                 }  
  237.          }
  238.          else if(S>6)  //如果距离大于6cm就认为货已经过去了,清除变来过准备下一次计数
  239.          {
  240.                  
  241.                  temp1=0;
  242.                 temp3++;
  243.                 if(temp3>1)
  244.                 {
  245.                         LED=0;//打开指示灯
  246.                         temp3=0;
  247.                         temp2=0;
  248.                        
  249.                 }
  250.          }
  251.    }                                                                                                             
  252. }

  253. //************************************
  254. //定时器初始化
  255. //初始化为10MS定时器       
  256. //************************************
  257. void Time0_init()
  258. {
  259.   TMOD |= 0x01;                         //使用模式1,16位定时器
  260.   TH0   = 0;        //定时器装入初始值10ms
  261.   TL0   = 0;
  262.   EA    = 1;  //总中断
  263.   ET0   = 1;//定时器0初始化
  264.   TR0   = 0;
  265.   
  266. }
  267. //************************************
  268. //定时器初始化
  269. //初始化为60MS定时器       
  270. //************************************
  271. void Time1_init()
  272. {
  273.   TMOD |= 0x10;                         //使用模式1,16位定时器
  274.   TH1   = (65536-6000)/256;        //定时器装入初始值60ms
  275.   TL1   = (65536-6000)%256;
  276.   EA    = 1;  //总中断
  277.   ET1   = 1;//定时器1初始化
  278.   TR1   = 1;
  279. }
  280. //

  281. void  StartModule()                          //T1中断用来扫描数码管和计800MS启动模块
  282. {
  283.   TX=1;                                         //800MS  启动一次模块
  284.   _nop_();
  285.   _nop_();
  286.   _nop_();
  287.   _nop_();
  288.   _nop_();
  289.   _nop_();
  290.   _nop_();
  291.   _nop_();
  292.   _nop_();
  293.   _nop_();
  294.   _nop_();
  295.   _nop_();
  296.   _nop_();
  297.   _nop_();
  298.   _nop_();
  299.   _nop_();
  300.   _nop_();
  301.   _nop_();
  302.   _nop_();
  303.   _nop_();
  304.   _nop_();
  305.   TX=0;
  306. }
  307. /********************************************************************
  308. * 名称 : Main()
  309. * 功能 : 主函数
  310. * 输入 : 无
  311. * 输出 : 无
  312. ***********************************************************************/
  313. void Main(void)
  314. {
  315.   uint try=0;
  316.   uchar timeout_flag=0;
  317.   Time0_init();         //初始化定时器
  318.   Time1_init();
  319.   
  320.   while(1)
  321.   {
  322.    
  323.     StartModule();
  324.     while(!RX)                //当RX为零时等待
  325.         {
  326.            try++;
  327.            if(try>6000)         //等待时间不能太长,防止程序死机
  328.            {
  329.              try=0;
  330.             timeout_flag=1;//置位超时标志
  331.                    break;
  332.                 }
  333.         }
  334.         TH0=0;
  335.           TL0=0;
  336.     TR0=1;                            //开启计数
  337.         if(timeout_flag==0)
  338.         {
  339.             while(RX)                        //当RX为1计数并等待
  340.                 {
  341.                   try++;
  342.                    if(try>6000)          //等待时间不能太长,防止程序死机
  343.                    {
  344.                             try=0;
  345.                                    timeout_flag=1;        //置位超时标志
  346.                                    break;
  347.                         }
  348.                 }
  349.         }
  350.     TR0=0;                                //关闭计数
  351.         if(timeout_flag)//如果超时了
  352.         {
  353.                 TH0=0;
  354.                   TL0=0;
  355.                   timeout_flag=0;
  356.         }
  357.         else//正常数据
  358.         {
  359.             Conut();                        //计算
  360.         }
  361.     delayms(12);                //延时一段时间       
  362.    
  363.   }
  364. }


  365. void time1(void)interrupt 3
  366. {
  367.        
  368.         key_num=KEY_Scan(0); //获取矩阵按键的数值
  369.     switch(key_num)
  370.     {
  371.     case 1:        //开始按键
  372.       start_flag=1;
  373.           set_flag=0;
  374.       break;
  375.     case 2:        //停止按键
  376.       start_flag=0;
  377.       break;
  378.     case 3://设定计数按键
  379.                 if(start_flag==0)
  380.               set_flag=1;
  381.       break;
  382. ……………………

  383. …………限于本文篇幅 余下代码请从51黑下载附件…………
复制代码

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

使用道具 举报

沙发
ID:367110 发表于 2018-7-8 14:09 | 只看该作者
没有potues仿真啊
回复

使用道具 举报

板凳
ID:453974 发表于 2019-1-2 22:36 | 只看该作者
仿真不能实现
还我黑币
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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