51单片机实现三位十进制数加减乘除运算
一.题目
51单片机IO接口作业
请将附件给出的Proteus图用51单片机完成一个计算器功能。
1、显示采用动态分时8位共阳数码管输出。
2、采用4*4矩阵键盘输入,键盘上已经标识对应键。
3、完成三位十进制数的加、减、乘、除运算。
4、开机显示最右边数码管显示‘0’,输入按键值后依次左移。"+—*/"数码管显示分别“A B C D”。
按要求上交实验报告(加、减、乘、除的对应的Proteus仿真截图一定要有,下载到开发板图也必须有)。
二.实验思路
程序分为以下几步:
- 数码管显示模块,数码管上显示数字
- 矩阵键盘模块,用户按下按键返回相应的按键值
- 主函数,实现加减乘除运算,偷了点懒,其实加减乘除运算也可以独立出来做成一个模块
三.程序代码
#include<reg52.h>
//共阳极数码管
unsigned char code segCodeTable[16] = {0xc0,0xf9,0xa4,0xb0,
0x99,0x92,0x82,0xf8,
0x80,0x90,0x88,0x83,
0xc6,0xa1,0x86,0x8e};
//位码表
unsigned char code posCodeTable[8] = {
0x80,0x40,0x20,0x10,0x08,0x04,0x02,0x01};
unsigned char code key_value[16]={0xD7,0xEB,0xDB,0xBB,0xED,0xDD,0xBD,0xEE,0xDE,0xBE,0x77,0x7B,0x7D,0x7E,
0xB7,0xE7};//键盘标识对应的键盘值
void dis_seg7(unsigned long num,unsigned char dec_hex);
unsigned char keyscan();
void delayms (void);
unsigned char pre_P1;
void main()
{
unsigned char key0=0,key1=0,key2=0;
unsigned char value = 0,j = 0;
unsigned char state = 0;
unsigned char dec_hex = 10;
unsigned int NUMA = 0,NUMB = 0;
unsigned long dis_num = 0;
while(1)
{
value = keyscan();
//if((pre_P1 == 0xf0)&&(P1 != 0xf0))
//实现数码管显示多位数字
if((pre_P1 == 0xf0)&&(P1 != 0xf0))
{
if(value >= 0 && value <= 9)
{
dec_hex = 10;
key2 = key1;
key1 = key0;
key0 = value;
dis_num = 100*key2 + 10* key1 + key0;
}
//按下操作符+-*/前,保存数码管显示数字dis_num到NUMA
// key0 = 0;key1 = 0;
//key2 = 0;dis_num = value;
//上述四条语句的目的:按下操作符显示对应的16进制数;
//实现数码管的清零,即实现120+150,数码管一次显示120;
//A(表示加号);150
else if(value>=10&&value<=13)
{
NUMA = dis_num;
key0 = 0;
key1 = 0;
key2 = 0;
dis_num = value;
dec_hex = 16;
if(value == 10 )
{
state ='+';
}
else if(value == 11)
{
state = '-';
}
else if (value == 12)
{
state = '*';
}
else if (value == 13)
{
state = '/';
}
}
//按下等号时,保存数码管显示数字dis_num到NUMB,实现计算
else if(value == 14)
{
dec_hex = 10;
key0 = 0;
key1 = 0;
key2 = 0;
NUMB = dis_num;
if(state == '+')
{
dis_num = NUMA + NUMB;
}
else if(state == '-')
{
dis_num = NUMA - NUMB;
}
else if(state == '*')
{
dis_num = NUMA * NUMB;
}
else if(state == '/')
{
dis_num = NUMA / NUMB;
}
}
//数码管清零
else if(value == 15)
{
dec_hex = 10;
key0 = 0;
key1 = 0;
key2 = 0;
NUMA = 0;
NUMB = 0;
dis_num = 0;
}
}
pre_P1 = P1;
dis_seg7(dis_num,dec_hex);
for(j = 0;j < 200;j++);
}
}
//七段数码管显示模块
void dis_seg7(unsigned long num,unsigned char dec_hex)
{
char i = 0,count = 8;
unsigned int j =0;
char dis_data = 0;
for(i = 0;i < count;i++)
{
dis_data = num % dec_hex;
num = num / dec_hex;
P2 = segCodeTable[dis_data];
P3 = posCodeTable[i];
for(j = 0;j < 200;j++);
P2 = 0xff; //清除余晖
if(num == 0)
{
break;
}
}
}
//延时模块
void delayms (void)
{
unsigned char i;
for (i=200;i>0;i--);
}
//按键扫描模块
unsigned char keyscan()
{
unsigned char rowscan,colscan,row_col,i;
static unsigned char value;
P1 = 0xf0; //P1输出 0xf0
if((P1&0xf0) != 0xf0) //P1读入数据,判断是否有按键按下
{
delayms();//延时消抖
if((P1&0xf0) != 0xf0)
{
//本代码采用逐行扫描的方式来确定按下的按键
rowscan = 0xfe;
while((rowscan&0x10)!=0)
{
P1 = rowscan;
colscan = P1 & 0xf0;
if(colscan != 0xf0)
{
//确定按下按键的行号与列号,查表,返回按键值
row_col = colscan | (rowscan&0x0f);
for(i = 0;i<16;i++)
{
if(row_col == key_value[i])
{
value = i;
}
}
break;
}
else
{
rowscan = (rowscan << 1) | 0x1;
}
}
}
}
return value;
}
四.运行结果
1.加法
123 + 456 = 579
2.减法
789 - 123 = 666
3.乘法
100 * 234 = 23400
4.除法
480/160 =3
github下载链接
代码及proteus工程下载