单片机实现简单计算器(4位加减乘除)
在嵌入式系统开发中,实现一个简单的计算器是一个常见且实用的项目,尤其是在学习和实践单片机编程时。我们将通过使用单片机(例如AT89C51)来实现一个支持4位加、减、乘、除的简单计算器。计算器将接收用户输入的两个4位数字,以及操作符,然后进行相应的计算,并通过显示设备(如7段数码管或LCD显示屏)输出结果。
1. 项目需求分析
目标:
- 用户输入:用户通过键盘输入两个4位数字和一个操作符(加、减、乘、除)。
- 显示结果:计算器将显示计算结果(4位数)。
- 操作支持:支持加法、减法、乘法和除法四种基本运算。
- 错误处理:如果除数为0,显示错误提示。
功能需求:
- 输入功能:通过键盘输入数字和运算符。
- 显示功能:通过7段数码管或LCD显示计算结果。
- 运算功能:支持加法、减法、乘法、除法等四则运算。
- 除数为零处理:当用户进行除法运算且除数为零时,计算器应显示“ERROR”。
2. 硬件设计
2.1 单片机选择
本项目使用AT89C51单片机,它具有足够的GPIO端口来连接显示器和键盘。通过串口或并口与显示器连接,通过GPIO口控制键盘输入。
2.2 硬件连接
- 键盘:
- 使用4×4矩阵键盘进行数字和操作符输入。矩阵键盘通过行列连接到单片机的GPIO口。
- 显示设备:
- 可以使用7段数码管或LCD屏来显示输入的数字和计算结果。
- 电源:
- 为单片机和其他外设提供稳定的电源。
2.3 电路设计
- 矩阵键盘:连接至单片机的4行4列引脚。
- 7段数码管:连接至单片机的多个GPIO引脚,用于显示输入的数字和计算结果。
3. 软件设计
3.1 键盘扫描
使用矩阵键盘来输入数字和运算符。每按下一个键,程序将根据扫描键盘的状态,将按键值保存下来。
3.2 运算逻辑
根据用户输入的两个4位数字和操作符进行相应的计算。支持加法、减法、乘法和除法。对于除法操作,需要特别处理除数为零的情况。
3.3 显示功能
使用7段数码管或LCD显示屏显示计算结果。由于结果可能是4位数,需要确保显示器能够显示足够的字符。
3.4 程序设计
- 配置矩阵键盘输入,扫描用户输入。
- 根据输入的数字和运算符进行四则运算。
- 结果通过数码管或LCD显示。
- 错误处理(如除数为零)。
3.5 代码实现
#include <reg51.h> // 包含51单片机的寄存器定义文件
// 定义矩阵键盘的行列引脚
#define ROW1 P1_0
#define ROW2 P1_1
#define ROW3 P1_2
#define ROW4 P1_3
#define COL1 P1_4
#define COL2 P1_5
#define COL3 P1_6
#define COL4 P1_7
// 定义7段数码管连接端口
#define SEGMENTS P2
// 用于存储输入的数字和操作符
unsigned char num1[4], num2[4], operator;
unsigned char result[4]; // 用于存储计算结果
// 函数声明
void delay(unsigned int time);
void init_keypad();
unsigned char scan_keypad();
void display_result(unsigned char* result);
unsigned char calculate(unsigned char num1[], unsigned char num2[], unsigned char operator);
void delay(unsigned int time) {
unsigned int i, j;
for (i = 0; i < time; i++) {
for (j = 0; j < 120; j++);
}
}
// 初始化矩阵键盘扫描
void init_keypad() {
ROW1 = ROW2 = ROW3 = ROW4 = 1; // 设置为输入状态
COL1 = COL2 = COL3 = COL4 = 0; // 设置为低电平
}
// 扫描矩阵键盘
unsigned char scan_keypad() {
unsigned char key = 0;
init_keypad(); // 初始化矩阵键盘
if (COL1 == 0) key = 1; // 按键1
else if (COL2 == 0) key = 2; // 按键2
else if (COL3 == 0) key = 3; // 按键3
else if (COL4 == 0) key = 4; // 按键4
return key;
}
// 数码管显示结果(这里只是示例,具体显示可根据需求调整)
void display_result(unsigned char* result) {
// 显示数组中的数字(假设是4位数)
// 你可以在这里使用具体的显示函数来显示数字
SEGMENTS = result[0]; // 显示第一个数字
delay(500);
SEGMENTS = result[1]; // 显示第二个数字
delay(500);
SEGMENTS = result[2]; // 显示第三个数字
delay(500);
SEGMENTS = result[3]; // 显示第四个数字
}
// 计算两个数字的运算结果
unsigned char calculate(unsigned char num1[], unsigned char num2[], unsigned char operator) {
unsigned int n1 = num1[0] * 1000 + num1[1] * 100 + num1[2] * 10 + num1[3];
unsigned int n2 = num2[0] * 1000 + num2[1] * 100 + num2[2] * 10 + num2[3];
unsigned int res;
switch (operator) {
case '+':
res = n1 + n2;
break;
case '-':
res = n1 - n2;
break;
case '*':
res = n1 * n2;
break;
case '/':
if (n2 == 0) {
// 处理除数为零的情况
result[0] = 'E';
result[1] = 'R';
result[2] = 'R';
result[3] = '0';
return 0; // 错误
}
res = n1 / n2;
break;
default:
return 0; // 错误
}
result[0] = res / 1000; // 高位
result[1] = (res % 1000) / 100; // 次高位
result[2] = (res % 100) / 10; // 次低位
result[3] = res % 10; // 低位
return 1;
}
// 主程序
void main() {
unsigned char key = 0;
unsigned char state = 0; // 用于记录当前输入状态(输入num1、num2或操作符)
while (1) {
key = scan_keypad(); // 扫描按键输入
if (key) {
if (state == 0) { // 输入第一个数字(num1)
num1[0] = key; // 存储按下的数字
state = 1; // 切换到输入num2
} else if (state == 1) { // 输入操作符
operator = key; // 存储操作符
state = 2; // 切换到输入num2
} else if (state == 2) { // 输入第二个数字(num2)
num2[0] = key; // 存储按下的数字
state = 3; // 切换到计算并显示
}
}
if (state == 3) { // 进行计算
if (calculate(num1, num2, operator)) {
display_result(result); // 显示结果
}
state = 0; // 重置状态,准备进行下一次计算
}
}
}
4. 代码解释
-
初始化键盘和显示器:
init_keypad()
函数用于初始化矩阵键盘,准备开始扫描。display_result()
函数用于将计算结果显示在数码管上(这里只是一个简化的示例,具体显示功能可以根据需要设计)。
-
矩阵键盘扫描:
scan_keypad()
函数负责扫描矩阵键盘,返回按下的键值。
-
计算函数:
calculate()
函数根据输入的两个数字和操作符进行计算。支持加法、减法、乘法和除法。当除数为零时,返回错误信息。
-
主程序流程:
- 主程序中不断扫描键盘,等待用户输入数字、操作符和第二个数字,计算结果并显示。
5. 仿真步骤
- 在Proteus中创建一个新项目,添加AT89C51单片机。
- 连接矩阵键盘到单片机的相应引脚,连接数码管或LCD显示器。
- 配置仿真环境,上传代码,启动仿真。
- 仿真时通过键盘输入数字、操作符,观察数码管显示计算结果。
6. 总结
本项目成功实现了一个简单的四则运算计算器,支持加、减、乘、除四种运算,能够进行基本的错误处理(如除数为零)。通过矩阵键盘输入和数码管或LCD显示屏输出,用户能够与计算器进行交互。此设计不仅展示了单片机在数学运算中的应用,还可以作为嵌入式系统学习的基础,具备较高的实用价值。