//-----------------------------------------------------------------------------
//
// 目标器件: C8051F320x
//
// 编译工具: Silicon Laboratories IDE
//
//-----------------------------------------------------------------------------
//程序描述:
// 16 Key + LCD Display
// 可以进行正整数的加、减、乘、整除运算,计算结果显示范围:-9999999~99999999
//-----------------------------------------------------------------------------
// 头文件包含
//-----------------------------------------------------------------------------
#include <c8051F320.h>
//;************************************************************************
//;* p1.0 : 1st column (k0,k4,k8,kc)
//;* p1.1 : 2nd column (k1,k5,k9,kd)
//;* p1.2 : 3rd column (k2,k6,ka,ke)
//;* p1.3 : 4th column (k3,k7,kb,kf)
//;* p1.4 : 1st row (k0,k1,k2,k3) p1.7-p1.4 connect to 74LS21
//;* p1.5 : 2nd row (k4,k5,k6,k7)
//;* p1.6 : 3rd row (k8,k9,ka,kb)
//;* p1.7 : 4th row (kc,kd,ke,kf)
//:* p2.6 : =0 a key is pressed
//;**********************************
//-----------------------------------------------------------------------------
//全局变量定义
//-----------------------------------------------------------------------------
unsigned char DispData0[8]={'0',' ',' ',' ',' ',' ',' ',' '};//
unsigned int x;
unsigned char *lcdpoint0; //指向 lcddata数组的指针
unsigned char *lcdpoint1; //指向 lcddata数组的指针
sbit rs = P2^3;
sbit e = P2^5;
sbit aKey = P2^6;
//-----------------------------------------------------------------------------
// 函数定义
//-----------------------------------------------------------------------------
void PORT_Init (void); //通用I/O口及交叉开关初始化
void SYSCLK_Init (void); //系统时钟初始化
void LCD_Init(void); //液晶初始化
void LCD_Instruction(unsigned char comnd);
void LCD_Data(unsigned char data0);
void LCD_Display (void);
void Delay8_33us(unsigned int iM);
void ClearLCD(void); //清除显示内容
void GetKey(unsigned char chkey);//获得显示字符
void GetResult(void); // 计算结果
int ii,i=0;
unsigned char columNum; //列号
unsigned char rowNum; //行号
unsigned char tt;
unsigned char key;
//-----------------------------------------------------------------------------
// 主程序
//-----------------------------------------------------------------------------
void main (void)
{
PCA0MD &= ~0x40; // no Watchdog
SYSCLK_Init(); // System Clock=12MHz/8
PORT_Init();
LCD_Display();
while(1)
{
P1 = 0x0f; //检测按键列号
while(aKey)
{ //waiting for a key
}
columNum = ~P1 & 0x0f; //获得按键列号
P1 = 0xf0; //检测按键行号
tt = P1;
rowNum = ~P1>>4; //获得按键行号
if (columNum == 4) columNum = 3; //columNum为0100,列号为3
if (columNum == 8) columNum = 4; //columNum为1000,列号为4
if (rowNum == 4) rowNum = 3; //rowNum为0100,行号为3
if (rowNum == 8) rowNum = 4; //rowNum为1000,行号为4
/*根据行列号获得按键字符*/
if(rowNum==1)
{
if(columNum==1)
key='7';
else if(columNum==2)
key='8';
else if(columNum==3)
key='9';
else if(columNum==4)
key='/';
}
if(rowNum==2)
{
if(columNum==1)
key='4';
else if(columNum==2)
key='5';
else if(columNum==3)
key='6';
else if(columNum==4)
key='x';
}
if(rowNum==3)
{
if(columNum==1)
key='1';
else if(columNum==2)
key='2';
else if(columNum==3)
key='3';
else if(columNum==4)
key='-';
}
if(rowNum==4)
{
if(columNum==1)
key='c';
else if(columNum==2)
key='0';
else if(columNum==3)
key='=';
else if(columNum==4)
key='+';
}
GetKey(key); //获得显示字符
LCD_Display();
P1 = 0x0f;
Delay8_33us(5000);
while(aKey == 0)
{
}
}
}
//-----------------------------------------------------------------------------
//函数名称: SYSCLK_Init ()
//函数功能: 系统时钟初始化
//入口参数: 无
//出口参数: 无
//全局变量引用: 无
//调用模块: 无
//-----------------------------------------------------------------------------
void SYSCLK_Init (void)
{
OSCICL = 0x00; // 基本频率12MHz,修正=0
OSCICN = 0x80; // 1:internal oscillator enabled, 2: 12MHz/8
RSTSRC = 0x04; // enable missing clock detector,时钟停止将复位
//隐含CLKSEL=0;USBCLK=000: 时钟4倍:6MHz(低速USB), CLKSL=00: 内部震荡器/8=1.5MHz
}//
//-----------------------------------------------------------------------------
//函数名称: PORT_Init ()
//函数功能: 通用I/O口及交叉开关初始化
//入口参数: 无
//出口参数: 无
//全局变量引用: 无
//调用模块: 无
//-----------------------------------------------------------------------------
void PORT_Init (void)
{
P0MDOUT = 0xFF; //P0 als Digital Output
P1MDOUT = 0x00; //P1 als Digital Output
P0MDIN = 0xFF; //P0 als Digital Input
P1MDIN = 0xFF; //P1 als Digital Input
P2MDIN = 0xFF; //P2 als Digital Input
P2MDOUT = 0x00; //P2 as a push-pull mode
XBR1 = 0x40; //cross Bar funktioniert
P1 = 0x0f;
}
//-----------------------------------------------------------------------------
//函数名称: LCD_Init ()
//函数功能: LCD初始化
//入口参数: 无
//出口参数: 无
//全局变量引用: 无
//调用模块: 无
//-----------------------------------------------------------------------------
void LCD_Init(void)
{
LCD_Instruction(0x38); //lcd disabled
LCD_Instruction(0x38); //lcd disabled
LCD_Instruction(0x01); //clear screen
LCD_Instruction(0x0C); //open display
}
//-----------------------------------------------------------------------------
//函数名称: LCD_Instruction ()
//函数功能: LCD get Instruction
void LCD_Instruction(unsigned char Commnd)
{
rs = 0;
e = 1;
P0 = Commnd;
for(x=0;x<2000;x++);
e = 0;
}
//-----------------------------------------------------------------------------
//函数名称: LCD_Data ()
//函数功能: LCD get Data
void LCD_Data(unsigned char data0)
{
rs = 1;
e = 1;
P0 = data0;
for(x=0;x<2000;x++);
e = 0;
}
//
void Delay8_33us(unsigned int iM) //8.33us
{
while(iM>0)
{
iM--;
}
}
//
void LCD_Display(void)
{
lcdpoint0 = &DispData0[0];
LCD_Init(); //LCD初始化
LCD_Instruction(0x80); //address 0
for(ii=0;ii<8;ii++)
{
LCD_Data(*lcdpoint0);
lcdpoint0++;
}
}
//---------------------------------------------------------------------------
//函数名称: GetKey(unsigned char)
void GetKey(unsigned char chkey)
{
if(chkey!='c' ) //是否按下清零键
{
if(chkey!='=') //是否按下'='
{
DispData0[i] =chkey; //显示按键数字和运算符
i++;
}
else
{
GetResult(); //进行计算
}
}
else
{
ClearLCD(); //清除显示
}
}
//--------------------------------------------------------------------------
//函数名称: ClearLCD()
//函数功能: 清除显示
void ClearLCD(void)
{
for(ii=0;ii<8;ii++)
{
DispData0[ii]=' '; //清空显示数组
}
DispData0[0]='0';
i=0;
}
//--------------------------------------------------------------------------
//函数名称: GetResult()
//函数功能: 计算
void GetResult(void)
{
int num1=0; //第一个操作数
int num2=0; //第二个操作数
long result; //计算结果
long bufresult; //计算结果缓存
char oper; //运算符
char isOperator=0; //运算符按下标志,0表示没有按下运算符
unsigned char count; //计算结果位数
unsigned char buffer; //字符缓存
for(ii=0;ii<8;ii++)
{
if(DispData0[ii]>='0'&&DispData0[ii]<='9')
{
if(isOperator==0)
{
num1=num1*10+(DispData0[ii]-0x30); // 计算第一个操作数
}
else
{
num2=num2*10+(DispData0[ii]-0x30); //计算第二个操作数
}
}
else if(DispData0[ii]=='+'||DispData0[ii]=='-'||DispData0[ii]=='x'||DispData0[ii]=='/') //取运算符
{
oper=DispData0[ii];
isOperator=1;
}
}
ClearLCD(); //清除显示
switch(oper) //判断运算类型
{
case '+':
{
result=num1+num2;break;
}
case '-':
{
result=num1-num2;break;
}
case 'x':
{
result=num1*num2;break;
}
case '/':
{
result=num1/num2;break;
}
}
bufresult=result;
for(ii=0;ii<8;ii++) //计算结果的位数
{
bufresult=bufresult/10;
if(bufresult==0)
{
count=ii+1;
break;
}
}
if(result<0)
bufresult=-result;
else
bufresult=result;
for(ii=0;ii<count;ii++) //取结果的每一位放入显示数组
{
DispData0[ii]=bufresult%10+0x30;
bufresult=bufresult/10;
}
if(result<0)
{
DispData0[ii]='-'; //如果是负数,添加'-'
count+=1;
}
for(ii=0;ii<count/2;ii++) //按显示顺序排列
{
buffer=DispData0[ii];
DispData0[ii]=DispData0[count-ii-1];
DispData0[count-ii-1]=buffer;
}
}
主要缺点:
1、只能计算和显示整数
2、可以计算的数字位数和显示结果位数有限,最大8个字符,但可以通过修改DispData0[]长度调节,比较容易