标题:
单片机计算器源程序 1602液晶显示
[打印本页]
作者:
535663152
时间:
2018-4-9 21:53
标题:
单片机计算器源程序 1602液晶显示
可以用语音来实现加减乘除之类计算 并显示到1602上面
单片机源程序如下:
/*
接盘按键说明:
--------------------------------------------------
| 1 | 2 | 3 | + |
- - - - - - - - - - - - -
| 4 | 5 | 6 | - |
- - - - - - - - - - - - -
| 7 | 8 | 9 | * |
- - - - - - - - - - - - -
| C | 0 | = | / |
--------------------------------------------------*/
#include<reg51.h>
#define uint unsigned int
#define uchar unsigned char
#define XTAL 12000000 //CPU晶振频率
#define baudrate 9600 //通信波特率
//--------LCD1602-------------------
//P00-07==== D0-7
sbit rs=P1^5; //指令or数据 2.6
sbit wela=P1^4; //读or写 2.5
sbit lcden=P1^6; //使能信号 2.7
sbit feng=P1^0; //蜂鸣器
//--------LCD1602-------------------
//--------KEY-----------------------
//P1口
//--------KEY-----------------------
uchar code table[]= " ";
unsigned char data_a,data_b; //计算结果
unsigned char data_c;
unsigned char num1; //第一个数
unsigned char num2; //第二个数
unsigned char count; //一个起识别作用的变量
unsigned char yusuanfu; //加减乘除等运算符
uchar dispaly[10]; //显示缓冲
//************************************************************************/
// 描述: 延时t us函数
//************************************************************************/
void LCD_Delay_us(unsigned int t)
{
while(t--); //t=0,退出
}
//************************************************************************/
// 描述: 延时t ms函数
//************************************************************************/
void LCD_Delay_ms(unsigned int t)
{
unsigned int i,j;
for(i=0;i<t;i++) //执行t次循环
for(j=0;j<113;j++) //执行113次循环
;
}
//************************************************************************/
// 描述: 1602液晶写指令
//************************************************************************/
void write_com(uchar com) //1602液晶写指令
{
rs=0; //写指令
lcden=0; //使能1602
P2=com; //写入指令com
LCD_Delay_ms(1); //延时1ms
lcden=1; //使能1602
LCD_Delay_ms(2); //延时2ms
lcden=0; //使能1602
}
//************************************************************************/
// 描述:1602液晶写数据
//************************************************************************/
void write_date(uchar date) //1602液晶写数据
{
rs=1; //写数据
lcden=0; //使能1602
P2=date; //写入数据date
LCD_Delay_ms(1); //延时1ms
lcden=1; //使能1602
LCD_Delay_ms(2); //延时2ms
lcden=0; //使能1602
}
//************************************************************************/
// 描述:指定x,y写入字符函数
//************************************************************************/
void W_lcd(unsigned char x,unsigned char y,unsigned char Data)
{
if (y == 0){write_com(0x80 + x);} //第一行
else{write_com(0xc0 + x);} //第二行
write_date( Data); //写入数据
}
//指定x,y写入字符串函数
void LCD_Write_String(unsigned char x,unsigned char y,unsigned char *s)
{
if (y == 0){write_com(0x80 + x);} //第一行
else{write_com(0xC0 + x);} //第二行
while (*s) //
{write_date( *s); s++;} //写入数据
}
//************************************************************************/
// 描述:初始化液晶,及画面初始化
//************************************************************************/
void init_lcd(void) //初始化液晶,及画面初始化
{
wela=0; //写液晶
lcden=0; //使能1602
write_com(0x38); //8 位总线,双行显示,5X7 的点阵字符
LCD_Delay_us(100); //延时100us
write_com(0x0c); //开显示,无光标,光标不闪烁
write_com(0x06); //光标右移动
write_com(0x01); //清屏
write_com(0x80); //DDRAM 地址归0
}
//************************************************************************/
// 描述: 反转法键盘扫描
//************************************************************************/
short keycheckdown() /* 反转法键盘扫描 */
{
short temp1,temp2,temp,a=0xff;
P1=0xf0; /* 输入行值(或列值) */
LCD_Delay_ms(20); /* 延时 */
temp1=P1; /* 读列值(或行值) */
P1=0xff;
LCD_Delay_ms(20); /* 延时 */
P1=0x0f; /* 输入列值(或行值) */
LCD_Delay_ms(20); /* 延时 */
temp2=P1; /* 读行值(或列值) */
P1=0xff;
temp=(temp1&0xf0)|(temp2&0xf); /* 将两次读入数据组合 */
switch(temp) /* 通过读入数据组合判断按键位置 */
{
case 0x77 :a=0x0d;break; // 按键/ 77
case 0xb7 :a=0x0e; break;// 按键= 7b
case 0xd7 :a=0; break;// 按键0 7d
case 0xe7 :a=0x0f; break;// 按键CE 7e
case 0x7b :a=0x0c;break;// 按键* b7
case 0xbb :a=0x9;break; // 按键9 bb
case 0xdb :a=0x8;break; // 按键8 bd
case 0xeb :a=0x7;break; // 按键7 be
case 0x7d :a=0x0b;break;// 按键- d7
case 0xbd :a=0x6;break; // 按键6 db
case 0xdd :a=0x5;break; // 按键5 dd
case 0xed :a=0x4;break; // 按键4 de
case 0x7e :a=0x0a; break;// 按键+ e7
case 0xbe :a=3;break;// 按键3 eb
case 0xde :a=2;break;// 按键2 ed
case 0xee :a=1;break;// 按键1 ee
default :a=0xff;
}
return a; /* 返回按键值 */
}
void display_a() //显示运算结果
{
dispaly[3]=data_a%10000/1000; //千
dispaly[2]=data_a%1000/100; //百
dispaly[1]=data_a%100/10; //十
dispaly[0]=data_a%10; //个
write_com(0x80+7); //显示运算结果在7的位置上
if(data_a>999){ write_date('0'+dispaly[3]);} //显示千位
if(data_a>99){ write_date('0'+dispaly[2]);} //显示百位
if(data_a>9){ write_date('0'+dispaly[1]);} //显示十位
write_date('0'+dispaly[0]); //显示个位
}
void display_num1() //显示数据a
{
dispaly[3]=num1%10000/1000; //千
dispaly[2]=num1%1000/100; //百
dispaly[1]=num1%100/10; //十
dispaly[0]=num1%10; //个
write_com(0x80+0); //显示第一个数在0的位置上
if(num1>999){ write_date('0'+dispaly[3]);} //显示千位
if(num1>99){ write_date('0'+dispaly[2]);} //显示百位
if(num1>9){ write_date('0'+dispaly[1]);} //显示十位
write_date('0'+dispaly[0]); //显示个位
}
void display_yusuanfu() //显示运算符
{
switch(yusuanfu)
{
case 219: write_com(0x80+1); write_date('+'); break; //写屏“+? 在1的位置上
case 221: write_com(0x80+1); write_date('-'); break; //写屏“-” 在1的位置上
case 136: write_com(0x80+1); write_date('*'); break; //写屏“*” 在1的位置上
case 223: write_com(0x80+1); write_date('/'); break; //写屏“/” 在1的位置上
}
}
void display_num2() //显示第二个数
{
dispaly[3]=num2%10000/1000; //千
dispaly[2]=num2%1000/100; //百
dispaly[1]=num2%100/10; //十
dispaly[0]=num2%10; //个
write_com(0x80+2); //显示第二个数在2的位置上
if(num1>999){ write_date('0'+dispaly[3]);} //显示千位
if(num1>99){ write_date('0'+dispaly[2]);} //显示百位
if(num1>9){ write_date('0'+dispaly[1]);} //显示十位
write_date('0'+dispaly[0]); //显示个位
}
void display_c(x) //此函数在此工程中没有用到,仅提供一个思路
{
if(data_c<100000000&&data_c>-1)//溢出时显示错误
{
dispaly[8]=data_c%1000000000/100000000; //万万
dispaly[7]=data_c%100000000/10000000; //千万
dispaly[6]=data_c%10000000/1000000; //百万
dispaly[5]=data_c%1000000/100000; //十万
dispaly[4]=data_c%100000/10000; //万
dispaly[3]=data_c%10000/1000; //千
dispaly[2]=data_c%1000/100; //百
dispaly[1]=data_c%100/10; //十
dispaly[0]=data_c%10; //个
write_com(0x80+6+0x40); //第一行
if(x==4)
{
if(data_c>99999999) { write_date('0'+dispaly[8]);} //显示万万
if(data_c>9999999) { write_date('0'+dispaly[7]);} //千万
if(data_c>999999) { write_date('0'+dispaly[6]);} //百万
if(data_c>99999) { write_date('0'+dispaly[5]);} //十万
if(data_b!=0) {
write_date('0'+dispaly[4]); //万
write_date('.');
write_date('0'+dispaly[3]); //千
write_date('0'+dispaly[2]); //百
write_date('0'+dispaly[1]); //十
write_date('0'+dispaly[0]); //个
}
}
else{
if(data_c>99999999) { write_date('0'+dispaly[8]);} //显示万万
if(data_c>9999999) { write_date('0'+dispaly[7]);} //千万
if(data_c>999999) { write_date('0'+dispaly[6]);} //百万
if(data_c>99999) { write_date('0'+dispaly[5]);} //十万
if(data_c>9999) { write_date('0'+dispaly[4]);} //万
if(data_c>999) { write_date('0'+dispaly[3]);} //千
if(data_c>99) { write_date('0'+dispaly[2]);} //百
if(data_c>9) { write_date('0'+dispaly[1]);} //十
write_date('0'+dispaly[0]); //个
}
}
else //溢出时显示错误
{
write_com(0x80+11+0x40); //第一行
write_date('E'); //显示 E
write_date('r'); //显示R
write_date('r'); //显示R
write_date('o'); //显示O
write_date('r'); //显示E
}
}
//加减乘除运算
void eql(uchar x) //此函数在此工程中没有用到 提供一个思路
{
switch(x) /*功能键选择*/
{
case 1:data_c=data_a+data_b;break; //加 /* + S=1 */ /* 数值转换函数 */
case 2:if(data_a>=data_b){data_c=data_a-data_b;} /* - S=2 *///减
else{data_c=data_b-data_a;W_lcd(5,1,'-');} //负数符号
break;
case 3:data_c=(data_a*data_b);break; /* * S=3 *///乘
case 4:if(data_b==0){LCD_Write_String(0,1,"Error ! ");}else{data_c=(data_a*10000)/data_b;}break; /* / S=4 *///除//溢出时显示错误
case 0:break;
}
}
void UART_Init(void) // 串口初始化
{
SCON = 0x50;
TMOD = 0x20;
TH1 = 0xfd;
TL1 = 0xfd;
EA = 1;
ES = 1;
TR1 = 1;
}
void INT_UartRcv(void) interrupt 4 //串口中断函数
{
unsigned char Rcv = 0;
if(RI)
{
RI = 0;
Rcv = SBUF; //串口读数据
if((Rcv>9||Rcv<0)&&(count==1)) //count=1,表明输入的是运算符
{
yusuanfu = Rcv; //将读回的数据存入yunsuanfu这个变量
switch(yusuanfu) //判断读回的运算符,并将他们显示在屏上1的位置
{
case 75 : write_com(0x80+1); write_date('+'); LCD_Delay_ms(1000); break;
case 77 : write_com(0x80+1); write_date('-'); break;
case 248 : write_com(0x80+1); write_date('*'); break;
case 79 : write_com(0x80+1); write_date('/'); break;
}
count++;
}
else if(count==2) //count=2表明第二个数据来了
{
num2= Rcv-2;
display_num2();
count++;
}
else if(count==3) //count=3表明该计算结果了
{
switch(yusuanfu) //判断运算符是哪个,并执行相应的计算
{
case 75: data_a = num1 +num2-110; break; //检测到”+“号,让两个数据相加
case 77: data_a = num1 -num2-146; break; //检测到”-“号,让两个数据相减
case 248: data_a = ((num2-110) *num1); break; //检测到”x“号,让两个数据相乘
case 79: data_a = num1 /(num2-110); break; //检测到”/“号,让两个数据相除
}
display_a(); //显示运算结果
LCD_Delay_ms(1000); //延时,让显示的结果延时一下
count=0; //计算完一遍,让变量清0
LCD_Write_String(0,0,table);LCD_Write_String(0,1,table);W_lcd(0,0,'0'); //清屏,让屏显示0,表示已准备好计算下一次
}
else if (count==0) //count=0,表示一次计算刚刚开始
{
num1 = Rcv-112; // 第一个数据发回来的码值减去112就是想要得到的数据
display_num1(); // 显示第一个数
count++; //变量加1
feng=1; //蜂鸣器响一下,此语句是调试阶段用到的
LCD_Delay_ms(1000);
feng=0; //关掉蜂鸣器
}
}
}
void main()
{
UART_Init(); //串口初始化
init_lcd(); //1602液晶初始化
while(1) //什么也不做,等待执行中断函数
{
;
}
}
复制代码
所有资料51hei提供下载:
1-计算器程序.rar
(51.11 KB, 下载次数: 10)
2018-4-9 21:53 上传
点击文件名下载附件
下载积分: 黑币 -5
欢迎光临 (http://www.51hei.com/bbs/)
Powered by Discuz! X3.1