标题:
51单片机+LCD12864的简易计算器Proteus仿真源程序
[打印本页]
作者:
158751hei0141
时间:
2021-3-23 21:09
标题:
51单片机+LCD12864的简易计算器Proteus仿真源程序
之前看到网上利用51和12864做计算器的资源比较少,找了很久才找到了一个帖子是用12864做的计算器,于是下载下来后做了一定程度的改进,于是想分享出来让更多吧友看到,也欢迎各位留言评论,咱们一起学习,个人的思想还是很狭隘的,一个人想问题时思绪容易走进死胡同出不来,希望各位吧友指出不足和改进意见。附件是仿真和程序,用keil5写的,keil4可能打不开哦(反正我用keil4打不开的),仿真也是protues8.6做的,低版本也可能打不开。
仿真原理图如下(proteus仿真工程文件可到本帖附件中下载)
1.png
(64.85 KB, 下载次数: 77)
下载附件
2021-3-23 21:45 上传
单片机源程序如下:
#include<reg52.h>
#include<array.h>
#include<stdio.h>
#include<string.h>
#define uint unsigned int
#define uchar unsigned char
sbit E=P2^0;
sbit RW=P2^1;
sbit RS=P2^2;
sbit CS2=P2^3;
sbit CS1=P2^4;
sbit RST=P2^5;
sbit BEEP=P2^6;
uchar hang,lie; //行,列
float dat1,dat2,count; //运算值
uchar keynum; //按键返回值(0~17)
uchar x; //按键所对应的字符在字符表中的行号
uchar keyfun; //运算方式选择(1:*, 2:+, 3:-, 4:/)
void delay(uchar i) //延迟10*n微秒
{
while(i--);
}
void delay_ms(uchar n) //延迟n毫秒
{
uchar i,j;
for(i=n;n>0;n--)
for(j=120;j>0;j--);
}
/********************************************************/
/*********************检测工作状态***********************/
//void checkbusy(void)
//{
// unsigned int timeout = 0;
// E = 0;
// RS = 0;
// RW = 1;
// E = 1;
// while((P0 & 0x80)&& ++timeout != 0);//忙状态检测,等待超时时间为60ms
// E = 0;
//}
/********************************************************/
/************************写命令**************************/
void write_cmd(uchar cmd)
{
// checkbusy();
RS=0;
RW=0;
E=1;
P0=cmd;
delay(20);
E=0;
}
/****************************************************/
/***********************写数据***********************/
void write_dat(uchar dat)
{
// checkbusy();
RS=1;
RW=0;
E=1;
P0=dat;
delay(20);
E=0;
}
/****************************************************/
/*********************设置页与列*********************/
void set(uchar page,uchar col)
{
page=page|0xb8; //页的首地址为0xb8
col=col|0x40; //列的首地址为0x40
write_cmd(col);
write_cmd(page);
}
/****************************************************/
/*******************选择左、右屏*********************/
void Select_Screen(uchar swich)
{
switch(swich)
{
case 0:CS1=CS2=0;break; //全屏
case 1:CS1=0;CS2=1;break; //左屏
case 2:CS1=1;CS2=0;break; //右屏
default:break;
}
}
/***************************************************/
/********************LCD初始化**********************/
void Lcd_Init()
{
uchar i,j,k=0;
RST=0;
delay(10);
RST=1;
write_cmd(0xc0);//设置显示起始行11xxxxxx
write_cmd(0x3f);//0x3f显示开,0x3e显示关
Select_Screen(0);
set(0,0);
for(i=0;i<8;i++)
{
for(j=0;j<64;j++)
write_dat(0x00);
k++;
set(k,0);
}
lie=2;hang=3;keyfun=0;
dat1=0.0,dat2=0.0,count=0.0;
}
/*****************************************************/
/********************计算窗口清空*********************/
void Clear_jisuan()
{
uchar i,j;
Select_Screen(0);
for(i=3;i<6;i++) //从第三页开始写入数据0x00,清空计算窗口
{
for(j=0;j<64;j++)
{
set(i,j);
write_dat(0x00);
}
}
lie=2;hang=3;keyfun=0;
dat1=0.0,dat2=0.0,count=0.0;
}
/**************************************************/
/********************显示字符**********************/
void Display_zifu(uchar n)
{
uchar i; //列数小于64时
if(lie<64)
{
Select_Screen(1); //开左屏
set(hang,lie); //设置行,列
for(i=0;i<6;i++)
write_dat(zifu[n++]); //写入数据
lie=lie+7; //每输出一个字符列数加6
if(hang>7) //行数大于7时回到初始值
hang=3;
}
else //列数大于64时
{
Select_Screen(2);
set(hang,lie-64);
for(i=0;i<6;i++)
write_dat(zifu[n++]);
lie=lie+7;
if(lie>123)
{
lie=0;hang++;
Select_Screen(1);
}
if(hang>7)
hang=3;
}
}
/******************************************************/
/***********将运算结果转化为字符串而后显示*************/
void Display_string(uchar page,uchar col,float num)
{
uchar str[20];
uchar tmp[16],i,j,k,c;
int len;
if((int)num==(int)(num+0.99999))//如果为整数
{
sprintf(str,"%d",(int)num); //将结果转化为字符串
len=sprintf(str,"%d",(int)num); //sprintf函数的返回值为字符串的长度,不含'/0'
}
else //如果为小数
{
sprintf(str,"%.3f",num); //将结果转化为字符串
len=sprintf(str,"%.3f",num);
}
if(col>63) //列数大于63开右屏
{
Select_Screen(2);
col=col-64;
}
for(i=0;i<len;i++) //将字符串逐个显示
{
if(col<63) //列数小于63开左屏
{Select_Screen(1);}
c=(str[i]-42)*6; //数组第一行*号的ASCII值为42,每个数组中的相应元素减去42得到其在数组中的行数
for(j=0;j<10;j++)
{tmp[j]=zifu[c];} //将数组zifu相应字符的ASCII码输送给数组tmp
set(page,col);
for(k=0;k<6;k++)
write_dat(zifu[c++]); //写入数据
col=col+6; //每写一个字符列数加6,继续写入下一个字符
delay(100);
}
}
/*****************************************************/
/***********************显示汉字**********************/
void Display_Project(uchar screen,uchar page,uchar col,uchar n,uchar table[][32])
{
uchar i,temp[32];
for(i=0;i<16;i++) //将table数组中的相应汉字的ascii码输送给数组temp
temp[i]=table[n][i];
for(i=16;i<32;i++)
temp[i]=table[n][i];
Select_Screen(screen);
set(page,col);
for(i=0;i<16;i++) //写汉字的上半部分
write_dat(temp[i]);
set(page+1,col);
for(i=0;i<16;i++) //写汉字的下半部分
write_dat(temp[i+16]);
}
/***********************************************************/
/******************** 响铃 *********************************/
//void play()
//{
//
// BEEP=0;
// delay_ms(1000);
// BEEP=1;
//
//}
/***********************************************************/
/********************选择计算类型***************************/
float calulate()
{
switch(keyfun)
{
case 1: count=dat2*dat1;dat1=count;break;
case 2: count=dat2+dat1;dat1=count;break;
case 3: count=dat2-dat1;dat1=count;break;
case 4: count=dat2/dat1;dat1=count;break;
default: break;
}
return(count);
}
/********************************************************/
/***********************计算过程*************************/
void cal_process()
{
uchar str_mul[10],len_mul;
if(x!=19)
{Display_zifu(x*6);}
while((P3&0xf0)!=0xf0); //按键按下有效,显示刷新
switch(keynum)
{
case 0:
case 1:
case 2:
case 3:
case 4:
case 5:
case 6:
case 7:
case 8:
case 9: dat1=dat1*10+keynum;break; //例如:输入12,初始dat1=0;则dat1=0*10+1=1;dat1=1*10+2=12
/* * */ case 10:calulate();dat2=dat1;dat1=0;keyfun=1;break;
/* + */ case 11:calulate();dat2=dat1;dat1=0;keyfun=2;break;
/* - */ case 12:calulate();dat2=dat1;dat1=0;keyfun=3;break;
/* / */ case 13:calulate();dat2=dat1;dat1=0;keyfun=4;break;
/* = */ case 14:hang=5;lie=0;Display_zifu(19*6);
switch(keyfun)
{
case 1: count=dat2*dat1;break;
case 2: count=dat2+dat1;break;
case 3: count=dat2-dat1;break;
case 4: count=dat2/dat1;break;
default:break;
}
if(count<999999999)
{
if(keyfun==1)
{
if((len_mul=sprintf(str_mul,"%d",count))<8) //多位整数乘法若结果大于6则显示?
Display_string(5,6,count);
}
else if(keyfun==4)
{
if(dat1!=0) //除数为0则输出?
Display_string(5,6,count);
}
else
Display_string(5,6,count);
}
else Display_zifu(20*6);break;
default: break;
}
}
/********************************************************/
/*****************矩阵按键扫描(逐行扫描)*****************/
void keyscan()
{
uchar key;
P3=0xfe; //令第一行为0,判断列
if(P3!=0Xfe)
{
delay(100); //消抖
if(P3!=0xfe)
{
key=P3&0xf0;
switch(key)
{
case 0xe0:keynum=7; x=13;cal_process();break; // 7
……………………
…………限于本文篇幅 余下代码请从51黑下载附件…………
复制代码
所有资料51hei提供下载:
计算器12864带字.rar
(139.63 KB, 下载次数: 195)
2021-3-23 21:08 上传
点击文件名下载附件
下载积分: 黑币 -5
作者:
大壮哥
时间:
2024-3-17 06:58
找了好久终于找到用12864屏幕的作者了,给作者点个赞
作者:
南-wgw
时间:
2024-3-25 16:39
这个屏幕我喜欢
作者:
mazd
时间:
2024-11-1 23:32
好东西,
很需要
作者:
Eliyas
时间:
2024-11-5 14:39
蓝色那个线是怎么接的?
作者:
mazdf
时间:
2024-11-13 15:49
好东西,很需要
作者:
zhp760721
时间:
2024-12-4 20:47
好东西,谢谢分享,
欢迎光临 (http://www.51hei.com/bbs/)
Powered by Discuz! X3.1