一、項(xiàng)目介紹
計(jì)算器是一種常見的電子產(chǎn)品,廣泛應(yīng)用于各個(gè)領(lǐng)域。而基于單片機(jī)的計(jì)算器設(shè)計(jì)則是學(xué)習(xí)單片機(jī)的一個(gè)重要環(huán)節(jié)。本項(xiàng)目基于STC89C52單片機(jī)設(shè)計(jì)了一款基本的四則運(yùn)算計(jì)算器。
項(xiàng)目里采用了單片機(jī)的IO口、定時(shí)器和LCD1602顯示屏等技術(shù)原理。其中,IO口用于控制矩陣鍵盤、蜂鳴器和LCD1602顯示屏等外設(shè);定時(shí)器用于進(jìn)行鍵盤掃描,確保能夠準(zhǔn)確地捕捉到按鍵的輸入;LCD1602顯示屏用于顯示輸入的數(shù)字和計(jì)算結(jié)果。
設(shè)計(jì)思路主要分為三個(gè)部分:鍵盤掃描、計(jì)算器運(yùn)算和LCD1602顯示。在鍵盤掃描部分,通過定時(shí)器中斷的方式進(jìn)行鍵盤掃描,判斷是否有按鍵按下,并將按鍵對應(yīng)的數(shù)字保存到緩存區(qū)中。在計(jì)算器運(yùn)算部分,采用棧的數(shù)據(jù)結(jié)構(gòu)進(jìn)行計(jì)算器運(yùn)算,當(dāng)按下運(yùn)算符號(hào)時(shí),將之前輸入的數(shù)字壓入棧中,等待下一次輸入。當(dāng)按下“=”時(shí),從棧中取出數(shù)字進(jìn)行計(jì)算,并將結(jié)果保存到棧中。最后將結(jié)果從棧中取出,顯示在LCD1602顯示屏上。在LCD1602顯示部分,通過設(shè)置LCD1602的命令和數(shù)據(jù),可以實(shí)現(xiàn)在LCD1602上顯示數(shù)字和運(yùn)算符號(hào)等內(nèi)容。
最終項(xiàng)目實(shí)現(xiàn)了基本的四則運(yùn)算功能,通過矩陣鍵盤輸入數(shù)字,在LCD1602顯示屏上顯示輸入的數(shù)字和計(jì)算結(jié)果,同時(shí)每次按鍵按下蜂鳴器會(huì)響一聲,反饋按鍵的按下效果。
二、設(shè)計(jì)思路
2.1 設(shè)計(jì)目的
本設(shè)計(jì)利用STC89C52單片機(jī),設(shè)計(jì)一款能夠進(jìn)行基本四則運(yùn)算的計(jì)算器,通過矩陣鍵盤輸入數(shù)字,在LCD1602顯示屏上顯示輸入的數(shù)字和計(jì)算結(jié)果,同時(shí)每次按鍵按下蜂鳴器會(huì)響一聲,反饋按鍵的按下效果。
2.2 硬件設(shè)計(jì)
本設(shè)計(jì)所需的硬件包括STC89C52單片機(jī)、LCD1602顯示屏、矩陣鍵盤、蜂鳴器、電源等。其中,矩陣鍵盤采用4行4列的設(shè)計(jì),通過4個(gè)IO口進(jìn)行控制。LCD1602顯示屏采用8位并行方式,通過6個(gè)IO口進(jìn)行控制。蜂鳴器通過一個(gè)IO口進(jìn)行控制。
2.3 軟件設(shè)計(jì)
本設(shè)計(jì)的軟件主要分為三部分:鍵盤掃描、計(jì)算器運(yùn)算和LCD1602顯示。
【1】鍵盤掃描
由于矩陣鍵盤的特殊性,需要進(jìn)行鍵盤掃描。設(shè)計(jì)采用定時(shí)器中斷的方式進(jìn)行鍵盤掃描,每隔一段時(shí)間進(jìn)行一次掃描,判斷是否有按鍵按下。如果有按鍵按下,則將按鍵對應(yīng)的數(shù)字保存到緩存區(qū)中。
【2】計(jì)算器運(yùn)算
采用棧的數(shù)據(jù)結(jié)構(gòu)進(jìn)行計(jì)算器運(yùn)算。當(dāng)按下運(yùn)算符號(hào)時(shí),將之前輸入的數(shù)字壓入棧中,等待下一次輸入。當(dāng)按下“=”時(shí),從棧中取出數(shù)字進(jìn)行計(jì)算,并將結(jié)果保存到棧中。最后將結(jié)果從棧中取出,顯示在LCD1602顯示屏上。
【3】LCD1602顯示
采用8位并行方式控制LCD1602顯示屏。通過設(shè)置LCD1602的命令和數(shù)據(jù),可以實(shí)現(xiàn)在LCD1602上顯示數(shù)字和運(yùn)算符號(hào)等內(nèi)容。同時(shí),通過設(shè)置光標(biāo)位置,可以實(shí)現(xiàn)在不同位置顯示不同內(nèi)容。
三、代碼實(shí)現(xiàn)
下面是使用STC89C52單片機(jī)設(shè)計(jì)計(jì)算器的完整代碼:
#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; // 第一個(gè)輸入數(shù)字
uchar num2 = 0; // 第二個(gè)輸入數(shù)字
uchar result = 0; // 計(jì)算結(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); // 延時(shí)一段時(shí)間,消除抖動(dòng)
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