单片机简单的计算器c语言程序,51单片机实现简单计算器C语言程序+Proteus仿真

  • Post author:
  • Post category:其他


#include

#include

#include

#include

#include

#include

#include

#define uchar unsigned char

#define        uint unsigned int

sbit LCDEN=P3^4;

sbit RS=P3^5;

sbit RW=P3^6;

sbit BF=P0^7;

sbit BEEP=P1^0;

uchar str[17];

uchar code keyval[]=”789/456*123-c0=+”; //按键对应的符号

void delay(unsigned int xms)

{

int i,j;

for(i=xms;i>0;i–)

for(j=110;j>0;j–);

}

uchar keypad4_4()//按键扫描函数:要去抖,若有按键按下,返回对应的按键值(0-15),没有按键按下返回16

{

uchar i,row,temp;

uchar key=16;//按键号,初值设置为16,目的是:没有按键按下时返回16;

//若不设初值(默认值为0),没有按键按下时,将返回0,会误认为0被按下

row=0xef; //从第一列开始

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

{

P2=0xff;

P2=row;        //第i列信号,对应列为低,其他全为高

row=_crol_(row,1);           //生成下一列信号

temp=P2; //读入扫描信号

temp=temp&0x0f; //屏蔽高4位列信号,只保留低4位行信号

if(temp!=0x0f)//有按键被按下,因为第i列某行有按键按下,则低4位中有一位为低

{

delay(20);  //延时去抖

temp=P2;

temp=temp&0x0f;

if(temp!=0x0f)   //再次确认有按键被按下

{

switch(temp)  //根据低4位行信号,判断哪个按键被按下

{

case 0x0e:key=0+i;break; //第i列第1行按键被按下

case 0x0d:key=4+i;break; //第i列第2行按键被按下

case 0x0b:key=8+i;break; //第i列第3行按键被按下

case 0x07:key=12+i;      //第i列第4行按键被按下

}

do

{

temp=P2;              //再次扫描按键

temp=temp&0x0f;

}while(temp!=0x0f); //等待按键释放

}

}

}

return(key);//扫面结束,返回按键值

}

uchar RdACAdr()//读当前光标地址

{

uchar result;

P2 = 0xff;        //读地址前先置高电平,防止误判

RS = 0;

delay(5);

RW = 1;

LCDEN = 1;

delay(5);

result=P2&0x7f; //去掉最高位忙闲标记,只保留低7位地址值

LCDEN = 0;

return result;

}

uchar DectectBusyBit(void)//状态判断函数(忙/闲?)

{

bit result;

P0 = 0xff;        //读状态前先置高电平,防止误判

RS = 0;

delay(5);

RW = 1;

LCDEN = 1;

delay(5);

result=BF; //若LCM忙,则反复测试,在此处原地踏步;当LCM闲时,才往下继续

LCDEN = 0;

return result;

}

void WrComLCD(unsigned char ComVal)//写命令函数

{

while(DectectBusyBit()==1);         //先检测LCM是否空闲

RS = 0;

delay(1);

RW = 0;

LCDEN = 1;

P0 = ComVal;

delay(1);

LCDEN = 0;

}

void WrDatLCD(uchar DatVal)//写数据函数

{

while(DectectBusyBit()==1);

RS = 1;

delay(1);

RW = 0;

LCDEN = 1;

P0 = DatVal;

delay(1);

LCDEN = 0;

}

void WrStrDat(uchar *p)//显示英文字符串(长度不超过32)

{

uchar i=0,t;

while(p[i]!=’\0′)

{

WrDatLCD(p[i]);

i++;

delay(5);

t=RdACAdr();

if(t==0x10) WrComLCD(0xc0);//读当前坐标,如果第1行写完换行到第2行

if(t==0x50) WrComLCD(0x80);//读当前坐标,如果第2行写完换行到第1行

}

}

void LCD_Init(void)//1602初始化函数

{

//delay(15);

WrComLCD(0x38);

//delay(5);     // 功能设定:16*2行、5*7点阵、8位数据接口

WrComLCD(0x38);

//delay(5);

WrComLCD(0x38);

//多次重复设定功能指令,因为LCD启动后并不知道使用的是4位数据接口还是8位的,所以开始时总是默认为4位,这样刚开始写入功能设定指令时,低4位被忽略,为了可靠,最好多写几遍该指令

WrComLCD(0x01);    // 清屏

WrComLCD(0x06);    // 光标自增、屏幕不动

delay(1);              // 延时,等待上面的指令生效,下面再显示,防止出现乱码

WrComLCD(0x0C);    // 开显示、关光标

}

double str2num(uchar* str)

{

uint i=0,j=0,index=0;

uchar ch[10];

long a1=atol(str),b1=0;

double a2=atof(str),b2=0,c=0;

for(i=0;str[i]!=’\0′;i++)

{

if(!isalnum(str[i]))

{

index=i;

break;

}

}

for(j=0,i=index+1;i<=strlen(str);i++)

ch[j++]=str[i];

b1=atol(ch);

b2=atof(ch);

switch(str[index])

{

case ‘+’:c=a1+b1;break;

case ‘-‘:c=a1-b1;break;

case ‘*’:c=a2*b2;break;

case ‘/’:c=a2/b2;break;

default:c=a2;break;

}

return c;

}

void main()

{

uchar i=0,j=0,y=16;

uchar flag=0;

uchar end=0;

LCD_Init();

delay(5);   //延时,等待初始化完成

WrComLCD(0x80);           //设置显示地址第一行第一位:0X00(0x80+0x00)

delay(1);

WrComLCD(0xc0);

delay(1);

WrDatLCD(‘0’);

delay(1);

WrComLCD(0x80);

while(1)

{

y=keypad4_4();

if(y<16)

{

if(y!=12)

{

if(end==1)

{

end=0;

flag=0;

WrComLCD(0x01);

delay(1);

WrComLCD(0xc0);

delay(1);

WrDatLCD(‘0’);

delay(1);

WrComLCD(0x80);

}

str[strlen(str)]=keyval[y];

WrDatLCD(keyval[y]);

if(y==14)

{

uchar ch[17];

flag=1;

end=1;

str[strlen(str)]=’\0′;

WrComLCD(0xc0);

sprintf(ch,”%.2f”,str2num(str));

WrStrDat(ch);

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

str[i]=’\0′;

}

}

else

{

……………………

…………限于本文篇幅 余下代码请从51黑下载附件…………