一、項目介紹
計算器是一種常見的電子產品,廣泛應用于各個領域。而基于單片機的計算器設計則是學習單片機的一個重要環節。本項目基于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