You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于PIC16F1517与BCD4511的0-9999计数显示程序调试求助

Troubleshooting Your PIC16F1517 BCD Counter Code

Let's walk through the issues causing your jumpy display and erratic counting, then fix them one by one. Most of the problems stem from incorrect BCD logic, display timing, and interrupt configuration—easy fixes once we spot them!

1. Critical TMR0 Interrupt Issues

Your TMR0 interrupt is missing two key steps that cause unstable triggering:

  • No initial TMR0 reload value: The PIC16F1517's TMR0 is an 8-bit counter that overflows from 0xFF to 0x00. Without loading an initial value, your interrupt frequency will be inconsistent, and it will fire extremely fast (e.g., ~1.5kHz with 4MHz INTOSC and 1:256 prescaler), making the display look like it's jumping.
  • Uncleared interrupt flag before enabling interrupts: If TMR0IF was set accidentally, enabling TMR0IE will trigger an immediate interrupt, causing unexpected behavior.

Fix:

Add a TMR0 initial value calculation (example for ~10ms interrupt with 4MHz INTOSC) and reload it every interrupt:

; Add these register definitions at the top
W_TEMP EQU 0x70
STATUS_TEMP EQU 0x71
TMR0_INIT EQU 0xD9 ; Calculated for ~10ms interrupt (4MHz FOSC, 1:256 prescaler)

; In your settings section, initialize TMR0
BANKSEL TMR0
MOVLW TMR0_INIT
MOVWF TMR0

; Update your interrupt service routine (ISR) to save context and reload TMR0
interupt:
    ; Save registers to avoid corrupting main program state
    MOVWF W_TEMP
    SWAPF STATUS, W
    MOVWF STATUS_TEMP
    BCF STATUS, RP0 ; Switch to bank 0
    BCF STATUS, RP1

    ; Reload TMR0 first to keep interrupt timing consistent
    MOVLW TMR0_INIT
    MOVWF TMR0
    BCF INTCON, 2 ; Clear TMR0IF

    ; Your existing counter logic here
    incf WSKP,f
    call check
    call display

    ; Restore registers
    SWAPF STATUS_TEMP, W
    MOVWF STATUS
    SWAPF W_TEMP, F
    SWAPF W_TEMP, W
    retfie

2. Broken BCD Counting Logic

Your check function has incorrect BCD correction logic—you're checking for 0x60 (6 in the tens place) instead of detecting when a BCD digit exceeds 9. This causes wrong increments and resets at the wrong values.

Fix: Replace the check function with this correct BCD increment logic

check:
    ; Handle low byte (units + tens)
    MOVFW WSKP
    ANDLW 0x0F ; Check units digit
    SUBLW 0x09
    BTFSC STATUS, C ; If units <=9, skip correction
    goto CHECK_TENS
    MOVLW 0x06
    ADDWF WSKP, f ; Correct units digit (add 6 to skip non-BCD values)
CHECK_TENS:
    MOVFW WSKP
    ANDLW 0xF0 ; Check tens digit
    SUBLW 0x90
    BTFSC STATUS, C ; If tens <=9, skip carry to high byte
    goto CHECK_HIGH_BYTE
    CLRF WSKP ; Tens digit overflowed, reset low byte
    INCF WSKL, f ; Carry to high byte (hundreds + thousands)

    ; Handle high byte (hundreds + thousands)
CHECK_HIGH_BYTE:
    MOVFW WSKL
    ANDLW 0x0F ; Check hundreds digit
    SUBLW 0x09
    BTFSC STATUS, C ; If hundreds <=9, skip correction
    goto CHECK_THOUSANDS
    MOVLW 0x06
    ADDWF WSKL, f ; Correct hundreds digit
CHECK_THOUSANDS:
    MOVFW WSKL
    ANDLW 0xF0 ; Check thousands digit
    SUBLW 0x90
    BTFSC STATUS, C ; If thousands <=9, skip reset
    goto CHECK_DONE
    CLRF WSKP ; Reset low byte
    CLRF WSKL ; Reset high byte (count wraps from 9999 to 0)
CHECK_DONE:
    RETURN

3. Display Timing & Latch Order Errors

Your display function has the wrong order for latching data to your BCD4511 circuit. You're latching first, then sending data—this means you're locking in old data instead of the new value. You also need a short delay to ensure the display stabilizes between digit switches.

Fix: Rewrite the display function with correct timing

display:
    BCF BI ; Disable display first to prevent flicker during data switch
    ; Update low byte (units + tens)
    MOVFW WSKP
    MOVWF PORTD ; Send data to PORTD first
    BSF LEL ; Latch low byte data
    BCF LEL ; Hold latch state
    ; Update high byte (hundreds + thousands)
    MOVFW WSKL
    MOVWF PORTD ; Send high byte data
    BSF LEH ; Latch high byte data
    BCF LEH ; Hold latch state
    BSF BI ; Re-enable display
    ; Short delay to stabilize display (adjust value as needed)
    MOVLW 0x08
    call SHORT_DELAY
    RETURN

SHORT_DELAY:
    DECFSZ WREG, f
    goto SHORT_DELAY
    RETURN

4. Button Debouncing & Main Loop Logic

Your START loop uses a typo (tmfsc instead of btfsc) and lacks button debouncing. Without debouncing, the RB0 press can trigger multiple times, leading to unexpected interrupt enabling.

Fix: Correct the button check and add debouncing

START:
    BTFSC PORTB, 0 ; Wait for RB0 press (assuming active low)
    goto START
    ; Debounce delay to ignore switch bounce
    MOVLW 0xFF
    call SHORT_DELAY
    BTFSC PORTB, 0 ; Confirm button is still pressed
    goto START
    ; Enable interrupts (clear flag first to avoid immediate trigger)
    BANKSEL INTCON
    BCF INTCON, 2 ; Clear TMR0IF
    BSF INTCON, 7 ; Enable GIE
    BSF INTCON, 5 ; Enable TMR0IE
MAIN_LOOP:
    goto MAIN_LOOP ; Stay in main loop after enabling interrupts

Final Notes

  • Double-check your hardware connections: Ensure the BCD4511's LE pins are connected to RC4/RC5, BI to RC2, and that PORTD is connected to the BCD inputs of each 4511.
  • The prescaler setting in OPTION_REG (1:256) gives a slow enough interrupt for visible counting, but you can adjust TMR0_INIT to make the count faster or slower.

内容的提问来源于stack exchange,提问作者stackingnauledge

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 03:51:52