本文设计了一款以AT89C51单片机为核心的自动售货机系统,并且着重详细地介绍了自动售货机的整体系统设计方案、硬件选择基础、软件使用方法及技巧。以AT89C51作为CPU处理单元连接各个功能模块;以4×4矩阵键盘作为输入控制模块对货物进行种类和数量的选择以及模拟货币的投入功能;以LCD1602液晶作为显示模块来显示当前的购物状态以及货币状态;以LED的显示来表示当前选择货物以及出货的状态。
自助售货机原理:
在初始化的界面等待顾客按键选择货物的种类和数量顾客投入货币,按下确定购买键后等待售货机自动计算所购商品的总价,然后提示顾客投入货币。所投的货币经过外部硬件检测传感器检测真假后累加计数。若顾客确认购买系统则跳转到下一步骤,反之取消购买即退出货币返回到主界面,等待顾客下一步操作。自动售货机通过货币的总价与和所购商品的总价的差值来进行出货找零。
仿真:
操作说明:
仿真分析为:
(1)加载Sale.hex文件到AT89C51单片机,点击运行,自动售货机系统进入初始化等待状态,LCD显示“Welcome Sale”,同时等待按键输入。
(2)通过按键“价格+”和“价格-”来选择货物的种类,然后通过“数量+”和“数量-”来选择所购买货物的数量,同时代表被选择货物的LED指示灯亮。
(3)当选择好货物后,按下“确认OK”键进入到投币系统,此时机器会自动计算出所购货物总金额。
(4)(4)当机器计算出总价等待顾客投入货币并按下“确认OK”键后,当投入货币货币值大于或等于总价时就出货并找零,若投入货币货币值小于总价则不能出货只能按下“取消NO”退出所投货币或继续增加投币。
(5)当完成以上步骤后则完成一次自动购物过程,机器自动复位回到初始化界面,同时在操作过程中的任一环节,都可通过按下“取消NO”键,是售货机系统复位到初始状态。
代码:
- #include<reg51.h>
- #define WAIT_SALE 0
- #define NO_WATER 1
- #define INPUT_MONEY 2
- #define SALING 3
- #define CHANGE 4
- #define CANCLE 5
- #define NO_DATA 0
- #define water_change(x, y) ((x) & (~(0x01 << y)))
- #define uint unsigned int
- #define uchar unsigned char
- unsigned char water_total[] = {10, 10, 10, 10, 10, 10, 10, 10};
- unsigned char water_price[] = {1, 2, 3, 4, 5, 6, 7, 8};
- uchar code wait_sale[]=" Welcome Sale "; //定义所显示的内容
- uchar code no_water[] = "No Water!";
- uchar code price[] = "Price:";
- uchar code number[] = "Num:";
- uchar code sum[] = "SUM:";
- uchar code input[] = "INPUT:";
- uchar code change[] = "Change:";
- uchar code put_water[] = "Get Water...";
- uchar code cancle[] = "Cancle...";
- unsigned char e=0x00;
- sbit P2_0=P2^0; //定义接端口
- sbit P2_1=P2^1;
- sbit P2_2=P2^2;
- sbit P2_3=P2^3;
- sbit lcd_en=P3^4;
- sbit rs=P3^2;
- sbit rw = P3^3;
- void lcd_1602_delay(uint z) //延时
- {
- uint x,y;
- for(x=z;x>0;x--)
- for(y=110;y>0;y--);
- }
- void lcd_1602_write_com(uchar com) //写命令
- {
- rs=0;
- rw=0;
- P2=com;
- lcd_1602_delay(5);
- lcd_en=1;
- lcd_1602_delay(5);
- lcd_en=0;
- }
- void lcd_1602_write_data(uchar date) //写数据
- {
- rs=1;
- rw=0;
- P2=date;
- lcd_1602_delay(5);
- lcd_en=1;
- lcd_1602_delay(5);
- lcd_en=0;
- }
- void lcd_1602_init() //LCD1602初始化函数
- {
- lcd_en=0;
- lcd_1602_write_com(0x38);
- lcd_1602_write_com(0x0e);
- lcd_1602_write_com(0x06);
- lcd_1602_write_com(0x01);
- }
- void lcd_1602_wait_sure() //显示'OK'&'NO'界面
- {
- lcd_1602_write_com(0x80+0x40);
- lcd_1602_write_data('O');
- lcd_1602_write_data('K');
-
- lcd_1602_write_com(0x80+0x4e);
- lcd_1602_write_data('N');
- lcd_1602_write_data('O');
- }
- void lcd_1602_show_num(uint num) // 1602显示数字的函数
- {
- if(num <= 9)
- {
- lcd_1602_write_data('0'+num);
- lcd_1602_write_data(' ');
- }else if(num > 10 )
- {
- lcd_1602_write_data('0'+num/10);
- lcd_1602_write_data('0'+num%10);
- }
- }
- void lcd1602_info_display(uint choose, uint num_type, uint num_count)
- {
- int num;
- lcd_1602_write_com(0x81);
- switch(choose)
- {
- case WAIT_SALE:
- lcd_1602_write_com(0x80+0x01); //
- for(num = 0; num < 13; num++)
- {
- lcd_1602_write_data(wait_sale[num]);
- }
- break;
- case NO_WATER:
- lcd_1602_write_com(0x80+0x03);
- for(num = 0; num < 9; num++)
- {
- lcd_1602_write_data(no_water[num]);
- }
- break;
- case SALING:
- lcd_1602_write_com(0x80+0x00);
- for(num = 0; num < 6; num++)
- {
- lcd_1602_write_data(price[num]);
- }
- lcd_1602_write_data('0'+(num_type+1));
- lcd_1602_write_data(' ');
- lcd_1602_write_data(' ');
- for(num = 0; num < 4; num++)
- {
- lcd_1602_write_data(number[num]);
- }
- lcd_1602_show_num(num_count);
- break;
复制代码
|