一、项目介绍
计算器是一种常见的电子产品,广泛应用于各个领域。而基于单片机的计算器设计则是学习单片机的一个重要环节。本项目基于STC89C52单片机设计了一款基本的四则运算计算器。
项目里采用了单片机的IO口、定时器和LCD1602显示屏等技术原理。其中,IO口用于控制矩阵键盘、蜂鸣器和LCD1602显示屏等外设;定时器用于进行键盘扫描,确保能够准确地捕捉到按键的输入;LCD1602显示屏用于显示输入的数字和计算结果。
设计思路主要分为三个部分:键盘扫描、计算器运算和LCD1602显示。在键盘扫描部分,通过定时器中断的方式进行键盘扫描,判断是否有按键按下,并将按键对应的数字保存到缓存区中。在计算器运算部分,采用栈的数据结构进行计算器运算,当按下运算符号时,将之前输入的数字压入栈中,等待下一次输入。当按下“=”时,从栈中取出数字进行计算,并将结果保存到栈中。最后将结果从栈中取出,显示在LCD1602显示屏上。在LCD1602显示部分,通过设置LCD1602的命令和数据,可以实现在LCD1602上显示数字和运算符号等内容。
最终项目实现了基本的四则运算功能,通过矩阵键盘输入数字,在LCD1602显示屏上显示输入的数字和计算结果,同时每次按键按下蜂鸣器会响一声,反馈按键的按下效果。
二、设计思路
2.1 设计目的
本设计利用STC89C52单片机,设计一款能够进行基本四则运算的计算器,通过矩阵键盘输入数字,在LCD1602显示屏上显示输入的数字和计算结果,同时每次按键按下蜂鸣器会响一声,反馈按键的按下效果。
2.2 硬件设计
本设计所需的硬件包括STC89C52单片机、LCD1602显示屏、矩阵键盘、蜂鸣器、电源等。其中,矩阵键盘采用4行4列的设计,通过4个IO口进行控制。LCD1602显示屏采用8位并行方式,通过6个IO口进行控制。蜂鸣器通过一个IO口进行控制。
2.3 软件设计
本设计的软件主要分为三部分:键盘扫描、计算器运算和LCD1602显示。
【1】键盘扫描
由于矩阵键盘的特殊性,需要进行键盘扫描。设计采用定时器中断的方式进行键盘扫描,每隔一段时间进行一次扫描,判断是否有按键按下。如果有按键按下,则将按键对应的数字保存到缓存区中。
【2】计算器运算
采用栈的数据结构进行计算器运算。当按下运算符号时,将之前输入的数字压入栈中,等待下一次输入。当按下“=”时,从栈中取出数字进行计算,并将结果保存到栈中。最后将结果从栈中取出,显示在LCD1602显示屏上。
【3】LCD1602显示
采用8位并行方式控制LCD1602显示屏。通过设置LCD1602的命令和数据,可以实现在LCD1602上显示数字和运算符号等内容。同时,通过设置光标位置,可以实现在不同位置显示不同内容。
三、代码实现
下面是使用STC89C52单片机设计计算器的完整代码:
#include < reg52.h >
#include < intrins.h >
#define uint unsigned int
#define uchar unsigned char
sbit beep = P2^3; // 蜂鸣器引脚
sbit RS = P1^0; // LCD1602 串行/并行选择引脚
sbit RW = P1^1; // LCD1602 读/写控制引脚
sbit E = P1^2; // LCD1602 使能引脚
uchar num1 = 0; // 第一个输入数字
uchar num2 = 0; // 第二个输入数字
uchar result = 0; // 计算结果
void Delay(uint ms)
{
uint i;
while (ms--)
{
for (i = 0; i < 122; i++)
;
}
}
void Write_Command(uchar com) // 向 LCD1602 发送命令
{
RS = 0;
RW = 0;
E = 1;
P0 = com;
_nop_();
E = 0;
Delay(5);
}
void Write_Data(uchar dat) // 向 LCD1602 发送数据
{
RS = 1;
RW = 0;
E = 1;
P0 = dat;
_nop_();
E = 0;
Delay(5);
}
void Init_LCD1602() // 初始化 LCD1602 显示屏
{
Write_Command(0x38);
Write_Command(0x0c);
Write_Command(0x06);
Write_Command(0x01);
Delay(5);
}
uchar Read_Key() // 读取矩阵键盘输入的数字
{
uchar key_num = 0xff; // 初始化为无效值
P3 = 0xf0; // 第一步:P3.0~P3.3 输出 0,P3.4~P3.7 输出 1
if (P3 != 0xf0) // 若检测到有按键按下,则进入第二步
{
Delay(5); // 延时一段时间,消除抖动
if (P3 != 0xf0) // 再次检测是否仍然有按键按下
{
switch (P3) // 根据按键的位置确定输入的数字
{
case 0xe0: key_num = 0; break;
case 0xd0: key_num = 1; break;
case 0xb0: key_num = 2; break;
case 0x70: key_num = 3; break;
}
P3 = 0xff; // 复位 P3 口的状态
}
}
return key_num; // 返回输入的数字
}
void main()
{
Init_LCD1602(); // 初始化 LCD1602 显示屏
Write_Command(0x80); // 光标移到左上角
Write_Data('0'); // 默认显示 0
while (1)
{
num1 = Read_Key