一、項(xiàng)目介紹
計算器是一種常見的電子產(chǎn)品,廣泛應(yīng)用于各個領(lǐng)域。而基于單片機(jī)的計算器設(shè)計則是學(xué)習(xí)單片機(jī)的一個重要環(huán)節(jié)。本項(xiàng)目基于STC89C52單片機(jī)設(shè)計了一款基本的四則運(yùn)算計算器。
項(xiàng)目里采用了單片機(jī)的IO口、定時器和LCD1602顯示屏等技術(shù)原理。其中,IO口用于控制矩陣鍵盤、蜂鳴器和LCD1602顯示屏等外設(shè);定時器用于進(jìn)行鍵盤掃描,確保能夠準(zhǔn)確地捕捉到按鍵的輸入;LCD1602顯示屏用于顯示輸入的數(shù)字和計算結(jié)果。
設(shè)計思路主要分為三個部分:鍵盤掃描、計算器運(yùn)算和LCD1602顯示。在鍵盤掃描部分,通過定時器中斷的方式進(jìn)行鍵盤掃描,判斷是否有按鍵按下,并將按鍵對應(yīng)的數(shù)字保存到緩存區(qū)中。在計算器運(yùn)算部分,采用棧的數(shù)據(jù)結(jié)構(gòu)進(jìn)行計算器運(yùn)算,當(dāng)按下運(yùn)算符號時,將之前輸入的數(shù)字壓入棧中,等待下一次輸入。當(dāng)按下“=”時,從棧中取出數(shù)字進(jìn)行計算,并將結(jié)果保存到棧中。最后將結(jié)果從棧中取出,顯示在LCD1602顯示屏上。在LCD1602顯示部分,通過設(shè)置LCD1602的命令和數(shù)據(jù),可以實(shí)現(xiàn)在LCD1602上顯示數(shù)字和運(yùn)算符號等內(nèi)容。
最終項(xiàng)目實(shí)現(xiàn)了基本的四則運(yùn)算功能,通過矩陣鍵盤輸入數(shù)字,在LCD1602顯示屏上顯示輸入的數(shù)字和計算結(jié)果,同時每次按鍵按下蜂鳴器會響一聲,反饋按鍵的按下效果。
二、設(shè)計思路
2.1 設(shè)計目的
本設(shè)計利用STC89C52單片機(jī),設(shè)計一款能夠進(jìn)行基本四則運(yùn)算的計算器,通過矩陣鍵盤輸入數(shù)字,在LCD1602顯示屏上顯示輸入的數(shù)字和計算結(jié)果,同時每次按鍵按下蜂鳴器會響一聲,反饋按鍵的按下效果。
2.2 硬件設(shè)計
本設(shè)計所需的硬件包括STC89C52單片機(jī)、LCD1602顯示屏、矩陣鍵盤、蜂鳴器、電源等。其中,矩陣鍵盤采用4行4列的設(shè)計,通過4個IO口進(jìn)行控制。LCD1602顯示屏采用8位并行方式,通過6個IO口進(jìn)行控制。蜂鳴器通過一個IO口進(jìn)行控制。
2.3 軟件設(shè)計
本設(shè)計的軟件主要分為三部分:鍵盤掃描、計算器運(yùn)算和LCD1602顯示。
【1】鍵盤掃描
由于矩陣鍵盤的特殊性,需要進(jìn)行鍵盤掃描。設(shè)計采用定時器中斷的方式進(jìn)行鍵盤掃描,每隔一段時間進(jìn)行一次掃描,判斷是否有按鍵按下。如果有按鍵按下,則將按鍵對應(yīng)的數(shù)字保存到緩存區(qū)中。
【2】計算器運(yùn)算
采用棧的數(shù)據(jù)結(jié)構(gòu)進(jìn)行計算器運(yùn)算。當(dāng)按下運(yùn)算符號時,將之前輸入的數(shù)字壓入棧中,等待下一次輸入。當(dāng)按下“=”時,從棧中取出數(shù)字進(jìn)行計算,并將結(jié)果保存到棧中。最后將結(jié)果從棧中取出,顯示在LCD1602顯示屏上。
【3】LCD1602顯示
采用8位并行方式控制LCD1602顯示屏。通過設(shè)置LCD1602的命令和數(shù)據(jù),可以實(shí)現(xiàn)在LCD1602上顯示數(shù)字和運(yùn)算符號等內(nèi)容。同時,通過設(shè)置光標(biāo)位置,可以實(shí)現(xiàn)在不同位置顯示不同內(nèi)容。
三、代碼實(shí)現(xiàn)
下面是使用STC89C52單片機(jī)設(shè)計計算器的完整代碼:
#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; // 第一個輸入數(shù)字
uchar num2 = 0; // 第二個輸入數(shù)字
uchar result = 0; // 計算結(jié)果
?
void Delay(uint ms)
{
uint i;
while (ms--)
{
for (i = 0; i < 122; i++)
;
}
}
?
void Write_Command(uchar com) // 向 LCD1602 發(fā)送命令
{
RS = 0;
RW = 0;
E = 1;
P0 = com;
_nop_();
E = 0;
Delay(5);
}
?
void Write_Data(uchar dat) // 向 LCD1602 發(fā)送數(shù)據(jù)
{
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() // 讀取矩陣鍵盤輸入的數(shù)字
{
uchar key_num = 0xff; // 初始化為無效值
P3 = 0xf0; // 第一步:P3.0~P3.3 輸出 0,P3.4~P3.7 輸出 1
if (P3 != 0xf0) // 若檢測到有按鍵按下,則進(jìn)入第二步
{
Delay(5); // 延時一段時間,消除抖動
if (P3 != 0xf0) // 再次檢測是否仍然有按鍵按下
{
switch (P3) // 根據(jù)按鍵的位置確定輸入的數(shù)字
{
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; // 復(fù)位 P3 口的狀態(tài)
}
}
return key_num; // 返回輸入的數(shù)字
}
?
void main()
{
Init_LCD1602(); // 初始化 LCD1602 顯示屏
Write_Command(0x80); // 光標(biāo)移到左上角
Write_Data('0'); // 默認(rèn)顯示 0
while (1)
{
num1 = Read_Key