全部資料51hei下載地址:
傳送帶計數器.rar
(336.62 KB, 下載次數: 102)
2018-7-1 04:02 上傳
點擊文件名下載附件
摘要
本設計采用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黑下載附件…………
復制代碼
|