单片机:实现简易计算器(附带源码)
单片机实现简易计算器
简易计算器是一个经典的单片机应用项目,涉及到数字输入、按键扫描、显示输出以及运算逻辑等方面。在本项目中,我们将使用8051单片机实现一个简易的四则运算计算器,包括加法、减法、乘法和除法运算。
项目目标
本项目的目标是设计并实现一个基于8051单片机的简易计算器,主要实现以下功能:
- 数字输入:通过按键输入数字。
- 运算符输入:支持加法、减法、乘法和除法运算符。
- 显示结果:使用7段数码管或LCD显示屏显示输入的数字和计算结果。
- 计算功能:根据用户输入的数字和运算符,进行相应的计算。
- 清除功能:可以清除输入或重置计算器。
一、硬件设计
1.1 单片机选择
本项目使用8051单片机,它有足够的I/O接口来连接数字按键和显示器,且具有定时器、PWM和中断等功能,非常适合用于实现一个简易计算器。
1.2 外部硬件
1.3 硬件连接
- 按键矩阵:通过行列扫描连接到8051的P1端口(例如P1.0到P1.7)。
- 显示器:7段数码管连接到P2端口,显示输入的数字和计算结果。
- 蜂鸣器:连接到P3.0端口,在错误或操作确认时发出声音。
二、系统设计
2.1 功能模块
- 数字输入模块:通过按键输入数字0-9,用于输入操作数。
- 运算符输入模块:通过按键输入四则运算符(+,-,*,/)。
- 结果显示模块:将输入的数字和运算结果通过7段数码管或LCD显示屏显示出来。
- 计算模块:根据输入的数字和运算符进行四则运算。
- 清除功能:按下C键清除当前输入,重置计算器状态。
2.2 数据结构
2.3 操作流程
- 初始化:初始化LCD或数码管显示,清除存储的数值。
- 数字输入:通过矩阵键盘输入数字,按下数字键时更新显示。
- 选择运算符:按下运算符键时,记录当前的运算符,切换到输入第二个操作数。
- 计算和显示:按下等号键(=)时,计算结果并显示在屏幕上。
- 清除操作:按下C键时,清除当前输入的数字和计算结果,恢复到初始状态。
三、程序设计
3.1 定时器和中断
可以使用定时器来处理按键去抖,确保按键输入稳定可靠。在每次按键扫描时,通过定时器中断触发按键处理程序。
3.2 主程序框架
- 初始化LCD显示和按键矩阵。
- 循环等待用户输入:根据用户输入更新操作数、运算符和计算结果。
- 执行运算:根据输入的运算符执行加法、减法、乘法或除法。
- 更新显示:根据计算结果更新显示屏。
3.3 代码实现
#include <reg51.h> // 包含8051的寄存器定义
// 定义按键矩阵的连接端口
#define KEY_ROW P1
#define KEY_COL P2
// 定义七段数码管连接端口
#define SEG P0
// 定义蜂鸣器连接端口
#define BUZZER P3_0
// 定义常量
#define MAX_INPUT_LEN 4 // 最大输入长度(四位数)
// 操作数和运算符
unsigned char num1 = 0, num2 = 0; // 操作数1和操作数2
unsigned char operator = 0; // 运算符
unsigned char result = 0; // 计算结果
// 按键扫描函数
unsigned char key_scan() {
unsigned char row, col;
KEY_ROW = 0x0F; // 设置为行扫描模式
for (row = 0; row < 4; row++) {
KEY_ROW = ~(1 << row); // 激活一行
for (col = 0; col < 4; col++) {
if (!(KEY_COL & (1 << col))) { // 检测是否按下
delay(20); // 按键去抖
return (row * 4 + col + 1); // 返回按键编号
}
}
}
return 0;
}
// 延时函数(去抖)
void delay(unsigned int time) {
unsigned int i, j;
for (i = 0; i < time; i++) {
for (j = 0; j < 120; j++) {
// 空循环
}
}
}
// 数字显示函数(假设7段数码管)
void display_number(unsigned char num) {
unsigned char seg_data[] = {
0x3F, 0x06, 0x5B, 0x4F, 0x66, 0x6D, 0x7D, 0x07, 0x7F, 0x6F
};
SEG = seg_data[num];
}
// 主程序
void main() {
unsigned char key;
while (1) {
key = key_scan();
if (key) {
if (key <= 9) { // 输入数字
num1 = key; // 当前输入数字存入num1
display_number(num1);
} else if (key == 10) { // 输入加号
operator = '+';
num2 = num1; // 将num1存入num2
num1 = 0; // 清空num1准备输入第二个数字
} else if (key == 11) { // 输入减号
operator = '-';
num2 = num1;
num1 = 0;
} else if (key == 12) { // 输入乘号
operator = '*';
num2 = num1;
num1 = 0;
} else if (key == 13) { // 输入除号
operator = '/';
num2 = num1;
num1 = 0;
} else if (key == 14) { // 输入等号
if (operator == '+') {
result = num2 + num1;
} else if (operator == '-') {
result = num2 - num1;
} else if (operator == '*') {
result = num2 * num1;
} else if (operator == '/') {
if (num1 != 0) {
result = num2 / num1;
} else {
result = 0; // 除0处理
}
}
display_number(result); // 显示结果
} else if (key == 15) { // 清除操作
num1 = 0;
num2 = 0;
result = 0;
operator = 0;
display_number(0); // 清除显示
}
}
}
}
四、程序说明
- 按键扫描:通过矩阵扫描方式获取用户的输入。每次按键按下时,扫描矩阵,检测到按键后返回对应的数字或运算符。
- 数字显示:通过七段数码管显示输入的数字和计算结果。
display_number
函数通过查询预定义的7段数码管编码表,将数字显示在7段数码管上。 - 运算符处理:通过
operator
变量记录当前选择的运算符。用户输入运算符后,程序进入等待第二个操作数的状态。 - 计算处理:按下等号键时,程序根据当前运算符执行相应的运算(加法、减法、乘法、除法),并显示结果。
五、优化与扩展
- 增加多位数输入:目前只支持一位数字输入,可以扩展为支持多位数输入。
- 增强显示功能:可以使用LCD显示屏替代7段数码管,支持显示更复杂的计算过程。
- 除法精度:目前除法操作只支持整数除法,可以改进为支持浮点数运算。
- 错误处理:增加更多的错误处理,比如除以零、输入非法字符等。
六、总结
本项目通过使用8051单片机实现了一个简易计算器,涵盖了数字输入、运算符处理、结果显示和基本的运算功能。通过该项目,可以加深对单片机编程、按键扫描和显示控制的理解,并为更复杂的嵌入式计算器系统打下基础。
作者:Katie。