from machine import Pin
from utime import sleep, ticks_ms, ticks_diff
# 设置GPIO与键盘引脚
row_list = [15, 14, 13, 12] # R行接口
col_list = [5, 4, 3, 2] # C列接口
R = [Pin(i, Pin.OUT, value=1) for i in row_list] # R为输出,初始高电平
C = [Pin(i, Pin.IN, Pin.PULL_UP) for i in col_list] # C为输入,上拉
key_map = [['1', '2', '3', '+'],
['4', '5', '6', '-'],
['7', '8', '9', '*'],
['C', '0', '=', '/']] # 将'#'改为'=', '*'改为'C'更符合计算器习惯
# 计算器状态
input_buffer = '' # 当前输入的数字或表达式
result = 0 # 计算结果
last_key_time = 0 # 上次按键时间(用于防抖)
debounce_time = 50 # 消抖时间(ms)
last_key = None # 记录上一个按键
# 安全计算函数 - 替换不安全的eval()
def safe_calculate(expression):
try:
# 简单验证表达式只包含数字和运算符
allowed_chars = set('0123456789+-*/. ')
if not all(c in allowed_chars for c in expression):
return "Error"
# 分割数字和运算符
tokens = []
current_token = ''
for c in expression:
if c in '+-*/':
if current_token:
tokens.append(float(current_token))
current_token = ''
tokens.append(c)
else:
current_token += c
if current_token:
tokens.append(float(current_token))
# 简单计算逻辑(仅支持两个操作数的运算)
if len(tokens) != 3 or tokens[1] not in '+-*/':
return "Error"
a, op, b = tokens
if op == '+':
return a + b
elif op == '-':
return a - b
elif op == '*':
return a * b
elif op == '/':
if b == 0:
return "Error" # 除零错误
return a / b
except:
return "Error"
# 改进的键盘读取函数
def keypad_read(rows, cols):
global last_key_time, last_key
current_time = ticks_ms()
for i in range(len(rows)):
rows[i].value(0) # 拉低当前行
for j in range(len(cols)):
if cols[j].value() == 0: # 检测列是否被拉低
key = key_map[i][j]
# 消抖处理
if ticks_diff(current_time, last_key_time) > debounce_time or key != last_key:
last_key_time = current_time
last_key = key
rows[i].value(1) # 恢复行高电平
return key
rows[i].value(1) # 恢复行高电平
sleep(0.001) # 短暂延迟
return None
# 处理按键输入
def process_key(key):
global input_buffer, result
if key == 'C': # 清除
input_buffer = ''
return "0"
if key == '=': # 计算结果
if input_buffer:
result = safe_calculate(input_buffer)
input_buffer = str(result) if result != "Error" else "Error"
return input_buffer
return "0"
# 数字输入
if key.isdigit():
# 如果上次结果是错误,清除后重新输入
if input_buffer == "Error":
input_buffer = key
else:
input_buffer += key
return input_buffer
# 运算符输入
elif key in '+-*/':
# 不允许连续输入运算符
if input_buffer and input_buffer[-1] not in '+-*/':
input_buffer += key
# 如果当前是错误状态,用结果继续计算
elif input_buffer == "Error":
input_buffer = str(result) + key if result != "Error" else key
return input_buffer
return input_buffer or "0"
# 主循环
print('-------计算器启动-------')
print('使用说明:')
print('数字键: 0-9')
print('运算符: +, -, *, /')
print('C: 清除')
print('=: 计算结果')
print('-----------------------')
current_display = "0"
last_display = ""
while True:
key = keypad_read(R, C)
if key:
current_display = process_key(key)
if current_display != last_display: # 只有显示变化时才打印
print(current_display)
last_display = current_display
sleep(0.01)