1.背景及意義
在工業生產的早期階段,人們對檢測對象的數據獲取和處理都是靠人工來完成的,甚至處理隨機誤差和系統誤差都是以人工方法進行的。隨著全球化和市場競爭的加劇,企業需要快速、準確地處理大量零部件,以滿足不斷變化的市場需求。然而傳統的計數和檢測方法往往效率低下,且容易出錯,無法滿足現代制造業的需求,因此,迫切需要智能產線零部件自動計數系統的技術誕生。該技術基于微處理器的智能檢測系統,包含了測量檢驗、信息處理和決策輸出等多種內容,其范疇遠超過傳統的“測量”。該技術可以對生產線上的零部件進行自動計數和檢測,篩選合格與不合格產品,從而實現生產流程的自動化和智能化。這不僅提高了生產效率,降低了人工成本,還能確保產品的質量穩定和一致性。同時,這種系統還可以為產品設計和生產提供寶貴的數據支持,幫助企業優化產品性能和質量,為企業提供了一種高效、準確的解決方案。
總之,智能產線零部件自動計數系統的研究和發展,符合我們推動制造業轉型升級的導向。通過引入先進技術,提高生產效率和產品質量,有助于企業實現可持續發展,為經濟發展做出貢獻。
2.設計目標
1)通過按鍵電路設置檢測零件的個數,并通過LCD顯示;
2)通過脈沖信號模擬產線零部件的計數信號;
3)單片機接收來自電機電機電路的脈沖信號并進行計數;
4)當零部件數量達到設定值后,系統停止工作,蜂鳴報警其發出聲報警。
3.設計內容
3.1 硬件設計
3.1.1各部件工作原理
單片機芯片內部邏輯結構
1.中央處理器(CPU):中央處理器簡稱CPU,是單片機的核心,完成運算和控制操作。按其功能,中央處理器包括運算器和控制器兩部分電路。
2.運算器電路:運算電路時單片機的運算部件,用于實現算術和邏輯運算。運算電路以ALU為核心,基本的算術和邏輯運算均在其中進行,包括加、減、乘、除、增量、減量、十進制調整、比較等算術運算,與、或、、異或等邏輯運算,左、右、移位和半字節交換等操作。運算和操作結果的狀態由狀態寄存器(PSW)保存。
3.控制器電路:控制電路時單片機的指揮控制部件,保證單片機各部分能自動而協調地工作。單片機執行指令是在控制電路的控制下進行的。首先從程序存儲器中讀出指令,送指令寄存器保存,然后送指令譯碼器進行譯碼,譯碼結果送定時控制邏輯電路,由定時控制邏輯產生各種定時信號和控制信號,再送到系統的各個部件去進行相應的操作。這就是執行一條指令的全過程,執行程序就是不斷重復這一過程。
4.內部數據存儲器:內部數據存儲器包括RAM(128 x8)和RAM地址寄存器等。實際上80C51芯片中共有256個RAM單元,但其中后128單元被專用寄存器占用,供用戶使用的只是前128單元,用于存放可讀寫的數據。因此,通常所說的內部數據存儲器是指前128單元,簡稱“內部RAM”。
5.內部程序存儲器:內部程序存儲器包括ROM(4Kx8)和程序地址寄存器等。80C51共有4KB掩膜ROM,用于存放程序和原始數據。因此稱之為程序存儲器,簡稱“內部ROM”。
6.定時器/計數器:出于控制應用的需要,80C51共有兩個16位的定時器/計數器,以實現定時或計數功能,并以其定時或計數結果對單片機進行控制。
7.并行I/O口:MCS-51共有4個8位的I/O口(P0、P1、、P2、P3),以實現數據的并行輸入輸出。
8.串行口:MCS-51單片機有一個全雙公的串行口,以實現單片機和其它數據設備之間的串行數據傳送。該串行口功能較強,即可作為全雙工異步通信收發器使用,也可作為同步移位器使用。
9.中斷控制系統:MCS-51單片機的中斷功能較強,以滿足控制應用需要。80C51共有5個中斷源,即外中斷2個,定時/計數中斷2個,串行中斷1個。全部中斷分為高級和低級共兩個優先級別。
10.時鐘電路:MCS-51芯片的內部有時鐘電路,但石英晶體和微調電容需外接,時鐘電路為單片機產生時鐘脈沖序列,典型的晶振頻率為12MHZ。
11.位處理器:單片機主要用于控制,需要有較強的位處理功能,因此位處理器是它的必要組成部分,在一些書中常把位處理器稱為布爾處理器。位處理器以狀態寄存器中的進位標志位C為累加器,可進行置位、復位、取反、等于“0” 轉移、等于“1”轉移且清“0”以及C可尋址位之間的傳送、邏輯與、邏輯或等位操作。位處理操作也是通過運算器實現的。必須特別指出,位處理器是單片機的重要內容,因為它是單片機實現控制功能的保證。
12.總線:上述這些部件都是通過總線連接起來,才能構成一個完整的單片機系統。總線結構減少了單片機的連線和引腳,提高了集成度和可靠性。從上述內容可以看出,雖然MCS-51只是一個芯片,但“麻雀雖小五臟俱全”,作為計算機應該具有的基本部件在單片機中幾乎都包括,因此,實際上它已經是一個簡單的微型計算機系統了,應當按計算機系統的概念來理解單片機。
本設計采用的是AT89C51,它的主要性能:
·與MCS-51 兼容
·4K字節可編程閃爍存儲器
·壽命:1000寫/擦循環
·數據保留時間:10年
·全靜態工作:0Hz-24MHz
·三級程序存儲器鎖定
·128×8位內部RAM
·32可編程I/O線
·兩個16位定時器/計數器
·5個中斷源
·可編程串行通道
·低功耗的閑置和掉電模式
·片內振蕩器和時鐘電路
AT89C51管腳圖及各管腳功能
AT89C51管腳圖
AT89C51管腳功能如下:
·VCC:供電電壓。
·GND:接地。
·P0口:P0口為一個8位漏級開路雙向I/O口,每腳可吸收8TTL門電流。當P1口的管腳第一次寫1時,被定義為高阻輸入。P0能夠用于外部程序數據存儲器,它可以被定義為數據/地址的第八位。在FIASH編程時,P0 口作為原碼輸入口,當FIASH進行校驗時,P0輸出原碼,此時P0外部必須被拉高。
·P1口:P1口是一個內部提供上拉電阻的8位雙向I/O口,P1口緩沖器能接收輸出4TTL門電流。P1口管腳寫入1后,被內部上拉為高,可用作輸入,P1口被外部下拉為低電平時,將輸出電流,這是由于內部上拉的緣故。在FLASH編程和校驗時,P1口作為第八位地址接收。
·P2口:P2口為一個內部上拉電阻的8位雙向I/O口,P2口緩沖器可接收,輸出4個TTL門電流,當P2口被寫“1”時,其管腳被內部上拉電阻拉高,且作為輸入。并因此作為輸入時,P2口的管腳被外部拉低,將輸出電流。這是由于內部上拉的緣故。P2口當用于外部程序存儲器或16位地址外部數據存儲器進行存取時,P2口輸出地址的高八位。在給出地址“1”時,它利用內部上拉優勢,當對外部八位地址數據存儲器進行讀寫時,P2口輸出其特殊功能寄存器的內容。P2口在FLASH編程和校驗時接收高八位地址信號和控制信號。
·P3口:P3口管腳是8個帶內部上拉電阻的雙向I/O口,可接收輸出4個TTL門電流。當P3口寫入“1”后,它們被內部上拉為高電平,并用作輸入。作為輸入,由于外部下拉為低電平,P3口將輸出電流(ILL)這是由于上拉的緣故。
·P3口也是復用口,可作為AT89C51的一些特殊功能口,如下:
·P3.0 RXD:串行輸入口;
·P3.1 TXD:串行輸出口;
·P3.2 /INT0:外部中斷0;
·P3.3 /INT1:外部中斷1;
·P3.4 T0:計時器0外部輸入;
·P3.5 T1:計時器1外部輸入;
·P3.6 /WR:外部數據存儲器寫選通;
·P3.7 /RD:外部數據存儲器讀選通;
同時,P3口為閃爍編程和編程校驗接收一些控制信號。
·RST:復位輸入。當振蕩器復位器件時,要保持RST腳兩個機器周期的高電平時間。
·ALE/PROG:當訪問外部存儲器時,地址鎖存允許的輸出電平用于鎖存地址的地位字節。在FLASH編程期間,此引腳用于輸入編程脈沖。在平時,ALE端以不變的頻率周期輸出正脈沖信號,此頻率為振蕩器頻率的1/6。因此它可用作對外部輸出的脈沖或用于定時目的。然而要注意的是:每當用作外部數據存儲器時,將跳過一個ALE脈沖。如想禁止ALE的輸出可在SFR8EH地址上置0。此時, ALE只有在執行MOVX,MOVC指令是ALE才起作用。另外,該引腳被略微拉高。如果微處理器在外部執行狀態ALE禁止,置位無效。
·PSEN:外部程序存儲器的選通信號。在由外部程序存儲器取指期間,每個機器周期兩次/PSEN有效。但在訪問外部數據存儲器時,這兩次有效的/PSEN信號將不出現。
·EA/VPP:當/EA保持低電平時,則在此期間外部程序存儲器(0000H-FFFFH),不管是否有內部程序存儲器。注意加密方式1時,/EA將內部鎖定為RESET;當/EA端保持高電平時,此間內部程序存儲器。在FLASH編程期間,此引腳也用于施加12V編程電源(VPP)。
·XTAL1:反向振蕩放大器的輸入及內部時鐘工作電路的輸入。
·XTAL2:來自反向振蕩器的輸出。
BUTTON(按鍵)
“BUTTON”是一種基本的元件,其主要功能是控制電路的開關,實現電路的各項功能對于"BUTTON"元件,其工作原理相對簡單。當按鈕未被按下前,電路是斷開的,按下按鈕后,按鈕的觸頭被連通,電路也被接通。這種情況對應的是常開觸頭(NO)。相反,如果按鈕的觸頭原本是閉合的,那么在按下按鈕后,觸頭被斷開,電路也被分斷,這種情況對應的是常閉觸頭(NC)
BUZZER(蜂鳴器)
“BUZZER”的主要功能是發出聲音。在Proteus中,"BUZZER"通常被用作一種測試工具,用來驗證電路的工作狀態。當你在Proteus中使用“BUZZER”時,它會發出一種短暫的聲音,以幫助你確定電路是否正常工作。"BUZZER"的工作原理主要依賴于其驅動方式。在Proteus中,"BUZZER"通常被用作一種測試工具,用來驗證電路的工作狀態。使用“BUZZER"時,它會發出一種短暫的聲音,以幫助確定電路是否正常工作。"BUZZER"的驅動方式主要分為兩種:有源和無源。有源”BUZZER"只需要加電壓就可以發出聲音,而無源”BUZZER”則需要有特定頻率的信號才能發出聲音。
(4)CAP(無極性電容)
無極性電容器是一種電容器,它沒有正負極性。這意味著這種電容器既沒有正電極也沒有負電極,因此可以在任何方向上連接到電路中為容由人工無極性電容器的工作原理無極性電容器主要用于純交流電路,并且由于其適中的電容量,也可以用于高頻濾波。它們不會根據施加的直流電壓的極性來阻止電流流動,而是像所有電容器一樣,基本上會阻止直流電流。
(5)CRYTAL(晶體振蕩器)
“CRYTAL”通常被用作晶振元件的標識符。晶振(Crystal)是一種電子元件,它能產生穩定的頻率信號,對于許多電子設備來說是非常重要的基礎部件。在Proteus中,晶振的主要作用是提供穩定的時鐘信號,用于驅動整個電路的運行。在實際的電路設計中,晶振的選取和布局是非常關鍵的。因為晶振的特性,比如頻率、精度、溫度系數等,都會直接影響到最終電路的性能。所以在使用Proteus進行電路設計時,需要仔細選擇合適的晶振,并合理安排其位置,以確保電路的正常工作。
LED(發光二極管)
LED(發光二極管)的作用主要是作為指示燈,用于顯示電路的工作狀態。當電路中的電流流過LED時,LED就會發出光亮,從而反映出電路是否正常工作。LED的工作原理是基于半導體材料的特性。當電子與空穴復合時,會釋放出能量,這些能量會轉化為光能并發射出來,形成可見光。因此,LED可以看作是一種能夠將電能直接轉換成光能的裝置。在電路圖中,電流經過一個電阻后,才到達LED燈的,這個電阻在電路中起到限流的作用,防止電流過大損壞LED。值得注意的是,LED的亮度并不是由其本身決定的,而是由外部電路決定的。例如,通過改變電源電壓、調整電阻值等方式,可以調節LED的亮度。此外,Proteus還支持對LED進行顏色設置,使得在仿真過程中,LED的顏色可以隨著電路的工作狀態而變化,更加直觀地反映出電路的工作狀態。
LM016L(LCD顯示屏)
LMO16L是一款液晶顯示模塊,其主要的工作原理是利用HD44780控制器進行控制。HD44780具有簡單而功能較強的指令集,可以實現字符移動、閃爍等功能。LMO16L的工作原理主要體現在以下幾個方面:
1.通信方式:LMO16L與單片機MCU(Microcontroller Unit)的通信可以采用8位或者4位并行傳輸兩種方式。
2.控制指令:通過對HD44780寫入控制指令,HD44780產生顯示驅動信號來驅動LMO16L0。
3.顯示功能:HD44780的控制指令主要有:清除顯示(Clear Display)、地址歸位(Return Home)、輸入模式設定(Entry Mode Set)、顯示開/關控制(Display On/Off Control)、功能設定。
4.引腳功能:LMO16L的引腳功能包括讀/寫以及指令/數據功能,還有控制指令的發送。
5.液晶顯示:LMO16L液晶模塊采用HD44780控制器,可以實現字符移動、閃爍等功能,并且可以存儲80個字符碼。
(8)MOTOR(步進電機)
MOTOR通常代表步進電機。步進電機是一種將電脈沖信號轉換為角位移的執行機構,通俗一點講,當步進驅動器接收到一個脈沖信號,它就驅動步進電機按設定的方向轉動一個固定的角度。可通過控制脈沖數來控制角位移量,從而達到準確的定位目的,也可通過控制脈沖的頻率來控制電機的轉速和加速度;從而達到調速的目的在Proteus中,步進電機的工作原理主要體現在以下幾個方面:
1.工作方式:步進電機有多種工作方式,比如三相單三拍、三相雙三拍和三相六拍等。每一種工作方式都有其特定的脈沖序列和頻率,不同的工作方式會導致電機的轉速和轉向有所不同。
2.控制指令:步進電機的轉速和轉向主要由控制指令決定。常見的控制指令包括脈沖頻率、脈沖數量和脈沖寬度等。這些參數的不同組合可以實現不同的運動效果。
3.步進角度:步進電機每轉動一圈,需要接受多少個脈沖。這個數值被稱為步進角度,步進角度的大小決定了電機的轉動速度和精度。步進角度可以通過公式計算得出,其中m為定子繞組的相數,z為轉子的齒數。
(9)PNP(三極管)
PNP三極管主要用于放大和開關操作。PNP三極管的工作原理是,當基極電壓低于0.7V時,流過集電極的電流瞬間增大PNP三極管的工作狀態主要取決于基極和發射極之間的電壓差。當基極電壓低于0.7V時,三極管導通,此時流過集電極的電流增大。PNP三極管的工作原理可以概括為:當基極電壓低于0.7V時,流過集電極的電流瞬間增大。三極管做開關時,工作在截止和飽和兩個狀態;通過控制三極管的基極電壓Ub來控制三極管的導通與斷開。PNP三極管的工作原理與NPN三極管有所不同。NPN三極管的工作原理是,當基極電壓大于0.7V時,三極管導通,當基極電壓小于0.7V時,三極管截止在實際電路設計中,PNP三極管常被用作開關,其工作原理是通過改變基極電壓來控制三極管的導通與斷開,從而實現電路的開關控制。
(10)POP-HG(滑動電阻)
POT-HG代表滑動變阻器。滑動變阻器在電路中主要用于調節電阻值,從而改變電流或電壓,進而影響電路的性能。
POT-HG的工作原理是,你可以在原理圖中插入POT-HG元件,然后通過拖動滑塊來改變電阻值。POT-HG的電阻值可以在運行時動態改變,你可以通過鼠標左鍵單擊滑塊中心,然后按住并拖動滑塊來改變電阻值。此外,POT-HG的調整精度為1%,也就是說,可以精確地調整電阻值到滿刻度的1%左右。在實際應用中,POT-HG可以用于許多場景,例如作為反饋控制器,調節某個設備的輸出,或者作為調節燈光亮度的裝置等。
(10)RELAY(繼電器)
繼電器的主要作用是實現電路的開關控制,特別是在需要控制大功率設備的情況下,繼電器能夠發揮出其優勢。繼電器的工作原理基于電磁效應,當電流通過繼電器的線圈時,會產生磁場,使得繼電器的觸點發生變化,從而實現電路的開關控制。在實際應用中,繼電器常常被用于控制大功率設備的開關,例如驅動電燈泡、電機等。例如,在Proteus中,你可以通過5V和GND輸入信號來控制通斷12V供電的繼電器電路來點亮和熄滅LED。此外也可以通過三極管放大電流,驅動繼電器工作。這種方式的工作原理是通過三極管將1O口輸出的電流放大來驅動繼電器工作。
RESSPACK-8(排電阻)
在Proteus中,排阻(Resistor Pack)是一種特殊的電阻,它是將若干個參數完全相同的電阻集中封裝在一起,組合制成的。排阻一般應用在數字電路上,比
如作為某個并行口的上拉或者下拉電阻用排阻的工作原理是,當我們在原理圖中使用排阻時,它會被視為一組相同的電阻,這樣就可以方便地控制整個電路的電阻值。例如,如果我們需要設置一個特定的電阻值,我們只需更改排阻的設定值,而不必單獨更改每個電阻的值此外,排阻還可以用于模擬實際電路中的電阻連接方式。例如,在某些情況下,我們可能希望模擬一個串聯或并聯的電阻網絡,這時就可以使用排阻來完成總的來說,排阻在Proteus中的主要作用是簡化電路設計過程,提高電路設計效率,同時也可以模擬實際電路中的電阻連接方式,使電路設計更加真實可靠。
3.1.2硬件接線圖
3.1.3 各硬件模塊的功能介紹
(1)系統控制電路:
該系統控制電路的功能如下
1.管理和協調各部件的工作:系統控制電路負責管理和協調單片機內部的各種功能模塊,如CPU、存儲器、輸入/輸出端口等,確保它們能夠有序地協同工作,從而實現產品計數,報警,實時顯示產品計數數量等功能。
2.控制系統的運行狀態:系統控制電路通過控制各個模塊的工作狀態,比如開啟連接在9號口的復位電路便可實現。調整模塊之間的工作關系等,便可控制整個系統的運行狀態
3.處理和響應外部事件:系統控制電路還負責接收和處理來自外部的各種事件,比如按鍵按下P1.3口的開關接通電源,整個計數系統便會開始工作。
4.提供系統的基本功能:系統控制電路不僅要保證單片機的基本功能正常運行,還要支持一些高級功能,比如定時、計數、數學運算、邏輯運算等。
(2)按鍵電路:
按鍵電路的主要作用包括:
1.接收用戶操作輸入:按鍵電路可以接收用戶按下的按鍵信號,將其轉換為數字信號,并將其傳遞給單片機進行處理。
2.觸發設置計數初值操作:當設置按鍵被按下時,按鍵電路便會進入輸入狀態,此時只要根據需求按下對應的數字按鈕便可輸入用戶需要的初值(初值最大值為9999)。
4.提供用戶交互界面:按鍵電路是單片機與用戶之間的交互界面,通過按鍵的不同狀態,可以實現用戶輸入不同初值的功能。
(3)LCD顯示電路:
LCD顯示電路
的主要作用包括:
1.顯示數據和程序信息:LCD顯示電路可以將單片機內部的數據和程序信息顯示出來,比如顯示當前計數的具體數值,設置的計數初值。
2.提供用戶交互界面:LCD顯示電路是單片機與用戶之間的另一個交互界面,通過顯示不同的信息,可以向用戶反饋實時計數系統的數值。
3.支持多種字符和符號的顯示:LCD顯示電路支持多種字符和符號的顯示,可以顯示數字、字母、符號等。
(4)蜂鳴器電路:
當用戶根據需求設置好計數系統初值后按下開始按鈕計數系統便開始工作,當實際計數數值與設置的初值相等時,蜂鳴報警器接收到來自計數器T1的信號后便開始報警,按下復位按鈕后報警停止。
(4)LED指示電路:
該LED燈連接單片機的P1.4口,一旦單片機開始工作該LED便常亮。
(5)電機電路:
產品到達以脈沖的形式進行模擬,通過調整步進電機的轉速和轉動的角度,便可形成有規律的脈沖,脈沖由P3.2口進行接收,當計數數值達到設定值后,便會觸發外部中斷0,外部中斷0被觸發之后,計數系統將停止工作,蜂鳴報警器將發聲報警,提醒工人計數工件已經到達設定值。
3.2 軟件設計
3.2.1 程序代碼圖
(3)軟件流程圖:
4.設計結果
4.1仿真結果
(1)實驗開始前,各裝置準備就緒:
(2)實驗過程,各裝置運行狀態:
(3)實驗結束時,產品數達到設定值,系統停止工作,觸發蜂鳴器報警報警,LED工作指示燈一直亮紅燈:
4.2 結果分析
在按下開始按鈕前,需要對計數系統進行初值設置,按下按鍵電路中的設置按鈕后,便可進入設置模式,根據用戶的需求設置好初值后按下按鍵電路中的確定鍵后,初值便設置完成。LCD顯示屏上的“set number”處便會帶有設置好的初值,按下按鈕后,計數系統便開始工作。產品到達以脈沖的形式進行模擬,通過調整步進電機的轉速和轉動的角度,便可形成有規律的脈沖,脈沖由P3.2口進行接收,當計數數值達到設定值后,便會觸發外部中斷0,外部中斷0被觸發之后,計數系統將停止工作,蜂鳴報警器將發聲報警,提醒工人計數工件已經到達設定值。
5.總結
智能產線零部件自動計數系統技術,是為提高生產效率、降低人工成本、保證產品質量和實現可追溯性而設計的。通過自動化計數和檢測,可以快速準確地識別出合格零部件,避免人工計數和檢測的誤差和延誤。同時,該系統還可以實現生產過程的可追溯性,方便查找問題和進行質量追溯。
該技術是通過AT89C51單片機為基礎控制裝置實現全部功能。單片機用來計算產線上到達的零部件總數數量,并將零部件總數數量通過LCD顯示屏顯示出來,該技術還為計數系統設置了初值,當實際計數數值達到設置的初值時時,系統自動停止工作,并觸發蜂鳴報警以提示工人產品數量已達到上限。
在設計完該技術后的仿真模擬中,以脈沖來模擬產品數量,LCD顯示屏顯示的兩行字符分別顯示設置初值和實際計數值。總之,智能產線合格零部件自動計數與檢測系統技術是解放生產力,降低人工成本和提高零部件計數和檢測準確率的重要技術段,同時也是實現工業4.0和智能制造的重要技術手段之
一,該技術已基本設計完成,功能基本達到預先要求,在完成該設計過程中,不僅再一次強化了我對于微機原理理論知識的理。
單片機程序如下
#include <reg51.h>
#include <intrins.h>
#define uchar unsigned char
#define uint unsigned int
sbit lcd_rs=P1^0;
sbit lcd_rw=P1^1;
sbit lcd_en=P1^2;
sbit qt=P1^3;
sbit bb=P3^5;
sbit out=P3^6;
sbit led=P1^4;
uint k,qidong,wei=15,kai=0;
uint q=2;
uint she,b=0,a,a1,a2,a3,a4,b1,b2,b3,b4,c,c1;
uint gw,sw,bw,qw;
void delay(uchar z)
{
uint x,y;
for(x=z;x>0;x--)
for(y=110;y>0;y--);
}
void write_com(uchar com)
{
lcd_rs=0;
lcd_en=0;
lcd_rw=0;
P0=com;
delay(5);
lcd_en=1;
delay(5);
lcd_en=0;
}
void write_data(uchar date)
{
lcd_rs=1;
lcd_en=0;
lcd_rw=0;
P0=date;
delay(5);
lcd_en=1;
delay(5);
lcd_en=0;
}
void write_sw(uchar add,uchar date)
{
uchar qian,bai,shi,ge;
qian=date/1000;
bai=date%1000/100;
shi=date%100/10;
ge=date%10;
write_com(0x80+add);
write_data(0x30+qian);
write_data(0x30+bai);
write_data(0x30+shi);
write_data(0x30+ge);
}
void write_s(uchar add,uchar date)
{
write_com(0x80+0x40+add);
write_data(0x30+date);
}
void init()
{
lcd_rw=0;
lcd_en=0;
write_com(0x38);
write_com(0x0c);
write_com(0x06);
write_com(0x01);
write_com(0x80);
}
void write_str(unsigned char x,unsigned char y,unsigned char *s)
{
if (y == 0)
{
write_com(0x80 + x);
}
else
{
write_com(0xC0 + x);
}
while (*s)
{
write_data( *s);
s ++;
}
}
void write_char(unsigned char x,unsigned char y,unsigned char z)
{
if (y == 0)
{
write_com(0x80 + x);
}
else
{
write_com(0xC0 + x);
}
write_data(z);
}
void kscan(void)
{
unsigned char i, temp;
for(i=0;i<4;i++)
{
P2=_crol_(0xfe,i);
temp=P2;
temp=temp&0xf0;
if(temp!=0xf0)
{
delay(5);
temp=P2;
temp=temp&0xf0;
if(temp!=0xf0)
{
temp=P2;
switch(temp)
{
/*1*/case 0xee:
if(she==1)
{a=1;wei--;}
break;
/*2*/case 0xde:
if(she==1)
{a=2;wei--;}
break;
/*3*/case 0xbe:
if(she==1)
{a=3;wei--;}
break;
/*A*/case 0x7e:k=0;break;
/*4*/case 0xed:
if(she==1)
{a=4;wei--;}
break;
/*5*/case 0xdd:
if(she==1)
{a=5;wei--;}
break;
/*6*/case 0xbd:
if(she==1)
{a=6;wei--;}
break;
/*B*/case 0x7d:if(she==1)
{
wei=15;
a1=0;a2=0;a3=0;a4=0;c=0;
write_str(11,1,"0000");
} break;
/*7*/case 0xeb:
if(she==1)
{a=7;wei--;}
break;
/*8*/case 0xdb:
if(she==1)
{a=8;wei--;}
break;
/*9*/case 0xbb:
if(she==1)
{a=9;wei--;}
break;
/*C*/case 0x7b:
write_char(15,1,'<');
she=1;
break;
/***/case 0xe7:break;
/*0*/case 0xd7:
if(she==1)
{a=0;wei--;}
break;
/*#*/case 0xb7:break;
/*D*/case 0x77:
write_char(15,1,' ');
she=0;kai=1;
break;
}
while((temp&0xf0)!=0xf0)
{
temp=P2;temp=temp&0xf0;
}
}
}
}
if((she==1)&&(wei<=14))
{
switch(wei)
{
case 14:
write_s(wei,a4);a4=a;
c=a4;c1=1;
break;
case 13:
write_s(wei,a4);
write_s(wei+1,a3);a3=a;
c=a4*10+a3;c1=2;
break;
case 12:
write_s(wei,a4);
write_s(wei+1,a3);
write_s(wei+2,a2);a2=a;
c=a4*100+a3*10+a2;c1=3;
break;
case 11:
write_s(wei,a4);
write_s(wei+1,a3);
write_s(wei+2,a2);
write_s(wei+3,a1);a1=a;
c=a4*1000+a3*100+a2*10+a1;
c1=4;
break;
}
if(wei<=10)
{
wei=14;a1=0;a2=0;a3=0;a4=0;
}
}
}
void qiti()
{
if(qt==0)
{
q++;
if(q==3)
{
q=1;
}
}
while(!qt);
switch(q)
{
case 1:out=0;EX0=1;break;
case 2:out=1;break;
}
}
void main()
{
IT0=1;
EA=1;
init();
write_str (0,0,"Now number:0000");
write_str (0,1,"Set number:0000");
led=0;
while(1)
{
qiti();
kscan();
write_sw(11,k);
b1=k/1000;
b2=k%1000/100;
b3=k%100/10;
b4=k%10;
if(kai==1)
{
switch(c1)
{
case 1:
if(c==k)
{
EX0=0;q=2;
bb=0;delay(100);bb=1;delay(100);led=1;
}
else led=0;
break;
case 2:
if(c==k)
{
EX0=0;q=2;
bb=0;delay(100);bb=1;delay(100);led=1;
}
else led=0;
break;
case 3:
if(c==k)
{
EX0=0;q=2;
bb=0;delay(100);bb=1;delay(100);led=1;
}
else led=0;
break;
case 4:
if(c==k)
{
EX0=0;q=2;
bb=0;delay(100);bb=1;delay(100);led=1;
}
else led=0;
break;
}
}
}
}
void t0() interrupt 0
{
if(q==1)
{
k++;
}
}
|