全部资料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的制作,中间有很多不懂的问题,都通过询问老师同学和反复实践解决了,最后我们终于制作出了很好的板子。如果说硬件电路是躯体的话,那么软件就是血液,软件编程的正确与否,直接导致了硬件电路功能的实现。程序调试过程中,出现了设置过程中数码管不能闪动、出现误计数的现象。这些都通过增大延时解决了。 我们所做的有关传送带计数包装的设计虽然满足了基本的要求,但还存在着一些不足,比如用独立按键进行预置数,每次按键值增加一个数值会耗费大量时间;我们不经过计时再设计,无法保证货物是否到位,而且如果货物之间的间隔不规则,也将会无法控制。另外,我们也没有考虑掉点保护和单片机抗干扰问题。由于能力有限,很多想法就没有体现在设计中。
单片机源程序如下:
- #include<reg52.h> //头文件
- #include <intrins.h>
- #define uint unsigned int
- #define uchar unsigned char
- sbit seg_1=P3^4;//定义数码管的位选
- sbit seg_2=P3^5;
- sbit seg_3=P3^6;
- sbit seg_4=P3^7;
- sbit TX=P2^5; //超声波传感器的接口
- sbit RX=P2^6;
- sbit LED=P2^7; //指示灯接口
- sbit motor=P1^5; //传送带电机接口
- sbit K1=P1^0; //按键接口
- sbit K2=P1^1;
- sbit K3=P1^2;
- sbit K4=P1^3;
- sbit K5=P1^4;
- uchar code SEG_Table[]= {0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71}; //CC共阴
- char dis_data_buf[4]= {0,0,0,0};
- uchar counter_buf[4]= {0,0,0,0};
- long int set_num=0;
- unsigned long int counter_num=0;
- uchar start_flag=0; //开始标志
- uchar set_flag=0;//设定计数值得标志
- uchar key_num=0; //按键值
- unsigned int time=0; //声波时间
- unsigned int S=0; //距离
- void Delay_1ms(uint i)//1ms延时
- {
- uchar x,j;
- for(j=0; j<i; j++)
- for(x=0; x<=148; x++);
- }
- //*********************************
- //按键扫描程序
- //mode:0,不支持连续按;1,支持连续按;
- //*********************************
- uchar KEY_Scan(uchar mode)
- {
- static uchar key_up=1;//按键按松开标志
- if(mode)key_up=1; //支持连按
- if(key_up&&(K1==0||K2==0||K3==0||K4==0||K5==0))
- {
- //Delay_1ms(10);//去抖动
- key_up=0;
- if(K1==0)return 1;
- else if(K2==0)return 2;
- else if(K3==0)return 3;
- else if(K4==0)return 4;
- else if(K5==0)return 5;
-
- } else if(K1==1&&K2==1&&K3==1&&K4==1&&K5==1)key_up=1;
- return 0;// 无按键按下
- }
- void diplay(uchar *dis_p)
- {
- static uchar temp_num=0;
- static uint flash_time=0;
- P0=SEG_Table[*(dis_p+temp_num)]; //查数组得到数码管段吗
- switch(temp_num)
- {
- case 0:
- if(set_flag) //如果是设定状态下就闪烁
- {
- if(flash_time<50)
- {
- seg_1=0;
- seg_2=1;
- seg_3=1;
- seg_4=1;
- }
- else if(flash_time<100)
- {
- seg_1=1;
- seg_2=1;
- seg_3=1;
- seg_4=1;
- }
- else
- {
- flash_time=0;
- }
- }
- else //正常显示千位
- {
- seg_1=0;
- seg_2=1;
- seg_3=1;
- seg_4=1;
- }
- break;
- case 1: //显示百位
- if(set_flag)
- {
- if( flash_time<50)
- {
- seg_1=1;
- seg_2=0;
- seg_3=1;
- seg_4=1;
- }
- else if(flash_time<100)
- {
- seg_1=1;
- seg_2=1;
- seg_3=1;
- seg_4=1;
- }
- else
- {
- flash_time=0;
- }
- }
- else
- {
- seg_1=1;
- seg_2=0;
- seg_3=1;
- seg_4=1;
- }
- break;
- case 2://显示十位
- if(set_flag)
- {
- if( flash_time<50)
- {
- seg_1=1;
- seg_2=1;
- seg_3=0;
- seg_4=1;
- }
- else if(flash_time<100)
- {
- seg_1=1;
- seg_2=1;
- seg_3=1;
- seg_4=1;
- }
- else
- {
- flash_time=0;
- }
- }
- else
- {
- seg_1=1;
- seg_2=1;
- seg_3=0;
- seg_4=1;
- }
- break;
- case 3://显示个位
- if(set_flag)
- {
- if( flash_time<50)
- {
- seg_1=1;
- seg_2=1;
- seg_3=1;
- seg_4=0;
- }
- else if(flash_time<100)
- {
- seg_1=1;
- seg_2=1;
- seg_3=1;
- seg_4=1;
- }
- else
- {
- flash_time=0;
- }
- }
- else
- {
- seg_1=1;
- seg_2=1;
- seg_3=1;
- seg_4=0;
- }
- break;
- }
- Delay_1ms(5);
-
- temp_num++; //循环扫描
- if(temp_num>3) temp_num=0;
-
- flash_time++; //闪烁的标志
- if(set_flag==0)flash_time=0;
- seg_1=1; //关闭所有数码管准备下次显示
- seg_2=1;
- seg_3=1;
- seg_4=1;
- }
- void delayms(unsigned int ms) //延时函数
- {
- unsigned char i=100,j;
- for(;ms;ms--)
- {
- while(--i)
- {
- j=10;
- while(--j);
- }
- }
- }
- void Conut(void) //计算距离的函数
- {
- static uchar temp1=0,temp2=0,temp3=0;
- time=(TH0<<8)+TL0;
- TH0=0;
- TL0=0;
- S=time/58; //算出来是CM
- delayms(10);
- if(start_flag)//开始键按下的时候才开始计数
- {
- if(S<5)// 距离小于5cm就认为有物体了,要计数
- {
-
- temp1++;
- temp3=0;
- if(temp1>1)
- {
- temp1 =0;
- if(temp2==0)
- {
- LED=1;//关闭指示灯
- temp2=1;
- counter_num++;
- if(counter_num>9999)counter_num=0; //把计数值分解到数码管上显示
- counter_buf[0]=counter_num%10000/1000;
- counter_buf[1]=counter_num%1000/100;
- counter_buf[2]=counter_num%100/10;
- counter_buf[3]=counter_num%10;
- }
- }
- }
- else if(S>6) //如果距离大于6cm就认为货已经过去了,清除变来过准备下一次计数
- {
-
- temp1=0;
- temp3++;
- if(temp3>1)
- {
- LED=0;//打开指示灯
- temp3=0;
- temp2=0;
-
- }
- }
- }
- }
- //************************************
- //定时器初始化
- //初始化为10MS定时器
- //************************************
- void Time0_init()
- {
- TMOD |= 0x01; //使用模式1,16位定时器
- TH0 = 0; //定时器装入初始值10ms
- TL0 = 0;
- EA = 1; //总中断
- ET0 = 1;//定时器0初始化
- TR0 = 0;
-
- }
- //************************************
- //定时器初始化
- //初始化为60MS定时器
- //************************************
- void Time1_init()
- {
- TMOD |= 0x10; //使用模式1,16位定时器
- TH1 = (65536-6000)/256; //定时器装入初始值60ms
- TL1 = (65536-6000)%256;
- EA = 1; //总中断
- ET1 = 1;//定时器1初始化
- TR1 = 1;
- }
- //
- void StartModule() //T1中断用来扫描数码管和计800MS启动模块
- {
- TX=1; //800MS 启动一次模块
- _nop_();
- _nop_();
- _nop_();
- _nop_();
- _nop_();
- _nop_();
- _nop_();
- _nop_();
- _nop_();
- _nop_();
- _nop_();
- _nop_();
- _nop_();
- _nop_();
- _nop_();
- _nop_();
- _nop_();
- _nop_();
- _nop_();
- _nop_();
- _nop_();
- TX=0;
- }
- /********************************************************************
- * 名称 : Main()
- * 功能 : 主函数
- * 输入 : 无
- * 输出 : 无
- ***********************************************************************/
- void Main(void)
- {
- uint try=0;
- uchar timeout_flag=0;
- Time0_init(); //初始化定时器
- Time1_init();
-
- while(1)
- {
-
- StartModule();
- while(!RX) //当RX为零时等待
- {
- try++;
- if(try>6000) //等待时间不能太长,防止程序死机
- {
- try=0;
- timeout_flag=1;//置位超时标志
- break;
- }
- }
- TH0=0;
- TL0=0;
- TR0=1; //开启计数
- if(timeout_flag==0)
- {
- while(RX) //当RX为1计数并等待
- {
- try++;
- if(try>6000) //等待时间不能太长,防止程序死机
- {
- try=0;
- timeout_flag=1; //置位超时标志
- break;
- }
- }
- }
- TR0=0; //关闭计数
- if(timeout_flag)//如果超时了
- {
- TH0=0;
- TL0=0;
- timeout_flag=0;
- }
- else//正常数据
- {
- Conut(); //计算
- }
- delayms(12); //延时一段时间
-
- }
- }
- void time1(void)interrupt 3
- {
-
- key_num=KEY_Scan(0); //获取矩阵按键的数值
- switch(key_num)
- {
- case 1: //开始按键
- start_flag=1;
- set_flag=0;
- break;
- case 2: //停止按键
- start_flag=0;
- break;
- case 3://设定计数按键
- if(start_flag==0)
- set_flag=1;
- break;
- ……………………
- …………限于本文篇幅 余下代码请从51黑下载附件…………
复制代码
|