使用51式单片机基于数码管显示设计一个简易计算器
时间: 2023-12-21 16:23:14 浏览: 186
好的,这个设计可以分为以下几个步骤:
1. 确定需要的功能,例如加减乘除、清零、等于等。
2. 设计数码管显示程序,可采用循环扫描或中断方式。
3. 设计按键扫描程序,检测用户输入的按键,并根据不同的按键触发不同的功能。
4. 设计计算程序,根据用户的输入进行相应的计算操作,并将结果显示在数码管上。
下面是一个简单的设计示例,实现加减乘除四则运算:
1. 功能设计:
- 数字键:0-9
- 运算符键:+、-、*、/
- 清零键:C
- 等于键:=
2. 数码管显示程序:
采用中断方式,每隔一定时间刷新一次数码管显示。
3. 按键扫描程序:
采用轮询方式,循环扫描每个按键,检测用户的输入。
4. 计算程序:
根据用户的输入,进行相应的计算操作,例如:
- 数字键:将数字存储到寄存器中。
- 运算符键:将寄存器中的数字和上一次操作的结果进行相应的运算,将结果存储到寄存器中。
- 清零键:将寄存器中的数字清零。
- 等于键:将寄存器中的数字和上一次操作的结果进行相应的运算,将结果显示在数码管上。
具体实现可以参考下面的代码示例(仅供参考):
```C
#include <reg51.h>
/* 定义数码管各位段选的控制信号 */
#define LED_PORT P0
/* 定义按键的输入信号端口 */
#define KEY_PORT P1
/* 定义按键的控制信号端口 */
#define KEY_CTRL P2
/* 定义计算器状态 */
typedef struct {
unsigned char num; // 当前输入的数字
unsigned char operator; // 当前的运算符
unsigned int result; // 上一次的计算结果
unsigned char flag; // 标志位,表示是否需要清零
} CALCULATOR;
CALCULATOR calc = {0, '+', 0, 1};
/* 定义数码管显示的字符集 */
unsigned char LED_TBL[] = {
0x3f, /* 0 */
0x06, /* 1 */
0x5b, /* 2 */
0x4f, /* 3 */
0x66, /* 4 */
0x6d, /* 5 */
0x7d, /* 6 */
0x07, /* 7 */
0x7f, /* 8 */
0x6f, /* 9 */
};
/* 延时函数 */
void delay_ms(unsigned int ms) {
unsigned int i;
while (ms--) {
for (i = 0; i < 120; i++);
}
}
/* 数码管显示函数 */
void led_display(unsigned int num) {
unsigned char i;
unsigned char buf[4] = {0};
/* 将数字转换为4位数码管显示的字符 */
for (i = 0; i < 4; i++) {
buf[i] = num % 10;
num /= 10;
}
/* 在数码管上显示字符 */
for (i = 0; i < 4; i++) {
LED_PORT = LED_TBL[buf[i]];
KEY_CTRL = ~(1 << i);
delay_ms(2);
KEY_CTRL = 0xff;
}
}
/* 按键扫描函数 */
unsigned char key_scan() {
unsigned char key_val = 0xff;
unsigned char i;
/* 确定按下的键 */
for (i = 0; i < 4; i++) {
KEY_CTRL = ~(1 << i);
if ((KEY_PORT & 0x0f) != 0x0f) {
delay_ms(10);
if ((KEY_PORT & 0x0f) != 0x0f) {
key_val = KEY_PORT & 0x0f;
}
}
}
/* 确定按下的键的类型 */
switch (key_val) {
case 0x0e: /* 数字0 */
return 0;
case 0x0d: /* 数字1 */
return 1;
case 0x0b: /* 数字2 */
return 2;
case 0x07: /* 数字3 */
return 3;
case 0x0c: /* 数字4 */
return 4;
case 0x0a: /* 数字5 */
return 5;
case 0x06: /* 数字6 */
return 6;
case 0x08: /* 数字7 */
return 7;
case 0x09: /* 数字8 */
return 8;
case 0x05: /* 数字9 */
return 9;
case 0x0f: /* 没有按键按下 */
return 0xff;
case 0x0b: /* 加号 */
return '+';
case 0x0a: /* 减号 */
return '-';
case 0x09: /* 乘号 */
return '*';
case 0x05: /* 除号 */
return '/';
case 0x0e: /* 等于号 */
return '=';
case 0x0c: /* 清零键 */
return 'C';
default:
return 0xff;
}
}
/* 计算函数 */
void calculator(unsigned char key) {
switch (key) {
case '+':
case '-':
case '*':
case '/':
/* 计算上一次的结果 */
switch (calc.operator) {
case '+':
calc.result += calc.num;
break;
case '-':
calc.result -= calc.num;
break;
case '*':
calc.result *= calc.num;
break;
case '/':
calc.result /= calc.num;
break;
}
/* 更新当前的运算符和数字 */
calc.num = 0;
calc.operator = key;
calc.flag = 1;
break;
case '=':
/* 计算最终结果 */
switch (calc.operator) {
case '+':
calc.result += calc.num;
break;
case '-':
calc.result -= calc.num;
break;
case '*':
calc.result *= calc.num;
break;
case '/':
calc.result /= calc.num;
break;
}
/* 显示结果 */
led_display(calc.result);
/* 清空计算器状态 */
calc.num = 0;
calc.operator = '+';
calc.result = 0;
calc.flag = 1;
break;
case 'C':
/* 清空计算器状态 */
calc.num = 0;
calc.operator = '+';
calc.result = 0;
calc.flag = 1;
led_display(0);
break;
default:
/* 更新当前的数字 */
if (calc.flag == 1) {
calc.num = key;
calc.flag = 0;
} else {
calc.num = calc.num * 10 + key;
}
/* 显示当前的数字 */
led_display(calc.num);
break;
}
}
/* 主函数 */
void main() {
unsigned char key_val;
/* 初始化按键扫描控制信号 */
KEY_CTRL = 0xff;
while (1) {
/* 扫描按键 */
key_val = key_scan();
/* 处理按键 */
if (key_val != 0xff) {
calculator(key_val);
}
}
}
```
这个计算器的功能比较简单,可以根据需要进行扩展。
阅读全文