Linux下Python脚本触发Ctrl+C键盘中断时无法稳定清空LCD显示屏问题
故障根因
- 你当前依赖
KeyboardInterrupt异常捕获的处理逻辑,会在代码任意执行位置触发中断,若中断刚好发生在lcd_driver内部和LCD硬件通信的过程中,会导致驱动对象状态异常,后续finally块调用的清屏、关背光操作就会失效,这就是你遇到的概率性失败的核心原因。 - 大部分LCD驱动的操作是异步发指令到硬件,若Python进程在指令未完全发送到硬件前就退出,也会导致操作不生效。
- 原代码中多个循环没有添加短延迟,CPU占用过高也会增加指令发送被打断的概率。
解决方案
- 显式注册SIGINT(Ctrl+C触发的信号)处理函数,设置退出标记,所有循环逻辑检测到退出标记后主动退出,避免异步中断打断LCD驱动的正常操作,保证驱动状态一致。
- 在清屏、关背光操作前后增加短延迟,确保硬件指令完全下发完成后进程再退出。
- 修复Python3环境下
getaddr函数的字节编码报错问题,降低功能异常概率。
修改后的完整代码
#!/usr/bin/env python import RPi.GPIO as GPIO import lcd_driver import socket import struct import fcntl import time import os import re import signal from time import sleep PIN = 23 COUNT = 0 # 新增全局退出标记 exit_flag = False # 新增SIGINT信号处理函数 def sigint_handler(signum, frame): global exit_flag exit_flag = True # 注册信号处理逻辑 signal.signal(signal.SIGINT, sigint_handler) GPIO.setmode(GPIO.BCM) GPIO.setwarnings(False) GPIO.setup(PIN,GPIO.IN,pull_up_down=GPIO.PUD_UP) print('Writing to Display!') disp = lcd_driver.lcd() def cputemp(): while True: if exit_flag: break cputemp = os.popen("vcgencmd measure_temp").readline() celsius = re.sub("[^0123456789/.]", "", cputemp) fahrenheit = int(9.0/5.0*int(float(celsius)+32)) disp.lcdstring("Cpu : {} C".format(celsius), 1) disp.lcdstring("Temp: {} F".format(fahrenheit), 2) button = GPIO.input(PIN) if button == False: break sleep(0.5) def curtime(): while True: if exit_flag: break disp.lcdstring("Time: {}".format(time.strftime("%H:%M:%S")), 1) disp.lcdstring("Date: {}".format(time.strftime("%m/%d/%Y")), 2) button = GPIO.input(PIN) if button == False: break sleep(0.2) def getaddr(ifname): s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) return socket.inet_ntoa(fcntl.ioctl( s.fileno(), 0x8915, # 修复Python3下字符串需转字节的问题 struct.pack('256s', ifname[:15].encode()) )[20:24]) def getip(): ip = getaddr('wlan0') while True: if exit_flag: break disp.lcdstring("IP Address: WiFi", 1) disp.lcdstring(ip, 2) button = GPIO.input(PIN) if button == False: break sleep(1) try: while True: if exit_flag: break button = GPIO.input(PIN) if button == True: if COUNT == 0: disp.lcdstring("Press the Button",1,0) disp.lcdstring("To Start Demo!",2,1) sleep(0.2) if COUNT == 1: disp.clear() cputemp() if COUNT == 2: disp.clear() curtime() if COUNT == 3: disp.clear() getip() if COUNT == 4: disp.clear() COUNT = 1 if COUNT > 4: disp.clear() COUNT = 0 if button == False: COUNT = COUNT +1 sleep(0.5) finally: # 等待当前未完成的驱动操作执行结束 sleep(0.2) disp.clear() # 等待清屏指令完全下发到硬件 sleep(0.3) disp.backlight(0) sleep(0.2) GPIO.cleanup()
内容的提问来源于stack exchange,提问作者Kristal Luna
相关产品推荐
相关产品推荐

