数码管之简单加减法计算器项目总结.docx

上传人:b****7 文档编号:16297986 上传时间:2023-07-12 格式:DOCX 页数:25 大小:399.77KB
下载 相关 举报
数码管之简单加减法计算器项目总结.docx_第1页
第1页 / 共25页
数码管之简单加减法计算器项目总结.docx_第2页
第2页 / 共25页
数码管之简单加减法计算器项目总结.docx_第3页
第3页 / 共25页
数码管之简单加减法计算器项目总结.docx_第4页
第4页 / 共25页
数码管之简单加减法计算器项目总结.docx_第5页
第5页 / 共25页
数码管之简单加减法计算器项目总结.docx_第6页
第6页 / 共25页
数码管之简单加减法计算器项目总结.docx_第7页
第7页 / 共25页
数码管之简单加减法计算器项目总结.docx_第8页
第8页 / 共25页
数码管之简单加减法计算器项目总结.docx_第9页
第9页 / 共25页
数码管之简单加减法计算器项目总结.docx_第10页
第10页 / 共25页
数码管之简单加减法计算器项目总结.docx_第11页
第11页 / 共25页
数码管之简单加减法计算器项目总结.docx_第12页
第12页 / 共25页
数码管之简单加减法计算器项目总结.docx_第13页
第13页 / 共25页
数码管之简单加减法计算器项目总结.docx_第14页
第14页 / 共25页
数码管之简单加减法计算器项目总结.docx_第15页
第15页 / 共25页
数码管之简单加减法计算器项目总结.docx_第16页
第16页 / 共25页
数码管之简单加减法计算器项目总结.docx_第17页
第17页 / 共25页
数码管之简单加减法计算器项目总结.docx_第18页
第18页 / 共25页
数码管之简单加减法计算器项目总结.docx_第19页
第19页 / 共25页
数码管之简单加减法计算器项目总结.docx_第20页
第20页 / 共25页
亲,该文档总共25页,到这儿已超出免费预览范围,如果喜欢就下载吧!
下载资源
资源描述

数码管之简单加减法计算器项目总结.docx

《数码管之简单加减法计算器项目总结.docx》由会员分享,可在线阅读,更多相关《数码管之简单加减法计算器项目总结.docx(25页珍藏版)》请在冰点文库上搜索。

数码管之简单加减法计算器项目总结.docx

数码管之简单加减法计算器项目总结

数码管之简单加减法计算器--项目总结

总结人:

徐冉

1.项目使用到的硬件板载资源

1)单片机STC89C52RC作为系统的处理器

2)6位共阳极数码管作为计算器的数字显示器件

3)LCD1602液晶显示一些提示信息如计算时的符号(正/负)

4)4*4矩阵按键作为计算器的数字输入设备

5)8个贴片LED小灯,用于走马灯效果作为修饰

6)用到了单片机的内部资源定时器T0

2.项目的基本功能

通过程序的烧录,将工程中的hex文件烧录到Kingst-51开发板上。

现象如下:

初始时

1)最右边的数码管上显示0,其余数码管不显示。

2)五个LED小灯像小火车一样循环跑着。

3)LCD1602液晶的左上角显示Symbol:

字样,用于显示符号。

正数不显示,负数时将显示‘-’。

进行简单的加减法运算

当用户使用按键输入相应的数字时,会在数码管上显示。

数字值将进行进位累加方式实现。

数字键(k13k1~k3k5~k7k9~k110~9),k4加法功能键,k12减法功能键,k14ESC清零键,k4和k12是双功能键,即k4既是加法键也是计算键,k12既是减法键也是计算键。

达到一键两用的效果。

注意:

用户在进行加法计算时可以随意计算,但在计算减法时第一步需要进行一次加法,然后才能进行减法运算。

当计算结果是负数时会在数码管上显示相应的数值的绝对值,而在LCD1602液晶上显示‘-’。

在计算期间LED小灯会一直循环流动。

这个计算器可以实现连加连减,计算十分方便,但没有处理小数。

当计算完成时,或输入错误时可按k14进行清零操作。

3.项目的创新点

首先该项目使用了LED的跑马灯效果进行了装饰,为了程序的简单且直观性程序使用了LCD1602进行运算时符号的显示。

程序在计算上使用了一键两用的功能设计,这样设计方便快捷。

4.项目的设计流程

N

Y

 

5.项目的不足之处

本项目只考虑了简单的加法和减法运算,且只是整数运算,而未能考虑到小数运算。

乘除法亦没有考虑到。

在进行减法运算时都必须进行一次加法运算才可以运算正常。

6.项目需要改进的地方

可对本项目进行全面的扩展,使其既能进行加减乘除运算,又能处理小数和负数的功能。

符号显示直接使用数码管显示即可。

将计算功能键单独进行处理,做成真正的计算器。

7.项目的硬件电路连接图

 

8.项目的源代码

/**

********************************************************************************

*@filemytype.h

*@authorqlp

*@date2014年6月18日

*@versionV1.2.3

*@brief自定义类型头文件

********************************************************************************

*/

#ifndef_MYTYPE_H_H

#define_MYTYPE_H_H

typedefunsignedcharuint8;

typedefunsignedintuint16;

typedefunsignedlonguint32;

#endif//_MYTYPE_H_H

/**

***********************************************************************

*@fileLcd1602.c

*@authorqlp

*@date2014年6月18日

*@versionV1.2.3

*@briefLCD1602液晶底层驱动

***********************************************************************

*/

#include

//LCD1602_IO

sbitLCD1602_RS=P1^0;

sbitLCD1602_RW=P1^1;

sbitLCD1602_EN=P1^5;

//74HC138

sbitADDR0=P1^0;

sbitADDR1=P1^1;

sbitADDR2=P1^2;

sbitADDR3=P1^3;

sbitENLED=P1^4;

bittmpADDR0=0;

bittmpADDR1=0;//地址选择缓冲区

#defineLCD1602_DBP0

/*暂停LED扫描*/

voidLEDRefreshPause()

{

ENLED=1;//关闭LED使能

tmpADDR0=ADDR0;//因为LED和LCD同时使用了P1^0和P1^1引脚,所以要暂时保存ADDR0和ADDR1的数据即LED扫描地址值

tmpADDR1=ADDR1;

P0=0xFF;//数码管+LED小灯去抖动

}

/*继续扫描LED*/

voidContinueRefreshLED()

{

ADDR0=tmpADDR0;

ADDR1=tmpADDR1;//恢复原来LED扫描的地址选择值

ENLED=0;//选择LED

P0=0xFF;//数码管和LED去抖

}

/*液晶忙碌等待*/

voidLCD1602Wait()

{

unsignedcharsta;

LCD1602_DB=0xFF;//总线拉高,检测液晶状态字

LCD1602_RS=0;

LCD1602_RW=1;

do

{

LCD1602_EN=1;

sta=LCD1602_DB;

LCD1602_EN=0;//避免液晶输出数据

}while(sta&0x80);//状态字最高位STA7==0空闲,1忙碌

}

/*液晶写命令*/

voidLCD1602WriteCmd(unsignedcharcmd)

{

LEDRefreshPause();//暂停LED数码管刷新

LCD1602Wait();

LCD1602_RS=0;

LCD1602_RW=0;

LCD1602_EN=0;

LCD1602_DB=cmd;

LCD1602_EN=1;

LCD1602_EN=0;

ContinueRefreshLED();//继续LED数码管刷新

}

/*液晶写数据*/

voidLCD1602WriteData(unsignedchardat)

{

LEDRefreshPause();//暂停LED数码管刷新

LCD1602Wait();

LCD1602_RS=1;

LCD1602_RW=0;

LCD1602_EN=0;

LCD1602_DB=dat;

LCD1602_EN=1;

LCD1602_EN=0;

ContinueRefreshLED();//继续LED数码管刷新

}

/*液晶初始化*/

voidInitalLCD1602()

{

LCD1602WriteCmd(0x38);

LCD1602WriteCmd(0x0C);

LCD1602WriteCmd(0x06);

LCD1602WriteCmd(0x01);//清屏

}

/*写数据到液晶上,字符串str,坐标(x,y),地址addr*/

voidLcdShowStr(unsignedcharx,unsignedchary,unsignedchar*str)

{

unsignedcharaddr;

if(y==0)

{

addr=0x00+x;

}

else

{

addr=0x40+x;

}

LCD1602WriteCmd(addr|0x80);

while(*str!

='\0')

{

LCD1602WriteData(*str++);

}

}

/**

********************************************************************************

*@filemain.c

*@authorqlp

*@date2014年6月18日

*@versionV1.2.3

*@brief简易加减法可实现连加连减

*@note单片机STC89C52RCMCU晶振11.0592MHZ

********************************************************************************

*/

#include

#include

#include"mytype.h"

//74HC138

sbitADDR0=P1^0;

sbitADDR1=P1^1;

sbitADDR2=P1^2;

sbitADDR3=P1^3;

sbitENLED=P1^4;

//时钟晶振和系统时钟

#defineXTAL11059200UL//11.0592MHZ

#defineSYS_XTALXTAL/12//系统时钟,为晶振的12分频

//按键输入输出

sbitKEY_IN_1=P2^4;

sbitKEY_IN_2=P2^5;

sbitKEY_IN_3=P2^6;

sbitKEY_IN_4=P2^7;

sbitKEY_OUT_1=P2^3;

sbitKEY_OUT_2=P2^2;

sbitKEY_OUT_3=P2^1;

sbitKEY_OUT_4=P2^0;

bitflag=0;//0:

add1:

sub

//按键状态枚举

typedefenum{

KEY_DOWN=0,KEY_UP=1

}ekey;

//数据输入口

#defineDISP_DBP0

staticvolatileuint8keySta[4][4]={

{1,1,1,1},

{1,1,1,1},

{1,1,1,1},

{1,1,1,1}

};//按键当前值

/*矩阵按键到PC标准键盘键码映射表*/

uint8codekeyCodeMap[4][4]={

{0x01,0x02,0x03,0x0A},//数字键1-3向上键UP

{0x04,0x05,0x06,0x0D},//数字键4-6向左键Left

{0x07,0x08,0x09,0x0C},//数字键7-9向下键DOWN

{0x00,0x0E,0x0F,0x0B}//数字键0ESC键回车键向右键Right

};

uint8codeLedTable[]={

0xC0,//"0"

0xF9,//"1"

0xA4,//"2"

0xB0,//"3"

0x99,//"4"

0x92,//"5"

0x82,//"6"

0xF8,//"7"

0x80,//"8"

0x90,//"9"

0xBF//"-"

};

/*定义跑马灯数组*/

unsignedcharcodeLedTable2[]={

0xE0,//11100000

0xC1,//11000001

0x83,//10000011

0x07,//00000111

0x0E,//00001110

0x1C,//00011100

0x38,//00111000

0x70//11100000

};

 

uint8LedBuff[7]={0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};//数码管显示缓冲区

uint8thr0,tlr0;

//定义用于加法计算的变量

signedlongresult=0;//结果

signedlongaddNum=0;//加数

voidKeyHandle();

voidKeyAction(uint8keycode);

voidKeyScan();

voidshowNum(uint32num);

voidConfigHC138();

voidConfigTimer0(uint16xms);

externvoidInitalLCD1602();

externvoidLcdShowStr(unsignedcharx,unsignedchary,unsignedchar*str);

voidmain()

{

InitalLCD1602();

ConfigHC138();

ConfigTimer0

(1);

LcdShowStr(0,0,"Symbol:

");//符号

while

(1){

KeyHandle();

}

}

/**

*@brief:

Led小灯扫描

*@param:

*@retval:

*/

voidLED_Scan(void)

{

staticunsignedcharj=0;

P0=0xFF;/*消隐*/

LedBuff[6]=LedTable2[j++];/*送入要求的数据到LED显示数据口*/

j&=0x07;/*到8归零*/

}

/**

*@brief定时器T0配置

*@paramxms

*@retval无

*/

voidConfigHC138()

{

ADDR3=1;

ENLED=0;

LedBuff[0]=LedTable[0];

}

/**

*@brief定时器T0配置

*@paramxms

*@retval无

*/

voidConfigTimer0(uint16xms)

{

uint16tmp;

tmp=65536-xms*SYS_XTAL/1000;

thr0=(uint8)(tmp>>8);

tlr0=(uint8)(tmp&0x00FF);

TMOD&=0xF0;

TMOD|=0x01;

TH0=thr0;

TL0=tlr0;

TR0=1;

EA=1;

ET0=1;

}

/**

*@brief按键驱动函数(根据按下的按键的键码执行相应的动作)

*@param无

*@retval无

*/

voidKeyHandle()

{

staticuint8backup[4][4]={

{1,1,1,1},

{1,1,1,1},

{1,1,1,1},

{1,1,1,1}

};//按键备份值

uint8i=0,j=0;

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

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

{

if(keySta[i][j]!

=backup[i][j])

{

if(backup[i][j]==KEY_DOWN)

{//按键弹起

KeyAction(keyCodeMap[i][j]);//调用按键动作函数,根据按下的按键的键码执行相应的操作

}

backup[i][j]=keySta[i][j];//备份按键值

}

}

}

/**

*@brief按键动作函数(根据按下的按键的键码执行相应的动作)

*@param按下按键的键码uint8keycode

*@retval无

*/

voidKeyAction(uint8keycode)

{

if(result>=0)

{

LcdShowStr(9,0,"");//清除

}

else

{

}

if((keycode>=0x01)&&(keycode<=0x09))//keycode键码是0-9的按键

{

addNum=(addNum*10)+(keycode-0x00);//将原来的加数扩大十倍后,在加上用户按下的数字,即为用户输入的加数

showNum(addNum);//数据分解

}

elseif(keycode==0x0A)//向上键+

{

//将上一个加数+到result中

result+=addNum;//可以实现连加

addNum=0;

showNum(result);//分解并显示结果

}

elseif(keycode==0x0C)//向下键-

{

result-=addNum;//连减

addNum=0;

if(result>=0)

{

showNum(result);

}

else

{

result=-result;

LcdShowStr(9,0,"-");

showNum(result);

result=0;

}

}

elseif(keycode==0x0E)//ESC键

{

result=0;

addNum=0;//清零

showNum(addNum);

LcdShowStr(9,0,"");//清除

}

elseif(keycode==0x0F)//回车键

{

addNum=0;

showNum(result);

}

}

/**

*@brief数据分解,只显示有效位

*@param待分解的数据uint32num

*@retval无

*/

voidshowNum(uint32num)

{

uint8buff[6];//中间缓冲区

signedchari=0;

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

{

buff[i]=num%10;//取最低位数字

num/=10;//num缩小10倍

}

//去掉无效位,不显示0

for(i=5;i>=1;i--)//从最高位开始检测无效位,遇0就赋值0xFF

{

if(buff[i]==0)

{

LedBuff[i]=0xFF;//不显示

}

else

{

break;//遇到第一个有效位就退出

}

}

//将有效位数字存入缓冲区

for(;i>=0;i--)

{

LedBuff[i]=LedTable[buff[i]];

}

}

/**

*@brief按键检测

*@param无

*@retval无

*/

voidKeyScan()

{

staticuint8keybuff[4][4]={

{0xFF,0xFF,0xFF,0xFF},

{0xFF,0xFF,0xFF,0xFF},

{0xFF,0xFF,0xFF,0xFF},

{0xFF,0xFF,0xFF,0xFF}

};//按键检测值缓冲区

staticuint8keyout=0;//行索引

uint8i=0;

keybuff[keyout][0]=(keybuff[keyout][0]<<1)|KEY_IN_1;//检测第keyout行的第0个按键的值

keybuff[keyout][1]=(keybuff[keyout][1]<<1)|KEY_IN_2;

keybuff[keyout][2]=(keybuff[keyout][2]<<1)|KEY_IN_3;

keybuff[keyout][3]=(keybuff[keyout][3]<<1)|KEY_IN_4;

//更新消抖后的按键值

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

{

if((keybuff[keyout][i]&0x1F)==0x1F)//五次连续检测都是1

{

keySta[keyout][i]=KEY_UP;

}

elseif((keybuff[keyout][i]&0x1F)==0x00)//五次连续检测都是0

{

keySta[keyout][i]=KEY_DOWN;

}

}

keyout++;//行++

if(keyout>=4)

keyout=0;

switch(keyout)

{

case0:

KEY_OUT_4=1;KEY_OUT_1=0;break;

case1:

KEY_OUT_1=1;KEY_OUT_2=0;break;

case2:

KEY_OUT_2=1;KEY_OUT_3=0;break;

case3:

KEY_OUT_3=1;KEY_OUT_4=0;break;

default:

break;//只有一行被选中

}

}

/**

*@briefLED数码管刷新

*@param无

*@retval无

*/

voidrefresh()

{

staticuint8j=0;

DISP_DB=0xFF;//消隐

switch(j)

{

case0:

ADDR2=0;ADDR1=0;ADDR0=0;break;

case1:

ADDR2=0;ADDR1=0;ADDR0=1;break;

case2:

ADDR2=0;ADDR1=1;ADDR0=0;break;

case3:

ADDR2=0;AD

展开阅读全文
相关资源
猜你喜欢
相关搜索
资源标签

当前位置:首页 > 高等教育 > 历史学

copyright@ 2008-2023 冰点文库 网站版权所有

经营许可证编号:鄂ICP备19020893号-2