PIC汇编实现按键按下时LED输出值逐次递增的问题
问题分析&修改方案
原代码为啥只能实现一次递增?核心俩问题:
- 用了编译时固定的常量
code1,code1+1是死值0x3,每次按键都往PORTB写同一个数,自然没法逐次往上加 - 只检测按键的电平状态,没做边沿触发检测,按住按键会一直重复无效操作,而且没处理机械按键的抖动问题
关键修改点
1. 用RAM变量存当前计数值
- 定义
COUNT作为RAM变量(地址0x0C,属于PIC16F84A的通用寄存器区),专门用来存要输出到LED的数值 - 初始化时把
COUNT设为0,同时让PORTB输出0
2. 给按键加边沿检测+消抖
- 加个
PREV_KEY变量存上一次按键的状态,只有当按键从**没按(高电平)变按下(低电平)**的时候,才执行加1操作,按住的时候不会重复触发 - 加了个
Delay_10ms延时子程序,用来消抖,去掉机械按键按下去时的抖动干扰
3. 把固定值改成动态累加
- 用
incf COUNT,F指令让计数值每次加1(这个是修改RAM里的变量,不是固定死的数值) - 加完之后把
COUNT里的数读到W寄存器,再输出到PORTB
4. 修正按键逻辑
- 原代码的按键分支搞反了,调整成:RA4高电平是按键没按,低电平是按键按下(符合常用的下拉式按键接法)
修改后的完整代码
LIST P=16F84A INCLUDE <P16F84A.INC> ; 设置配置位 __CONFIG _CP_OFF & _WDT_OFF & _PWRTE_ON & _XT_OSC ; 定义通用寄存器:存计数值和按键状态 COUNT EQU 0x0C PREV_KEY EQU 0x0D ; 存上一次按键状态,用于检测按下事件 ; 主程序 ------------------------------------------------------------ Start bsf STATUS, RP0 ; 切到Bank1 movlw b'11111111' movwf TRISA ; PORTA全设为输入 movlw b'00000000' movwf TRISB ; PORTB全设为输出 bcf STATUS, RP0 ; 切回Bank0 movlw d'0' movwf COUNT ; 计数值初始化为0 movwf PORTB ; PORTB初始输出0 movlw b'1' movwf PREV_KEY ; 初始按键状态设为高(未按下) MainLoop btfsc PORTA,4 ; 读RA4当前状态(按下时为低) goto Key_Not_Pressed ; 高电平=没按,跳去处理未按分支 ; 检测到按键按下,先看是不是刚按下去 btfsc PREV_KEY,0 ; 检查上一次状态是不是高 goto Process_Key_Press ; 上一次是高=刚按下,去处理加1 goto MainLoop ; 上一次已经是按下状态,跳过防重复 Process_Key_Press ; 按键消抖:等10ms再确认 call Delay_10ms btfsc PORTA,4 ; 再查一次按键是不是还按住 goto MainLoop ; 已经弹起=干扰,返回主循环 ; 执行加1操作 incf COUNT,F ; 计数值加1,结果存回COUNT movf COUNT,W ; 把计数值读到W寄存器 movwf PORTB ; 输出到PORTB movlw b'0' movwf PREV_KEY ; 更新按键状态为按下 goto MainLoop Key_Not_Pressed btfss PREV_KEY,0 ; 检查上一次是不是按下状态 goto Reset_Key_State ; 上一次是按下=现在弹起,重置状态 goto MainLoop ; 一直没按,返回主循环 Reset_Key_State call Delay_10ms ; 消抖延时 btfss PORTA,4 ; 再确认是不是真的弹起 goto MainLoop ; 没弹起,返回主循环 movlw b'1' movwf PREV_KEY ; 更新按键状态为未按下 goto MainLoop ; 延时子程序:约10ms(4MHz时钟下,指令周期1us) Delay_10ms movlw d'250' movwf 0x0E Delay_Loop1 movlw d'19' movwf 0x0F Delay_Loop2 decfsz 0x0F,F goto Delay_Loop2 decfsz 0x0E,F goto Delay_Loop1 retlw 0 end
运行逻辑
- 初始化时把PORTA设成输入、PORTB设成输出,计数值和PORTB都设为0
- 主循环里盯着RA4:
- 按键没按的时候,重置按键状态标记
- 按键刚按下去(确认不是抖动),就把计数值加1,输出到LED
- 按住按键的时候,不会重复加1,只有松开再按才会触发下一次递增
内容的提问来源于stack exchange,提问作者joepool
相关产品推荐
相关产品推荐

