单片机:实现简易计算器(附带源码)

单片机实现简易计算器

简易计算器是一个经典的单片机应用项目,涉及到数字输入、按键扫描、显示输出以及运算逻辑等方面。在本项目中,我们将使用8051单片机实现一个简易的四则运算计算器,包括加法、减法、乘法和除法运算。

项目目标

本项目的目标是设计并实现一个基于8051单片机的简易计算器,主要实现以下功能:

  1. 数字输入:通过按键输入数字。
  2. 运算符输入:支持加法、减法、乘法和除法运算符。
  3. 显示结果:使用7段数码管或LCD显示屏显示输入的数字和计算结果。
  4. 计算功能:根据用户输入的数字和运算符,进行相应的计算。
  5. 清除功能:可以清除输入或重置计算器。
一、硬件设计
1.1 单片机选择

本项目使用8051单片机,它有足够的I/O接口来连接数字按键和显示器,且具有定时器、PWM和中断等功能,非常适合用于实现一个简易计算器。

1.2 外部硬件
  • 按键输入:通过按键输入数字和运算符。为了简化设计,可以使用一个4×4矩阵键盘,能够输入数字(0-9)和运算符(+,-,*,/,=,C)。
  • 显示器:可以使用7段数码管或者LCD显示屏来显示输入的数字和结果。7段数码管相对简单,适合初学者。
  • 蜂鸣器:用于确认操作或在错误时给出反馈。
  • 电源和电阻:为硬件提供所需的电源和电阻,用于限流和保护电路。
  • 1.3 硬件连接
    1. 按键矩阵:通过行列扫描连接到8051的P1端口(例如P1.0到P1.7)。
    2. 显示器:7段数码管连接到P2端口,显示输入的数字和计算结果。
    3. 蜂鸣器:连接到P3.0端口,在错误或操作确认时发出声音。
    二、系统设计
    2.1 功能模块
    1. 数字输入模块:通过按键输入数字0-9,用于输入操作数。
    2. 运算符输入模块:通过按键输入四则运算符(+,-,*,/)。
    3. 结果显示模块:将输入的数字和运算结果通过7段数码管或LCD显示屏显示出来。
    4. 计算模块:根据输入的数字和运算符进行四则运算。
    5. 清除功能:按下C键清除当前输入,重置计算器状态。
    2.2 数据结构
  • 输入数据:存储当前输入的数字,支持两个操作数。
  • 运算符:存储当前选择的运算符(+,-,*,/)。
  • 计算结果:存储计算的结果,并在显示屏上更新。
  • 2.3 操作流程
    1. 初始化:初始化LCD或数码管显示,清除存储的数值。
    2. 数字输入:通过矩阵键盘输入数字,按下数字键时更新显示。
    3. 选择运算符:按下运算符键时,记录当前的运算符,切换到输入第二个操作数。
    4. 计算和显示:按下等号键(=)时,计算结果并显示在屏幕上。
    5. 清除操作:按下C键时,清除当前输入的数字和计算结果,恢复到初始状态。

    三、程序设计

    3.1 定时器和中断

    可以使用定时器来处理按键去抖,确保按键输入稳定可靠。在每次按键扫描时,通过定时器中断触发按键处理程序。

    3.2 主程序框架
    1. 初始化LCD显示和按键矩阵
    2. 循环等待用户输入:根据用户输入更新操作数、运算符和计算结果。
    3. 执行运算:根据输入的运算符执行加法、减法、乘法或除法。
    4. 更新显示:根据计算结果更新显示屏。
    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);  // 清除显示
                }
            }
        }
    }
    

    四、程序说明

    1. 按键扫描:通过矩阵扫描方式获取用户的输入。每次按键按下时,扫描矩阵,检测到按键后返回对应的数字或运算符。
    2. 数字显示:通过七段数码管显示输入的数字和计算结果。display_number函数通过查询预定义的7段数码管编码表,将数字显示在7段数码管上。
    3. 运算符处理:通过operator变量记录当前选择的运算符。用户输入运算符后,程序进入等待第二个操作数的状态。
    4. 计算处理:按下等号键时,程序根据当前运算符执行相应的运算(加法、减法、乘法、除法),并显示结果。

    五、优化与扩展

    1. 增加多位数输入:目前只支持一位数字输入,可以扩展为支持多位数输入。
    2. 增强显示功能:可以使用LCD显示屏替代7段数码管,支持显示更复杂的计算过程。
    3. 除法精度:目前除法操作只支持整数除法,可以改进为支持浮点数运算。
    4. 错误处理:增加更多的错误处理,比如除以零、输入非法字符等。

    六、总结

    本项目通过使用8051单片机实现了一个简易计算器,涵盖了数字输入、运算符处理、结果显示和基本的运算功能。通过该项目,可以加深对单片机编程、按键扫描和显示控制的理解,并为更复杂的嵌入式计算器系统打下基础。

    作者:Katie。

    物联沃分享整理
    物联沃-IOTWORD物联网 » 单片机:实现简易计算器(附带源码)

    发表回复