欧美极品高清xxxxhd,国产日产欧美最新,无码AV国产东京热AV无码,国产精品人与动性XXX,国产传媒亚洲综合一区二区,四库影院永久国产精品,毛片免费免费高清视频,福利所导航夜趣136

標題: 51單片機自動售貨機源程序與Proteus仿真原理圖及調試過程 [打印本頁]

作者: JN0717    時間: 2022-4-25 20:10
標題: 51單片機自動售貨機源程序與Proteus仿真原理圖及調試過程
此例程可以用于學習單片機技術,基于51單片機制作的自動售貨機仿真設計與調試,keil工程+proteus工程
仿真原理圖如下(proteus仿真工程文件可到本帖附件中下載)


設計了一款以INTEL公司出品的80C51單片機為核心的自動售貨機,并且著重詳細地介紹了自動售貨機的整體系統設計方案、硬件選擇基礎、軟件使用方法及技巧。以80C51作為CPU處理單元連接各個功能模塊;以4*4矩陣鍵盤作為輸入控制模塊對貨物進行種類和數量的選擇以及模擬幣的投入功能;以LCD1602液晶作為顯示模塊來顯示當前的購物狀態以及幣狀態;以LED的顯示來表示當前選擇貨物以及出貨的狀態。通過Protues7.5單片機電路原理圖進行連接布線連接各個模塊;再用Keil uVision3專業編譯軟件完成源程序編譯和調試,最終進行自動售貨機的實驗電路仿真來模擬自動售貨。結合工作原理、系統設計、軟件編譯和實驗仿真來實現自動售貨這一相關功能。

本課題研究的是通過核心單片機80C51控制的自動售貨機。涉及到用keil Uvision3來進行C語言程序的編譯調試,通過protues7.5電路連接來設計系統電路。通過80C51與輸入模塊、輸出顯示模塊、找零模塊、顯示模塊的連接來系統模擬自動售貨這一功能。設計從能根據投入的自動售貨的機器。用4*4矩陣鍵盤來模擬貨物種類以及數量的選擇,再通過鍵盤其他按鍵來模擬投功能。用LCD1602作為輸出顯示模塊,通過液晶顯示來明確按鍵的功能以及自動售貨機的購貨狀態等。用LED燈來表示貨物的種類。因為識別功能是在自動售貨機的外部硬件電路方面來加以具體實施的,而本設計是模擬自動售貨機的功能,所以不考慮識別的模塊設計,在這里只作原理介紹。

系統結構
自動售貨機是集光、機、電一體化的自動售貨裝置,能夠獨立完成自動售貨這一功能。
自動售貨機的工作原理是:在初始化的界面等待顧客按鍵選擇貨物的種類和數量顧客投入,按下確定購買鍵后等待售貨機自動計算所購商品的總價,然后提示顧客投入。所投的經過外部硬件檢測傳感器檢測真假后累加計數。若顧客確認購買系統則跳轉到下一步驟,反之取消購買即退出幣返回到主界面,等待顧客下一步操作。自動售貨機通過幣的總價與和所購商品的總價的差值來進行出貨找零?傮w工作原理如圖2.1:
圖2.1 自動售貨機的總體工作原理圖
2.1.2 自動售貨機的控制子系統概述
自動售貨機的控制子系統由以下幾個部分組成,分別是預設自動售貨系統、金額累加和找零系統、售完檢測系統、售出累計及反饋功能系統。

2.2 自動售貨機的功能簡介
2.2.1 自動售貨機的功能
概述
基本原理:通過矩陣鍵盤來選擇貨物的種類與數量過后自動售貨機提示。自動售貨機的幣識別器對所投幣進行識別,根據金額大小然后將商品選擇權通過LCD液晶顯示給客戶,客戶按鍵選擇后,CPU控制芯片發出指令將所選擇商品從儲備料道中送達取物口。
功能描述:貨物種類一共設有8種,這8種商品通過選擇按鍵進行選擇確認,通過數量選擇按鍵確定購買數量,價格規定為1-8元不等;幣識別器能夠識別各種。在規定的時間內,投了幾次幣后,幣能夠實現自動累加功能,這樣設計會把投入的所有幣總額數目數據傳遞到中央控制元器件進行處理;在超過規定時間后自動關閉,數據處理單元按照總數和購買的數量和價格乘積來進行加減運算累,實現購買和找回的功能。
本設計中有一共有16個按鍵選擇,其中有兩個是貨物選擇鍵,有兩個是數量選擇鍵,此外還有6個幣投入鍵1個確認鍵和1個取消鍵。
2.2.2 自動售貨機的設計思路
圖2.3 自動售貨機系統原理圖
P1口的按鍵值為0X04的時候代表1的投入;
P1口的按鍵值為0X05的時候代表5的投入;
P1口的按鍵值為0X06的時候代表10的投入;
P1口的按鍵值為0X07的時候代表20的投入;
P1口的按鍵值為0X08的時候代表50的投入;
P1口的按鍵值為0X09的時候代表100的投入;
P1口的按鍵值為0X0f的時候代表購物確定“OK”按鈕;
P1口的按鍵值為0X0e的時候代表購物取消“NO”按鈕;
本設計假定自動售貨機的商品種類為8種,價格為1、2、3、4、5、6、7、8元。每一個價格代表一種商品且一經售出就由外部電機自動完成補貨。規定每次最多只能購買10個。貨物選擇:
P1口的按鍵值為OX00的時候代表選擇貨物價格“price+”;
P1口的按鍵值為OX01的時候代表選擇貨物價格“price-”;
P1口的按鍵值為OX02的時候代表選擇貨物數量“num+”;
P1口的按鍵值為OX03的時候代表選擇貨物價格“num-”;
選擇商品1用P0.0控制D1LED燈亮;
選擇商品2用P0.1控制D2LED燈亮;
選擇商品3用P0.2控制D3LED燈亮;
選擇商品4用P0.3控制D4LED燈亮;
選擇商品5用P0.4控制D5LED燈亮;
選擇商品6用P0.5控制D6LED燈亮;
選擇商品7用P0.6控制D7LED燈亮;
選擇商品8用P0.7控制D8LED燈亮;

3  自動售貨機的硬件設計
3.1 80C51的簡介
3.1.1 80C51的基本概述
由INTEL公司出品的MCS-51系列的80C51其實用性非常高。由于它是采用CHMOS的工藝技術制造,所以它是一款穩定性很高的高性能8位單片機,是HCMOS中的最基本的產品之一。在制作工藝的程中不僅繼承和擴展了先前單片機的指令系統和體系結構更是把HMOS的高速高密度的技術特點和CHMOS的低功耗特點相結合。為了滿足需求,在80C51內部置入CPU、RAM(128字節)、I/O(32個雙向輸入輸出)、定時器/計數器(16位)、串行通信口、兩級中斷結構以及片內時鐘震蕩電路。此外,它還可以通過選擇空閑和掉電的方式用于低功耗模式來進行工作,空閑模式下保持串行口、中斷系統、RAM和定時器正常工作而同時凍結CPU來保證其正常運行。掉電模式下,自動保存RAM數據,時鐘震蕩停止、芯片的其他功能停止工作。
圖3.1 80C51單片機內部基本結構
3.1.2 80C51的引腳功能介紹
圖3.2 80C51的引腳圖
80C51單片機的40個引腳大致可分為4類:電源、時鐘、控制和I/O引腳。
在每次使用單片機之前,我們都要使單片機復位,讓CPU以及其他功能部件都處于一個確定的初始狀態,以消除上一次用戶的操作對本次用戶操作的影響。51的RST引腳是復位信號的輸入端。復位信號是高電平有效,持續時間要有24個時鐘周期以上。例如:若MCS-51單片機的時鐘頻率為12MHz,則復位脈沖寬度至少應為2us。通常,80C51的復位有自動上電復位和人工按紐復位兩種
自動上電復位電路的工作原理是:電容在通電的時候相當于短路情況,導致RST引腳上的電位為高電平,這樣電容會因為電阻被充電,然后RST端逐漸降低電壓直到變為低電平,從而使單片機開始正常工作。由于自動售貨機的功能需求,本次設計采用自動上電復位電路。

3.2 LCD1602字符型液晶簡介
3.2.1 LCD1602的概述
LCD1602液晶也叫1602字符型液晶,它是一種專門用來顯示字母、數字、符號等的點陣型液晶模塊。它由若干個5X7或者5X11等點陣字符位組成,每個點陣字符位都可以顯示一個字符,每位之間有一個點距的間隔,每行之間也有間隔,起到了字符間距和行間距的作用,正因為如此所以它不能很好地顯示圖形(用自定義CGRAM,顯示效果也不好)。1602LCD是指顯示的內容為16X2,即可以顯示兩行,每行16個字符液晶模塊(顯示字符和數字)。市面上字符液晶大多數是基于HD44780液晶芯片的,控制原理是完全相同的,因此基于HD44780寫的控制程序可以很方便地應用于市面上大部分的字符型液晶。液晶顯示器以其微功耗、體積小、顯示內容豐富、超薄輕巧的諸多優點,在各類儀表和低功耗系統中得到廣泛的應用。根據顯示內容可以分為字符型液晶,圖形液晶。根據顯示容量又可以分為單行16字,2行16字,兩行20字等等。
3.2.2 LCD1602的硬件結構
圖3.3 LCD1602的基本結構圖
引腳說明:LCD1602一般是16個引腳
第1腳:VSS為接地電源。
第2腳:VDD接5V正電源。
第3腳:VEE為液晶顯示器對比度調整端,通過連接電源正負來調節對比度的強弱。當連接電源正端時對比度最弱,反之連接負極則最高。對比度太高時會產生所謂的“鬼影”,在連接時可以通過接一個電位器來調整對比度。
第4腳:RS為數據命令選擇端,電平為H時選擇數據寄存器、電平為L時選擇指令寄存器。
第5腳:RW為讀寫選擇端,電平為H時進行讀操作,電平為L時進行寫操作。
第6腳:E端為使能端,當E端由高電平跳變成低電平時,液晶模塊執行命令。
第7~14腳:D0~D7為8位雙向數據線。
第15~16腳:空腳或背燈電源,15腳背光正極,16腳背光負極。
3.2.3 LCD1602的指令說明
表3.1 顯示模式設置
  
表3.2 顯示開/關及光標位置
表3.3 數據指針設置
表3.4 其他設置
3.2.4 LCD1602的基本時序操作
LCD1602的基本時序操作以及對應的狀態和輸入輸出如表3.5所示:

表3.5 基本時序操作及對應狀態的輸入輸出
LCD1602的讀寫時序操作如圖3.4、3.5所示:
圖 3.4讀時序操作圖
圖 3.5寫時序操作圖

3.3 4*4矩陣鍵盤簡介
3.3.1 4*4矩陣鍵盤的概述
4*4矩陣鍵盤又是4*4行列鍵盤,它是分別用4條I/O線作為行線和列線組成的鍵盤。每個鍵的位置設置在每條行線和列線在交叉處上,可以知道4*4矩陣鍵盤共有4*4=16個按鍵。這樣的設置可以有效地提高單片機I/O口的利用率,與獨立式按鍵相比大大降低了接口占用率。當設計過程中需要按鍵個數要求比較大時,為了釋放出I/O端口來供其他連接需要時往往采用這種矩陣式按鍵來解決問題。在矩陣鍵盤中,行列線均通過一個按鍵加以連接取代了直接交叉相連。這樣,在很大的程度上增加了按鍵數,而直接將端口線連接在鍵盤上則會減少一倍的按鍵數量。在需要很多按鍵的設計中采用矩陣鍵盤明顯地比獨立式按鍵更合理,而且行列線越多效果越明顯。
3.3.2 4×4矩陣鍵盤的硬件結構

圖3.6 4*4矩陣鍵盤的基本結構圖
在應用矩陣鍵盤的設計中要編譯程序的時候必定會計算出每個按鍵的接口地址是多少以方便編譯,在矩陣鍵盤的按鍵確定上我們可以采用兩種方法:
行掃描法是我們常用的一種識別按鍵的方法,這種方法需要我們逐行逐列進行掃描查詢,分為兩個步驟:
這種確定矩陣鍵盤按鍵的方法也是非常有效的方法,也分為兩個步驟:

3.4 識別系統
3.4.1對硬幣的識別
目前在國內,對于硬幣的識別可采用多種方法,比如激光掃描、應變片測重量、光電管檢測大小等,然而在自動售貨機中采用結構簡單、成本低、測量準確及其非接觸測量等優點集一身的渦流傳感器檢測。
電渦流檢測原理:以高頻的電信號通過一個線圈,在這個過程中產生變化的磁場通過硬幣的表面即變化磁通通過硬幣的表面,相應地硬幣表面上產生電渦流, 并產生反向的變化磁場,以削弱原來線圈產生出來的磁場。然后根據激勵磁場線圈幅值的變化,通過變化的給定值即可測出真假硬幣。

圖3.7 電渦流檢測電路原理圖
圖3.7中Q2所需要的頻率由Q1、L、C4等元件組成的振蕩電路所提供,從而在C點產生一正弦波振蕩信號;然后再A、B 兩點外接一個傳感線圈,當有硬幣投入通過線圈時會改變C點原有信號的幅值大小,而真假硬幣通過線圈時改變的幅值大小是不一樣的,通過對比設定給定真幣的參照值來判斷真假硬幣。
但是在實際應用中,由于某些條件的原因會影響到電子線路元器件的判定值,比如溫漂的影響,由于材質的差異比較小,從而導致信號值得差距變小,若受到的溫漂影響稍微增強一點,那么則很難精確地確檢測出不行的,為此可以采用電橋的方法來進行改善彌補,從而減小由溫漂造成的干擾。圖中L3、L4都是激勵線圈,L3上方放置一個標準的1元硬幣或其它用低碳鋼做成的圓片,L4為檢測有無硬幣通過和是否為真假的激勵線圈,A、B兩信號通過通信模塊同時送到后續的運算放大器之中進行相減,從而抵消因溫漂所造成的影響。


3.5 貨物選擇系統
貨物選擇系統主要通過矩陣鍵盤按鍵操作來完成。4*4矩陣鍵盤是自動售貨機中的輸入裝置,價格低廉,結構簡單,使用方便,在單片機應用系統中得到廣泛地應用。鍵盤按照接口原理可分為編碼鍵盤與非編碼鍵盤兩類,它們的主要區別是識別鍵符及給出相應鍵碼的方法。編碼鍵盤主要是用硬件來實現對鍵的識別,非編碼鍵盤主要是由軟件來實現鍵盤的定義與識別。
CPU可以采用查詢或中斷方式了解有無將鍵輸入,并檢查是哪一個鍵按下,然后通過跳轉指令轉入執行該鍵的功能程序,執行完后再返回主程序。
一個完整的矩陣鍵盤控制程序應該具備以下功能:
圖3.9 貨物選擇系統圖

3.6 出貨及找零系統
在本系統中,總共設計了8種飲料,價格分別為1、2、3、4、5、6、7、8元不等,由顧客通過按鍵選擇確定后,投入售貨機可識別的幣(幣可以累加計數)。當投入的幣總值不夠購買選擇的商品總值時,售貨機顯示金取消交易并退出所投幣,如果所投幣大于等于購買選擇的商品總值時,由售貨機出貨并計算剩余幣。但是在單片機的輸出中只有高電平和低電平之分。在自動售貨機中只需要安裝一個驅動電機,待顧客投入幣后將信號送入系統通過相應電路來驅動電機推出相應商品即可。本設計只模擬實現此功能,負責軟件仿真,暫不考慮硬件電機方面,只作介紹。在這里,我們選用光敏三極管來實現這一功能。當單片機輸出端為高電平時,則驅動二極管發光,使驅動電機電路導通,這時驅動電機開始工作等待信號。當單片機輸出端為低電平時,則二極管熄滅。驅動電機電路斷開,即完成推貨動作,LED燈閃爍。售貨機通過投幣時累計的計數和購買商品的總金額進行相減的運算,在LCD液晶上顯示出余幣的數量,顧客取走貨物后自動退還余幣。
圖3.10 出貨及找零

4  系統的軟件流程圖設計
4.1 自動售貨機貨物選擇流程圖
本設計提供1-8元不等的貨物,分別用1-8的序號對應貨物。當啟動系統后進入初始化界面,等待顧客選擇貨物種類和數量,按鍵“OK”則跳入投幣系統,按鍵“NO”則返回初始化等待界面。在這里只以1號商品作為例子來講解具體流程如圖4.1:
圖4.1 自動售貨機貨物選擇流程圖

4.2 自動售貨機投幣系統流程圖
在4*4矩陣鍵盤上模擬投入幣,若投入一種面值的幣就累加一種面值的幣,如果沒有投入幣或者投入幣值不足購買商品的話則提示繼續投幣。當所投幣足夠時,進入出貨找零系統如圖4.2所示:
圖4.2 自動售貨機投幣系統流程圖

4.3 自動售貨機出貨找零系統流程圖
進入出貨找零系統時,如果購買商品后沒有剩余幣則直接推出商品,若還有剩余幣則找出余幣,如圖4.3所示:
4.3 自動售貨機出貨找零系統流程圖

5.2 仿真結果
設計好程序之后,還需要通過protues7.5和keil3.0來實現程序的調試和仿真,仿真結果圖如下:
圖5.1 初始化等待界面
圖5.2 選擇貨物的種類及數量
圖5.3 貨物選擇并計價
圖5.4 出貨找零
圖5.5 自動復位返回初始化界面

附錄B:系統總圖

單片機源程序如下:
  1. #include<reg51.h>

  2. /*******************define*************************/
  3. #define WAIT_SALE        0                 //定義1602顯示狀態
  4. #define NO_WATER         1                 
  5. #define INPUT_MONEY        2
  6. #define SALING                3
  7. #define CHANGE                4
  8. #define CANCLE                5
  9. #define NO_DATA                0
  10. #define water_change(x, y) ((x) & (~(0x01 << y))) //宏 控制水種類的切換
  11. #define uint unsigned int
  12. #define uchar unsigned char

  13. unsigned char water_total[] = {10, 10, 10, 10, 10, 10, 10, 10};   
  14. unsigned char water_price[] = {1, 2, 3, 4, 5, 6, 7, 8};
  15. uchar code wait_sale[]="for sale";                  //定義所顯示的內容
  16. uchar code no_water[] = "no water!";
  17. uchar code price[] = "price:";
  18. uchar code number[] = "num:";
  19. uchar code sum[] = "SUM:";
  20. uchar code input[] = "INPUT:";
  21. uchar code change[] = "change:";
  22. uchar code put_water[] = "put water...";
  23. uchar code cancle[] = "cancle...";

  24. unsigned char e=0x00;                    
  25. sbit P2_0=P2^0;                       //定義接端口
  26. sbit P2_1=P2^1;
  27. sbit P2_2=P2^2;
  28. sbit P2_3=P2^3;
  29. sbit lcd_en=P3^4;            
  30. sbit rs=P3^2;
  31. sbit rw = P3^3;
  32. /****************************************************/

  33. /***********************function**********************************/
  34. /************lcd 1602*************************/
  35. void lcd_1602_delay(uint z)          //延時
  36. {
  37. uint x,y;
  38. for(x=z;x>0;x--)
  39. for(y=110;y>0;y--);
  40. }

  41. void lcd_1602_write_com(uchar com)   //寫命令
  42. {
  43. rs=0;
  44. rw=0;
  45. P2=com;
  46. lcd_1602_delay(5);
  47. lcd_en=1;
  48. lcd_1602_delay(5);
  49. lcd_en=0;
  50. }

  51. void lcd_1602_write_data(uchar date) //寫數據
  52. {
  53. rs=1;
  54. rw=0;
  55. P2=date;
  56. lcd_1602_delay(5);
  57. lcd_en=1;
  58. lcd_1602_delay(5);
  59. lcd_en=0;
  60. }

  61. void lcd_1602_init()               //LCD1602初始化函數
  62. {
  63. lcd_en=0;
  64. lcd_1602_write_com(0x38);
  65. lcd_1602_write_com(0x0e);
  66. lcd_1602_write_com(0x06);
  67. lcd_1602_write_com(0x01);
  68. }

  69. void lcd_1602_wait_sure()         //顯示'OK'&'NO'界面
  70. {
  71. lcd_1602_write_com(0x80+0x40);
  72. lcd_1602_write_data('O');
  73. lcd_1602_write_data('K');
  74.                
  75. lcd_1602_write_com(0x80+0x4e);
  76. lcd_1602_write_data('N');
  77. lcd_1602_write_data('O');
  78. }

  79. void lcd_1602_show_num(uint num)       // 1602顯示數字的函數
  80. {
  81. if(num <= 9)
  82. {
  83.    lcd_1602_write_data('0'+num);
  84.    lcd_1602_write_data(' ');
  85.   }else if(num >= 10 )
  86. {
  87.    lcd_1602_write_data('0'+num/10);
  88.    lcd_1602_write_data('0'+num%10);
  89.   }
  90. }

  91. void lcd1602_info_display(uint choose, uint num_type, uint num_count)  //1602顯示函數
  92. {
  93. int num;
  94. lcd_1602_write_com(0x01);
  95. switch(choose)
  96.   {
  97. case WAIT_SALE:
  98. lcd_1602_write_com(0x80+0x03);       //
  99. for(num = 0; num < 8; num++)
  100. {
  101. lcd_1602_write_data(wait_sale[num]);        
  102. }
  103. break;
  104. case NO_WATER:
  105. lcd_1602_write_com(0x80+0x03);
  106. for(num = 0; num < 9; num++)
  107.   {
  108.    lcd_1602_write_data(no_water[num]);        
  109.    }
  110. break;
  111. case SALING:
  112. //price
  113. lcd_1602_write_com(0x80+0x00);
  114. for(num = 0; num < 6; num++)
  115.   {
  116.     lcd_1602_write_data(price[num]);
  117.    }
  118. lcd_1602_write_data('0'+(num_type+1));
  119. lcd_1602_write_data(' ');
  120. //number
  121. lcd_1602_write_data(' ');
  122. for(num = 0; num < 4; num++)
  123.           {
  124.            lcd_1602_write_data(number[num]);
  125.            }
  126. lcd_1602_show_num(num_count);
  127.                
  128.                
  129. break;
  130. case INPUT_MONEY:
  131. //need money        
  132. lcd_1602_write_com(0x80+0x00);
  133. for(num = 0; num < 4; num++)
  134.     {
  135.       lcd_1602_write_data(sum[num]);
  136.     }
  137. lcd_1602_show_num(num_type);
  138. //input
  139. lcd_1602_write_data(' ');
  140. lcd_1602_write_data(' ');
  141. for(num = 0; num < 6; num++)
  142.         {
  143.        lcd_1602_write_data(input[num]);
  144.         }
  145. lcd_1602_show_num(num_count);
  146. break;
  147. case CHANGE:
  148. if(!num_count)
  149.                 {
  150.                 //put water
  151.        lcd_1602_write_com(0x80+0x02);
  152.                 for(num = 0; num < 13; num++)
  153.             {
  154. lcd_1602_write_data(put_water[num]);
  155.             }
  156.        }
  157. else
  158. {
  159. //cancle water
  160. lcd_1602_write_com(0x80+0x02);              //取消選擇時寫命令退幣
  161. for(num = 0; num < 9; num++)
  162.         {
  163.              lcd_1602_write_data(cancle[num]);
  164.         }
  165. }
  166. //change
  167. lcd_1602_write_com(0x80+0x43);
  168. for(num = 0; num < 7; num++)
  169.         {
  170.             lcd_1602_write_data(change[num]);
  171.         }
  172. lcd_1602_show_num(num_type);
  173. break;
  174. default:
  175. break;
  176. }
  177. lcd_1602_write_com(0x0c);
  178. }
  179. void lcd_1602_saling(uint type, uint num)
  180. {
  181.         lcd1602_info_display(SALING, type, num);
  182.         lcd_1602_wait_sure();
  183. }

  184. void lcd_1602_inputing(uint need, uint input)
  185. {
  186.   lcd1602_info_display(INPUT_MONEY, need, input);
  187.   lcd_1602_wait_sure();
  188. }
  189. /*************************************************/
  190. void delay1(unsigned int t)           // 延時函數
  191. {
  192. unsigned int i,j;
  193. for(i=0;i<t;i++)
  194. for(j=0;j<10;j++);
  195. }

  196. void out_water()             //推出水函數
  197. {
  198. int i, j = 100;
  199. while(j--)
  200.   {
  201.         for(i = 0; i < 8; i++)
  202.         {
  203.           P0 = water_change(0xff, i);
  204.      delay1(50);
  205.     }
  206.   }
  207. P0 = 0xff;
  208. }

  209. unsigned char key(void)       //按鍵響應函數
  210. {
  211. unsigned char key,key1,key2;
  212. P1=0XF0;
  213. if((P1&0XF0)!=0XF0)           //ked down
  214.     {
  215.        delay1(10);                         //延時去抖動
  216.        if((P1&0XF0)!=0XF0)                  //仍然有鍵按下
  217.       {
  218.         key1=P1&0XF0;                          //讀入列線值
  219.         P1=0X0F;
  220.         key2=P1&0X0F;
  221.         key=key1|key2;
  222. switch(key)                  //按鍵映射
  223. {
  224. case 0xee: e=0x00;break;
  225. case 0xde: e=0x01;break;
  226. case 0xbe: e=0x02;break;
  227. case 0x7e: e=0x03; break;
  228. case 0xed: e=0x04;break;
  229. case 0xdd: e=0x05;break;
  230. case 0xbd: e=0x06;break;
  231. case 0x7d: e=0x07; break;
  232. case 0xeb: e=0x08;break;
  233. case 0xdb: e=0x09;break;
  234. case 0xbb: e=0x0a;break;
  235. case 0x7b: e=0x0b; break;
  236. case 0xe7: e=0x0c;break;
  237. case 0xd7: e=0x0d;break;
  238. case 0xb7: e=0x0e;break;
  239. case 0x77: e=0x0f; break;
  240. }
  241. while((P1&0X0F)!=0X0F);
  242. delay1(10);
  243. return 1;
  244. }
  245.   }
  246. return 0;
  247. }

  248. /*********************************************************************/
  249. /*****************main********************************/
  250. void main()
  251. {
  252. unsigned char ok = 0, water_type = -1,  water_is_choose = 0;
  253. char water_count = 0;
  254. unsigned int flag = 0, money = 0, need_money;

  255. lcd_1602_init();
  256. again:
  257. ok = 0; water_type = -1; water_count = 0; water_is_choose = 0;
  258. flag = 0; money = 0; need_money = 0;        
  259. lcd1602_info_display(WAIT_SALE, 0, 0);
  260. while(!ok)        //choose the water and count
  261. {
  262.   flag=key();
  263.   if(flag)
  264.   {
  265.     switch(e)         //不同的按鍵進行不同的操作
  266.      {
  267.         case(0x00):
  268.         water_type++;
  269.         water_is_choose = 1;
  270.         if(water_type == 8)
  271.                {
  272.              water_type = 0;
  273.                 }
  274. P0 = water_change(0xff, water_type);
  275. break;               
  276. case(0x01):
  277. water_type--;
  278. water_is_choose = 1;
  279. if(water_type == -1 || water_type == -2)
  280. {
  281.   water_type = 7;
  282. }
  283. P0 = water_change(0xff, water_type);
  284. break;
  285. case(0x02):
  286. if(water_is_choose == 1)
  287.   {
  288.      water_count++;
  289.      if(water_count > water_total[water_type])
  290.      {
  291.        water_count = water_total[water_type];
  292.             }
  293.    }
  294. break;
  295. case(0x03):
  296. if(water_is_choose == 1)
  297. {
  298.   water_count--;
  299.   if(water_count < 0)
  300.         {
  301.       water_count = 0;
  302.          }
  303. }                                
  304. break;
  305. case(0x0e):        //  返回
  306. goto again;
  307. break;   
  308. case(0x0f):         //   確認
  309. if(water_is_choose == 1)
  310.          {        
  311.       ok=1;
  312.           }                                
  313.         break;
  314.    default:
  315.    break;                                
  316. }
  317. lcd_1602_saling(water_type, water_count);                        
  318.         }
  319. }
  320.         
  321. //choose ok: calculate the money        //計算總數
  322. need_money = water_count * water_price[water_type];
  323. lcd_1602_inputing(need_money, money);
  324. ok = 0;        
  325. while(!ok)                //get money
  326.         {
  327.                 flag=key();
  328.                 if(flag)
  329.                 {
  330.                         switch(e)
  331. ……………………

  332. …………限于本文篇幅 余下代碼請從51黑下載附件…………
復制代碼

Keil5代碼與Proteus8.8仿真下載:
仿真程序文檔.7z (756.5 KB, 下載次數: 114)

作者: heicad    時間: 2022-4-26 05:16
好資料,51黑有你更精彩!!!
作者: silence-阿    時間: 2022-5-14 18:14
您好啊,“自動售貨機的控制子系統由以下幾個部分組成,分別是預設自動售貨系統、金額累加和找零系統、售完檢測系統、售出累計及反饋功能系統!
我剛試了一遍,請問這里的售出累計及反饋功能系統  能顯示出來嗎?
作者: 2264003351    時間: 2023-1-4 11:30
51黑真的很好哦
作者: gemxie    時間: 2023-1-9 16:29
謝謝樓主分享,下載學習啦




歡迎光臨 (http://m.raoushi.com/bbs/) Powered by Discuz! X3.1