【Proteus仿真】【51单片机】基于51单片机自动售货机12864屏幕

目录

一、主要功能

二、使用步骤

三、硬件资源

四、软件设计

五、实验现象

一、主要功能

1、LCD12864液晶显示

2、5种商品

3、选择商品后,在规定时间内投入货币能实现累加并根据选择的商品进行结算

4、选择商品后,投入货币小于商品金额,在规定时间后,投入货币全部退还

二、使用步骤

  • 接通电源后LCD1602显示货物界面
  • 系统自动加载五种货物数据到内存中‌
  • 通过矩阵键盘选择商品类型:
    • 数字键对应不同商品分类‌
    • 投币键对应不同硬币价格
    • 当前选择会实时显示在LCD屏幕
    • 通过投币口投硬币:
      • 支持5元、1元、0.5元三种面额‌
      • 投币金额实时显示在找零区域

三、硬件资源

1、51单片机核心模块

2、按键模块

3、蜂鸣器模块

4、继电器模块

5、LCD12864显示模块

四、软件设计

#ifndef LCD12864BU_H

#define LCD12864BU_H

#define LCDLCDDisp_Off 0x3e

#define Page_Add 0xb8//页地址

#define Start_Line 0xC0//行地址

#define LCDCol_Add 0x40//列地址

#define LCDLCDDisp_On 0x3f

/*****液晶显示器的端口定义*****/

#define data_ora P0 /*液晶数据总线*/

sbit LCDDi=P2^0 ; /*数据/指令 选择*/

sbit LCDRW=P2^1 ; /*读/写 选择*/

sbit LCDEnable=P2^2 ; /*读/写 使能*/

sbit cs1=P2^3 ; /*片选1*/

sbit cs2=P2^4 ; /*片选2*/ // 实物片选要互换

sbit RESET=P2^5 ; /*复位信号*/

#include "value.h"

/****************************************************************************

函数功能:LCD延时程序

入口参数:t

出口参数:

****************************************************************************/

void LCDdelay(unsigned int t)

{

unsigned int i,j;

for(i=0;i<t;i++);

for(j=0;j<10;j++);

}

/********************************************************************

* 名称 : LCEdelay_1ms()

* 功能 : 延时1ms函数

* 输入 : q

* 输出 : 无

***********************************************************************/

void LCEdelay_1ms(uint q)

{

uint i,j;

for(i=0;i<q;i++)

for(j=0;j<115;j++);

}

/****************************************************************************

状态检查,LCD是否忙

*****************************************************************************/

void CheckState()

{

unsigned char dat,DATA;//状态信息(判断是否忙)

LCDDi=0; // 数据\指令选择,D/I(RS)="L" ,表示 DB7∽DB0 为显示指令数据

LCDRW=1; //R/W="H" ,E="H"数据被读到DB7∽DB0

do

{

DATA=0x00;

LCDEnable=1; //EN下降源

LCDdelay(2);//延时

dat=DATA;

LCDEnable=0;

dat=0x80&dat; //仅当第7位为0时才可操作(判别busy信号)

}

while(!(dat==0x00));

}

/*****************************************************************************

函数功能:写命令到LCD程序,RS(DI)=L,RW=L,EN=H,即来一个脉冲写一次

入口参数:cmdcode

出口参数:

*****************************************************************************/

void write_com(unsigned char cmdcode)

{

CheckState();//检测LCD是否忙

LCDDi=0;

LCDRW=0;

P0=cmdcode;

LCDdelay(2);

LCDEnable=1;

LCDdelay(2);

LCDEnable=0;

}

/*****************************************************************************

函数功能:LCD初始化程序

入口参数:

出口参数:

*****************************************************************************/

void init_lcd()

{

LCDdelay(100);

cs1=0;//仿真要打开 实物要关闭两屏

cs2=0;

LCDdelay(100);

write_com(LCDLCDDisp_Off); //写初始化命令

write_com(Page_Add+0);

write_com(Start_Line+0);

write_com(LCDCol_Add+0);

write_com(LCDLCDDisp_On);

}

/*****************************************************************************

函数功能:写数据到LCD程序,RS(DI)=H,RW=L,EN=H,即来一个脉冲写一次

入口参数:LCDDispdata

出口参数:

*****************************************************************************/

void write_data(unsigned char LCDDispdata)

{

CheckState();//检测LCD是否忙

LCDDi=1;

LCDRW=0;

P0=LCDDispdata;

LCDdelay(2);

LCDEnable=1;

LCDdelay(2);

LCDEnable=0;

}

/***********************写汉字函数**********************/

void write_yhanzi(uchar n,uchar x,uchar y,uchar * p)

{

uchar i,j,nm,m;

m=0xb8+x;

for(j=0;j<n;j++)

{

if((16*j+y)<64)

{

cs1=1;cs2=0;nm=0x40+y+16*j;

}

else

{

cs1=0;cs2=1;nm=0x40+y+16*(j-4);

}

write_com(m);

write_com(nm);

for(i=0;i<16;i++)

{

write_data(*p);p++;

}

write_com(m+1);

write_com(nm);

for(i=16;i<32;i++)

{

write_data(*p);p++;

}

}

}

void write_yhanzi_fanbai(uchar n,uchar x,uchar y,uchar * p,uchar fanbai)

{

uchar i,j,nm,m;

m=0xb8+x;

for(j=0;j<n;j++)

{

if((16*j+y)<64)

{

cs1=1;cs2=0;nm=0x40+y+16*j;

}

else

{

cs1=0;cs2=1;nm=0x40+y+16*(j-4);

}

write_com(m);

write_com(nm);

for(i=0;i<16;i++)

{

if(fanbai==0)

write_data(*p);

else

write_data(~(*p));

p++;

}

write_com(m+1);

write_com(nm);

for(i=16;i<32;i++)

{

if(fanbai==0)

write_data(*p);

else

write_data(~(*p));

p++;

}

}

}

/***********************写数字函数**********************/

void write_shuzi(uchar n,uchar x,uchar y,uchar * p,uchar fanbai)

{

uchar i,j,nm,m;

m=0xb8+x;

for(j=0;j<n;j++)

{

if((8*j+y)<64)

{

cs1=1;cs2=0;nm=0x40+y+8*j;

}

else

{

cs1=0;cs2=1;nm=0x40+y+8*(j-8);

}

write_com(m);

write_com(nm);

for(i=0;i<8;i++)

{

if(fanbai==0)

write_data((*p));

else

write_data(~(*p));

p++;

}

write_com(m+1);

write_com(nm);

for(i=8;i<16;i++)

{

if(fanbai==0)

write_data((*p));

else

write_data(~(*p));

p++;

}

}

}

/**********************************************************

*函数名: write_shu16

*功能:在12864上显示16进制数据

*说明:

*输入:无

*返回:无

**********************************************************/

void write_shu16(uchar x,uchar y,uchar dat,uchar fanbai)

{

if(dat>=100)

{

write_shuzi(1,x,y-8,shuzi[dat/100],fanbai);

write_shuzi(1,x,y,shuzi[dat%100/10],fanbai);

write_shuzi(1,x,y+8,dian[0],fanbai);//.

write_shuzi(1,x,y+16,shuzi[dat%10],fanbai);

}

else

{

write_shuzi(1,x,y,shuzi[dat/10],fanbai);

write_shuzi(1,x,y+8,dian[0],fanbai);//.

write_shuzi(1,x,y+16,shuzi[dat%10],fanbai);

}

}

void write_time(uchar x,uchar y,uchar dat,uchar fanbai)

{

write_shuzi(1,x,y,shuzi[dat/10],fanbai);

write_shuzi(1,x,y+8,shuzi[dat%10],fanbai);

}

/*****************************************************************************

函数功能:清除LCD内存程序

入口参数:pag,col,hzk

出口参数:

*****************************************************************************/

void Clr_Scr()

{

unsigned char j,k;

cs1=1; //左、右屏均开显示

cs2=1;

write_com(Page_Add+0);

write_com(LCDCol_Add+0);

for(k=0;k<8;k++)//控制页数0-7,共8页

{

write_com(Page_Add+k); //每页每页进行写

for(j=0;j<64;j++) //每页最多可写32个中文文字或64个ASCII字符

{

write_com(LCDCol_Add+j);

write_data(0x00);//控制列数0-63,共64列,写点内容,列地址自动加1

}

}

}

/*****************************************************************************

函数功能:左屏位置显示

入口参数:page,column,hzk

出口参数:

*****************************************************************************/

void Bmp_Left_Disp(unsigned char page,unsigned char column, unsigned char code *Bmp)

{

unsigned char j=0,i=0;

for(j=0;j<2;j++)

{

write_com(Page_Add+page+j);

write_com(LCDCol_Add+column);

for(i=0;i<16;i++)

{

write_data(Bmp[128*j+i]);

LCEdelay_1ms(50);

}

}

}

void Bmp_Left_Disp_hanzi(unsigned char page,unsigned char hang, unsigned char code *Bmp)

{

unsigned char j=0,i=0;

for(j=0;j<2;j++)

{

write_com(Page_Add+page+j);

write_com(LCDCol_Add+hang);

for(i=0;i<16;i++)

write_data(Bmp[0x00]);

}

}

void clear_12864()

{

uchar x,y;

cs1=1;

cs2=0;

for(x=0;x<8;x++)

{

write_com(0xb8+x);

for(y=0;y<64;y++)

{

write_data(0X00);

}

}

}

/*****************************************************************************

函数功能:右屏位置显示

入口参数:page,column,hzk

出口参数:

*****************************************************************************/

void Bmp_Right_Disp(unsigned char page,unsigned char column, unsigned char code *Bmp)

{

unsigned char j=0,i=0;

for(j=0;j<2;j++)

{

write_com(Page_Add+page+j);

write_com(LCDCol_Add+column);

for(i=64;i<128;i++)

{

write_data(Bmp[128*j+i]);

LCEdelay_1ms(50);

}

}

}

void qingling()

{

uchar x,y ;

cs1=0;

cs2=0;

write_com(0x3f);

write_com(0xc0);

for(x=0;x<8;x++)

{

write_com(0xb8+x);

write_com(0xc0);

for(y=0;y<64;y++)

{

write_data(0x00);

}

write_com(0xb8+x+1);

write_com(0xc0);

for(y=0;y<64;y++)

{

write_data(0x00);

}

}

}

#endif

五、实验现象

演示视频:

【51单片机-B005】【protues仿真】基于51单片机自动售货机12864屏幕1仿真