初学者写了一天都写不出来,12864lcd显示计算器,实现四则运算
时间:10-02
整理:3721RD
点击:
/* 12864液晶计算器
只能实现一位的加减乘除运算,按键返回值,多位数的赋值方法,将多位数显示在液晶上
难疑点: scanf输入,sprintf输出函数的格式和用途,ASCII码干什么用
将多位十进制数输入液晶,负数和分母为0的数的处理
*/
#include<reg52.h>
#include<intrins.h>
#include<stdlib.h>
#define uchar unsigned char
#define uint unsigned int
#define KeyPort P3
#define LCD_data P0 //数据口
sbit LCD_RS=P1^2; //寄存器选择输入
sbit LCD_RW=P1^1; //液晶读写控制
sbit LCD_EN=P1^0; //液晶使能控制
sbit LCD_PSB=P1^3; //串并方式控制
sbit beep=P2^0;
void delayms(uint x); //延时函数
uchar KeyPro(void);
uchar KeyScan(void); //键盘扫描函数,使用行列反转扫描法
void lcd_pos(uchar X,uchar Y); //*液晶地址设置函数
void write_date(uchar date); //向液晶写数据函数
void write_cmd(uchar cmd); //向液晶写指令函数*
void lcd_init(); // 液晶初始化函数
void di()
{
beep=1;
delayms(20);
beep=0;
}
/**************************/
void main()
{
lcd_init(); //液晶初始化
while(1)
{
uint one,two,shu;
uchar num,flag,fu;
// uchar temp1[4];
// uchar temp2[4];
num=KeyPro(); //扫描键盘
if(num!=0xff) //如果扫描是按键有效值则进行处理
{
delayms(10); //延时10Us
if(('+'==num)|| ('-'==num) || ('x'==num)|| ('/'==num) || ('='==num))//输入数字最大值8,输入符号表示输入结束
{
if(num!='=') //判断当前符号位并做相应处理
{
flag=1;
fu=num; //如果不是等号记下标志位
delayms(20);
//显示第2行内容
lcd_pos(1,7); //位置函数
write_date(fu);
}
else
{
flag=2; //检测到输入=号,判断上次读入的符合
switch(fu)
{
case '+':shu=one+two;
break;
case '-':shu=one-two;
break;
case 'x':shu=one*two;
break;
case '/':shu=one/two;
break;
default:break;
}
////显示第4行内容
lcd_pos(3,1); //位置函数
write_date(shu+48); //
}
}
else
{
if(flag==0) //如果是输入的第一个数据,赋值给a,并把标志位置1,到下一个数据输入时可以跳转赋值给b
{ //temp1[i] i++; //输入数值累加
one=num;
lcd_pos(0,1); //位置函数 s++;
write_date(one+48);
// one=temp1[3]*1000+temp1[2]*100+temp1[1]*10+temp1[0];
// scanf(temp,"%d",&one);//从一个字符串输入到变量
// for(s=0;s<8;s++) //赋值完成后把缓冲区清零,防止下次输入影响结果
// temp1[s]=0xff;
}
else
{
two=num; //temp2[i] i++;
lcd_pos(2,1); //位置函数 temp2[s] s++;
write_date(two+48);
// two=temp2[3]*1000+temp2[2]*100+temp2[1]*10+temp2[0];
// scanf(temp,"%d",&two);
// for(s=0;s<8;s++) //赋值完成后把缓冲区清零,防止下次输入影响结果
// temp2[s]=0xff;
}
}
}
}
}
void delayms(uint x) //延时函数
{
uint i,j;
for(i=x;i>0;i--)
for(j=110;j>0;j--);
}
/*------------------------------------------------
按键扫描函数,返回扫描键值
------------------------------------------------*/
unsigned char KeyScan(void) //键盘扫描函数,使用行列反转扫描法
{
unsigned char cord_h,cord_l;//行列值中间变量
KeyPort=0x0f; //行线输出全为0
cord_h=KeyPort&0x0f; //读入列线值
if(cord_h!=0x0f) //先检测有无按键按下
{
delayms(20); //去抖
if((KeyPort&0x0f)!=0x0f)
{
di();
cord_h=KeyPort&0x0f; //读入列线值
KeyPort=cord_h|0xf0; //输出当前列线值
cord_l=KeyPort&0xf0; //读入行线值
while((KeyPort&0xf0)!=0xf0);//等待松开并输出
return(cord_h+cord_l);//键盘最后组合码值
}
}return(0xff); //返回该值
}
/*------------------------------------------------
按键值处理函数,返回扫键值
P 可以根据需要改变返回值
7 -| 1 | 2 | 3 | + |
6 -| 4 | 5 | 6 | - |
5 -| 7 | 8 | 9 | * |
4 -| 0 | . | = | / |
3 ---------------- -|
2--------————|
1- -—|
0 - |
------------------------------------------------*/
unsigned char KeyPro(void)
{
switch(KeyScan())
{
case 0x7e:return 1 ;break;//0 按下相应的键显示相对应的码值
case 0x7d:return 2 ;break;//1
case 0x7b:return 3 ;break;//2
case 0x77:return '+';break;//3
case 0xbe:return 4 ;break;//4
case 0xbd:return 5 ;break;//5
case 0xbb:return 6 ;break;//6
case 0xb7:return '-';break;//7
case 0xde:return 7 ;break;//8
case 0xdd:return 8 ;break;//9
case 0xdb:return 9 ;break;//a
case 0xd7:return 'x';break;//b
case 0xee:return 0 ;break;//c
case 0xed:return '.';break;//d
case 0xeb:return '=';break;//e
case 0xe7:return '/';break;//f
default:return 0xff;break;
}
}
/****************向液晶写指令函数*****************/
void write_cmd(uchar cmd)
{
//RS=L, RW=L, E=高脉冲, D0~D7=指令码
LCD_RS=0;
LCD_RW=0;
LCD_EN=0;
P0=cmd;
delayms(5);
LCD_EN=1;
delayms(5);
LCD_EN=0;
}
/***********向液晶写数据函数*************/
void write_date(uchar date)
{
LCD_RS=1;
LCD_RW=0;
LCD_EN=0;
P0=date;
delayms(5);
LCD_EN=1;
delayms(5);
LCD_EN=0;
}
/*****************液晶地址设置函数***************/
void lcd_pos(uchar X,uchar Y)
{
uchar pos;
if(X==0)
{X=0x80;}
else if(X==1)
{X=0x90;}
else if(X==2)
{X=0x88;}
else if(X==3)
{X=0x98;}
pos=X+Y; //0x80+1=0x81
write_cmd(pos);
}
/***************液晶初始化函数******************/
void lcd_init()
{
LCD_PSB=1;
write_cmd(0x30); //基本指令
delayms(5);
write_cmd(0x0c); //光标设置,不显示光标
delayms(5);
write_cmd(0x01); //液晶清屏
delayms(5);
}
只能实现一位的加减乘除运算,按键返回值,多位数的赋值方法,将多位数显示在液晶上
难疑点: scanf输入,sprintf输出函数的格式和用途,ASCII码干什么用
将多位十进制数输入液晶,负数和分母为0的数的处理
*/
#include<reg52.h>
#include<intrins.h>
#include<stdlib.h>
#define uchar unsigned char
#define uint unsigned int
#define KeyPort P3
#define LCD_data P0 //数据口
sbit LCD_RS=P1^2; //寄存器选择输入
sbit LCD_RW=P1^1; //液晶读写控制
sbit LCD_EN=P1^0; //液晶使能控制
sbit LCD_PSB=P1^3; //串并方式控制
sbit beep=P2^0;
void delayms(uint x); //延时函数
uchar KeyPro(void);
uchar KeyScan(void); //键盘扫描函数,使用行列反转扫描法
void lcd_pos(uchar X,uchar Y); //*液晶地址设置函数
void write_date(uchar date); //向液晶写数据函数
void write_cmd(uchar cmd); //向液晶写指令函数*
void lcd_init(); // 液晶初始化函数
void di()
{
beep=1;
delayms(20);
beep=0;
}
/**************************/
void main()
{
lcd_init(); //液晶初始化
while(1)
{
uint one,two,shu;
uchar num,flag,fu;
// uchar temp1[4];
// uchar temp2[4];
num=KeyPro(); //扫描键盘
if(num!=0xff) //如果扫描是按键有效值则进行处理
{
delayms(10); //延时10Us
if(('+'==num)|| ('-'==num) || ('x'==num)|| ('/'==num) || ('='==num))//输入数字最大值8,输入符号表示输入结束
{
if(num!='=') //判断当前符号位并做相应处理
{
flag=1;
fu=num; //如果不是等号记下标志位
delayms(20);
//显示第2行内容
lcd_pos(1,7); //位置函数
write_date(fu);
}
else
{
flag=2; //检测到输入=号,判断上次读入的符合
switch(fu)
{
case '+':shu=one+two;
break;
case '-':shu=one-two;
break;
case 'x':shu=one*two;
break;
case '/':shu=one/two;
break;
default:break;
}
////显示第4行内容
lcd_pos(3,1); //位置函数
write_date(shu+48); //
}
}
else
{
if(flag==0) //如果是输入的第一个数据,赋值给a,并把标志位置1,到下一个数据输入时可以跳转赋值给b
{ //temp1[i] i++; //输入数值累加
one=num;
lcd_pos(0,1); //位置函数 s++;
write_date(one+48);
// one=temp1[3]*1000+temp1[2]*100+temp1[1]*10+temp1[0];
// scanf(temp,"%d",&one);//从一个字符串输入到变量
// for(s=0;s<8;s++) //赋值完成后把缓冲区清零,防止下次输入影响结果
// temp1[s]=0xff;
}
else
{
two=num; //temp2[i] i++;
lcd_pos(2,1); //位置函数 temp2[s] s++;
write_date(two+48);
// two=temp2[3]*1000+temp2[2]*100+temp2[1]*10+temp2[0];
// scanf(temp,"%d",&two);
// for(s=0;s<8;s++) //赋值完成后把缓冲区清零,防止下次输入影响结果
// temp2[s]=0xff;
}
}
}
}
}
void delayms(uint x) //延时函数
{
uint i,j;
for(i=x;i>0;i--)
for(j=110;j>0;j--);
}
/*------------------------------------------------
按键扫描函数,返回扫描键值
------------------------------------------------*/
unsigned char KeyScan(void) //键盘扫描函数,使用行列反转扫描法
{
unsigned char cord_h,cord_l;//行列值中间变量
KeyPort=0x0f; //行线输出全为0
cord_h=KeyPort&0x0f; //读入列线值
if(cord_h!=0x0f) //先检测有无按键按下
{
delayms(20); //去抖
if((KeyPort&0x0f)!=0x0f)
{
di();
cord_h=KeyPort&0x0f; //读入列线值
KeyPort=cord_h|0xf0; //输出当前列线值
cord_l=KeyPort&0xf0; //读入行线值
while((KeyPort&0xf0)!=0xf0);//等待松开并输出
return(cord_h+cord_l);//键盘最后组合码值
}
}return(0xff); //返回该值
}
/*------------------------------------------------
按键值处理函数,返回扫键值
P 可以根据需要改变返回值
7 -| 1 | 2 | 3 | + |
6 -| 4 | 5 | 6 | - |
5 -| 7 | 8 | 9 | * |
4 -| 0 | . | = | / |
3 ---------------- -|
2--------————|
1- -—|
0 - |
------------------------------------------------*/
unsigned char KeyPro(void)
{
switch(KeyScan())
{
case 0x7e:return 1 ;break;//0 按下相应的键显示相对应的码值
case 0x7d:return 2 ;break;//1
case 0x7b:return 3 ;break;//2
case 0x77:return '+';break;//3
case 0xbe:return 4 ;break;//4
case 0xbd:return 5 ;break;//5
case 0xbb:return 6 ;break;//6
case 0xb7:return '-';break;//7
case 0xde:return 7 ;break;//8
case 0xdd:return 8 ;break;//9
case 0xdb:return 9 ;break;//a
case 0xd7:return 'x';break;//b
case 0xee:return 0 ;break;//c
case 0xed:return '.';break;//d
case 0xeb:return '=';break;//e
case 0xe7:return '/';break;//f
default:return 0xff;break;
}
}
/****************向液晶写指令函数*****************/
void write_cmd(uchar cmd)
{
//RS=L, RW=L, E=高脉冲, D0~D7=指令码
LCD_RS=0;
LCD_RW=0;
LCD_EN=0;
P0=cmd;
delayms(5);
LCD_EN=1;
delayms(5);
LCD_EN=0;
}
/***********向液晶写数据函数*************/
void write_date(uchar date)
{
LCD_RS=1;
LCD_RW=0;
LCD_EN=0;
P0=date;
delayms(5);
LCD_EN=1;
delayms(5);
LCD_EN=0;
}
/*****************液晶地址设置函数***************/
void lcd_pos(uchar X,uchar Y)
{
uchar pos;
if(X==0)
{X=0x80;}
else if(X==1)
{X=0x90;}
else if(X==2)
{X=0x88;}
else if(X==3)
{X=0x98;}
pos=X+Y; //0x80+1=0x81
write_cmd(pos);
}
/***************液晶初始化函数******************/
void lcd_init()
{
LCD_PSB=1;
write_cmd(0x30); //基本指令
delayms(5);
write_cmd(0x0c); //光标设置,不显示光标
delayms(5);
write_cmd(0x01); //液晶清屏
delayms(5);
}
很好的学习资料
能用txt文件上传吗 ?这样没法复制
挺不错的 继续努力