#include <LiquidCrystal.h> // 引入LiquidCrystal函式庫,用於操作LCD顯示器
#include <Keypad.h> // 引入Keypad函式庫,用於處理鍵盤輸入
#include <Servo.h> // 引入Servo函式庫,雖然本程式未使用
/* Display */
LiquidCrystal lcd(12, 11, 10, 9, 8, 7); // 初始化LCD,指定控制引腳
/* Keypad setup */
const byte KEYPAD_ROWS = 4; // 定義鍵盤的行數
const byte KEYPAD_COLS = 4; // 定義鍵盤的列數
byte rowPins[KEYPAD_ROWS] = {5, 4, 3, 2}; // 對應鍵盤的行引腳
byte colPins[KEYPAD_COLS] = {A3, A2, A1, A0}; // 對應鍵盤的列引腳
// 定義鍵盤按鍵佈局
char keys[KEYPAD_ROWS][KEYPAD_COLS] =
{
{'1', '2', '3', '+'},
{'4', '5', '6', '-'},
{'7', '8', '9', '*'},
{'.', '0', '=', '/'}
};
// 初始化鍵盤物件
Keypad keypad = Keypad(makeKeymap(keys), rowPins, colPins, KEYPAD_ROWS, KEYPAD_COLS);
uint64_t value = 0; // 全域變數,用於存儲數值
// 顯示啟動畫面
void showSpalshScreen()
{
lcd.print("GoodArduinoCode"); // 在第一行顯示固定文字
lcd.setCursor(3, 1); // 將游標移到第二行中間
String message = "Calculator"; // 設定顯示文字
for (byte i = 0; i < message.length(); i++)
{
lcd.print(message[i]); // 逐字顯示文字
delay(50); // 每次顯示停頓50毫秒
}
delay(500); // 停頓0.5秒
}
// 更新游標的顯示效果(閃爍)
void updateCursor()
{
if (millis() / 250 % 2 == 0)
{ // 每250毫秒檢查一次時間
lcd.cursor(); // 開啟游標
} else
{
lcd.noCursor(); // 關閉游標
}
}
// 初始化設定
void setup()
{
Serial.begin(115200); // 啟動序列埠,波特率設為115200
lcd.begin(16, 2); // 設定LCD為16x2字符顯示
showSpalshScreen(); // 顯示啟動畫面
lcd.clear(); // 清除LCD內容
lcd.cursor(); // 啟用游標
lcd.setCursor(1, 0); // 將游標移到第一行第二列
}
// 定義全域變數,用於計算
char operation = 0; // 儲存目前的運算符號
String memory = ""; // 儲存運算的第一個數值
String current = ""; // 儲存運算的第二個數值
uint64_t currentDecimal; // 儲存小數點相關資訊
bool decimalPoint = false; // 標記是否包含小數點
// 計算函式:根據運算符號執行對應的運算
double calculate(char operation, double left, double right)
{
switch (operation)
{
case '+': return left + right; // 加法
case '-': return left - right; // 減法
case '*': return left * right; // 乘法
case '/': return left / right; // 除法
}
}
// 處理鍵盤輸入
void processInput(char key)
{
// 若輸入負號且目前數值為空,設定為負數
if ('-' == key && current == "")
{
current = "-";
lcd.print("-");
return;
}
switch (key)
{
case '+':
case '-':
case '*':
case '/':
if (!operation)
{ // 若未設定運算符號
memory = current; // 將目前數值儲存為第一數值
current = ""; // 清空目前數值
}
operation = key; // 儲存運算符號
lcd.setCursor(0, 1); // 將游標移到第二行
lcd.print(key); // 顯示運算符號
lcd.setCursor(current.length() + 1, 1); // 調整游標位置
return;
case '=':
float leftNum = memory.toDouble(); // 將第一數值轉為浮點數
float rightNum = current.toDouble(); // 將第二數值轉為浮點數
memory = String(calculate(operation, leftNum, rightNum)); // 計算結果
current = ""; // 清空目前數值
lcd.clear(); // 清空LCD
lcd.setCursor(1, 0); // 移動游標到第一行第二列
lcd.print(memory); // 顯示結果
lcd.setCursor(0, 1); // 將游標移到第二行
lcd.print(operation); // 顯示運算符號
return;
}
// 防止多次輸入小數點
if ('.' == key && current.indexOf('.') >= 0)
{
return;
}
// 處理數字與小數點輸入
if ('.' != key && current == "0")
{
current = String(key); // 如果目前數值為0,取代為輸入值
} else if (key)
{
current += String(key); // 追加輸入值
}
lcd.print(key); // 在LCD上顯示輸入值
}
// 主迴圈:不斷檢查鍵盤輸入
void loop()
{
updateCursor(); // 更新游標顯示
char key = keypad.getKey(); // 讀取鍵盤輸入
if (key)
{
processInput(key); // 處理鍵盤輸入
}
}