单片机:实现设计简单计算器(4位加减乘除)(附带源码)

单片机实现简单计算器(4位加减乘除)

在嵌入式系统开发中,实现一个简单的计算器是一个常见且实用的项目,尤其是在学习和实践单片机编程时。我们将通过使用单片机(例如AT89C51)来实现一个支持4位加、减、乘、除的简单计算器。计算器将接收用户输入的两个4位数字,以及操作符,然后进行相应的计算,并通过显示设备(如7段数码管或LCD显示屏)输出结果。

1. 项目需求分析

目标:
  1. 用户输入:用户通过键盘输入两个4位数字和一个操作符(加、减、乘、除)。
  2. 显示结果:计算器将显示计算结果(4位数)。
  3. 操作支持:支持加法、减法、乘法和除法四种基本运算。
  4. 错误处理:如果除数为0,显示错误提示。
功能需求:
  1. 输入功能:通过键盘输入数字和运算符。
  2. 显示功能:通过7段数码管或LCD显示计算结果。
  3. 运算功能:支持加法、减法、乘法、除法等四则运算。
  4. 除数为零处理:当用户进行除法运算且除数为零时,计算器应显示“ERROR”。

2. 硬件设计

2.1 单片机选择

本项目使用AT89C51单片机,它具有足够的GPIO端口来连接显示器和键盘。通过串口或并口与显示器连接,通过GPIO口控制键盘输入。

2.2 硬件连接
  1. 键盘
    • 使用4×4矩阵键盘进行数字和操作符输入。矩阵键盘通过行列连接到单片机的GPIO口。
  2. 显示设备
    • 可以使用7段数码管LCD屏来显示输入的数字和计算结果。
  3. 电源
    • 为单片机和其他外设提供稳定的电源。
2.3 电路设计
  • 矩阵键盘:连接至单片机的4行4列引脚。
  • 7段数码管:连接至单片机的多个GPIO引脚,用于显示输入的数字和计算结果。

3. 软件设计

3.1 键盘扫描

使用矩阵键盘来输入数字和运算符。每按下一个键,程序将根据扫描键盘的状态,将按键值保存下来。

3.2 运算逻辑

根据用户输入的两个4位数字和操作符进行相应的计算。支持加法、减法、乘法和除法。对于除法操作,需要特别处理除数为零的情况。

3.3 显示功能

使用7段数码管或LCD显示屏显示计算结果。由于结果可能是4位数,需要确保显示器能够显示足够的字符。

3.4 程序设计
  1. 配置矩阵键盘输入,扫描用户输入。
  2. 根据输入的数字和运算符进行四则运算。
  3. 结果通过数码管或LCD显示。
  4. 错误处理(如除数为零)。
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. 代码解释

  1. 初始化键盘和显示器

    • init_keypad()函数用于初始化矩阵键盘,准备开始扫描。
    • display_result()函数用于将计算结果显示在数码管上(这里只是一个简化的示例,具体显示功能可以根据需要设计)。
  2. 矩阵键盘扫描

    • scan_keypad()函数负责扫描矩阵键盘,返回按下的键值。
  3. 计算函数

    • calculate()函数根据输入的两个数字和操作符进行计算。支持加法、减法、乘法和除法。当除数为零时,返回错误信息。
  4. 主程序流程

    • 主程序中不断扫描键盘,等待用户输入数字、操作符和第二个数字,计算结果并显示。

5. 仿真步骤

  1. 在Proteus中创建一个新项目,添加AT89C51单片机
  2. 连接矩阵键盘到单片机的相应引脚,连接数码管或LCD显示器。
  3. 配置仿真环境,上传代码,启动仿真。
  4. 仿真时通过键盘输入数字、操作符,观察数码管显示计算结果。

6. 总结

本项目成功实现了一个简单的四则运算计算器,支持加、减、乘、除四种运算,能够进行基本的错误处理(如除数为零)。通过矩阵键盘输入和数码管或LCD显示屏输出,用户能够与计算器进行交互。此设计不仅展示了单片机在数学运算中的应用,还可以作为嵌入式系统学习的基础,具备较高的实用价值。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/942676.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

企业AI助理背后的技术架构:从数据到智能决策

在当今数字化时代&#xff0c;企业AI助理已经成为推动企业数字化转型和智能化升级的重要工具。它们通过整合企业内外部数据资源&#xff0c;运用先进的算法和模型&#xff0c;为企业提供高效、精准的智能决策支持。本文将深入探讨企业AI助理背后的技术架构&#xff0c;从数据收…

Node.js 工具:在 Windows 11 中配置 Node.js 的详细步骤

一、概述 记录时间 [2024-12-25] 本文讲述如何在 Windows 11 中进行 Node.js 工具的安装和配置。 以下是详细的步骤和说明。 二、安装 Node.js 1. 官网下载 通过官网&#xff0c;下载 Node.js&#xff0c;上面有好几种下载方式&#xff0c;文中下载的是 zip 压缩包。 如图&…

【Rabbitmq篇】高级特性----TTL,死信队列,延迟队列

目录 一.TTL 1.设置消息的TTL 2.设置队列的TTL 3.俩者区别 二.死信队列 定义&#xff1a; 消息成为死信的原因&#xff1a; 1.消息被拒绝&#xff08;basic.reject 或 basic.nack&#xff09; 2.消息过期&#xff08;TTL&#xff09; 3.队列达到最大长度 ​编辑 …

Solon v3.0.5 发布!(Spring 可以退休了吗?)

Solon 框架&#xff01; 新一代&#xff0c;面向全场景的 Java 应用开发框架。从零开始构建&#xff08;非 java-ee 架构&#xff09;&#xff0c;有灵活的接口规范与开放生态。 追求&#xff1a; 更快、更小、更简单提倡&#xff1a; 克制、高效、开放、生态 有什么特点&am…

【PCIe 总线及设备入门学习专栏 1.1 -- PCIe 基础知识 lane和link介绍】

文章目录 OverivewLane 和 LinkRC 和 RPPCIe controllerPCIE ControllerPHY模块 Inbound 和 OutboundPCIe transaction modelPIODMAP2P Overivew PCIe&#xff0c;即PCI-Express总线&#xff08;Peripheral Component Interconnect Express&#xff09;&#xff0c;是一种高速…

安卓 SystemServer 启动流程

目录 引言 Android系统服务启动顺序 zygote fork SystemServer 进程 SystemServer启动流程 1、SystemServer.main() 2、SystemServer.run() 3、初始化系统上下文 4、创建系统服务管理 5、启动系统各种服务 总结 引言 开机启动时 PowerManagerService 调用 AudioSer…

117.【C语言】数据结构之排序(选择排序)

目录 1.知识回顾 2.分析 设想的思路 代码 执行结果 ​编辑 错误排查和修复 详细分析出错点 执行结果 3.正确的思路 4.其他问题 1.知识回顾 参见42.5【C语言】选择排序代码 点我跳转 2.分析 知识回顾里所提到的文章的选择排序一次循环只比一个数字,和本文接下来要…

嵌入式驱动开发详解21(网络驱动开发)

文章目录 前言以太网框架ENET 接口简介MAC接口MII \ RMII 接口MDIO 接口RJ45 接口 PHY芯片以太网驱动驱动挂载wifi模块挂载后续 前言 linux驱动主要是字符设备驱动、块设备驱动还有网络设备驱动、字符设备驱动在本专栏前面已经详细将解了&#xff0c;网络设备驱动本文会做简要…

代码随想录Day37 动态规划:完全背包理论基础,518.零钱兑换II,本周小结动态规划,377. 组合总和 Ⅳ,70. 爬楼梯(进阶版)。

1.完全背包理论基础 思路 完全背包 有N件物品和一个最多能背重量为W的背包。第i件物品的重量是weight[i]&#xff0c;得到的价值是value[i] 。每件物品都有无限个&#xff08;也就是可以放入背包多次&#xff09;&#xff0c;求解将哪些物品装入背包里物品价值总和最大。 完…

软件测试之全链路压测详解

随着业务的快速发展我们日常遇到的系统性能压力问题也逐渐出现&#xff0c;甚至在部分场合会遇到一些突发的营销活动&#xff0c;会导致系统性能突然暴涨&#xff0c;可能导致我们系统的瘫痪。最近几年随着电商的各种促销活动&#xff0c;有一个词也渐渐进入我们眼帘&#xff0…

用于汽车碰撞仿真的 Ansys LS-DYNA

使用 Ansys LS-DYNA 进行汽车碰撞仿真汽车碰撞仿真 简介 汽车碰撞仿真是汽车设计和安全工程的一个关键方面。这些仿真使工程师能够预测车辆在碰撞过程中的行为&#xff0c;从而有助于改进安全功能、增强车辆结构并符合监管标准。Ansys LS-DYNA 是一款广泛用于此类仿真的强大工具…

ES已死,文本检索永生

长期以来&#xff0c;混合查询&#xff08;Hybrid Search&#xff09;一直是提升 RAG&#xff08;Retrieval-Augmented Generation&#xff09;搜索质量的重要手段。尽管基于密集向量&#xff08;Dense Embedding&#xff09;的搜索技术随着模型规模和预训练数据集的不断扩展&a…

43. Three.js案例-绘制100个立方体

43. Three.js案例-绘制100个立方体 实现效果 知识点 WebGLRenderer&#xff08;WebGL渲染器&#xff09; WebGLRenderer是Three.js中最常用的渲染器之一&#xff0c;用于将3D场景渲染到网页上。 构造器 WebGLRenderer(parameters : Object) 参数类型描述parametersObject…

YOLO原理讲解

一、YOLO的输入参数介绍 打标签后会生成一系列参数&#xff0c;包含&#xff1a; 置信度、预测框的位置&#xff08;中心点的位置、高度宽度&#xff09;、类别&#xff08;标签1、标签2、标签3......&#xff09; 二、处理图像和标签 首先YOLO会把图像均分为19*19个格子 &a…

9. zynq应用开发--makefile编译

3. 使用SDK工具 如果只做 Linux 应用开发&#xff0c;只需要一个 sdk.sh 文件即可&#xff0c;可以脱离 Petalinux 和 Vitis&#xff0c;也可以编译其三方的应用&#xff0c;可以说一劳永逸。 配置根文件系统 petalinux-config -c rootfs 编译SDK petalinux-build --sdk Linu…

“鞋履创新工坊”:运动鞋店的新产品设计与管理

3.1 系统可行性分析 开发一款程序软件不仅需要时间&#xff0c;也需要人力&#xff0c;物力资源。而进行可行性分析这个环节就是解决用户这方面的疑问&#xff0c;看看程序在当前的条件下是否可以进行开发。 3.1.1 技术可行性分析 此程序选用的开发语言是Java&#xff0c;这种编…

重温设计模式--6、享元模式

文章目录 享元模式&#xff08;Flyweight Pattern&#xff09;概述享元模式的结构C 代码示例1应用场景C示例代码2 享元模式&#xff08;Flyweight Pattern&#xff09;概述 定义&#xff1a; 运用共享技术有效地支持大量细粒度的对象。 享元模式是一种结构型设计模式&#xff0…

*(int**)是什么意思

有这样一段连续的内存&#xff0c;int*arr(int*)malloc(20); malloc 开辟了 20 个字节大小的空间&#xff0c;arr 指向这段空间的开头 我们要实现像链表一样的功能&#xff0c;有什么方法呢&#xff1f;(关于为什么要在一段连续的空间上实现像链表一样的功能&#xff0c;这只是…

STM32 SPI读取SD卡

七个响应类型&#xff1a; R1 Response (Normal Response): R1响应是最基本的响应&#xff0c;包含一个字节的状态位&#xff0c;用于指示命令是否成功执行。常用。最高位为0。最低位为1表示是空闲状态。其他位是各种错误提示。 R1b Response (Normal with Busy): 类似于R1&a…

[手机Linux] 七,NextCloud优化设置

安装完成后在个人设置里发现很多警告&#xff0c;一一消除。 只能一条一条解决了。 关于您的设置有一些错误。 1&#xff0c;PHP 内存限制低于建议值 512 MB。 设置php配置文件&#xff1a; /usr/local/php/etc/php.ini 把里面的&#xff1a; memory_limit 128M 根据你自…