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

PIC16F676的WDT、TIMER0延迟计算问题:MPASM预分频器异常排查

PIC16F676 LED每秒闪烁问题修复

原代码核心问题分析

  • 预分频器配置错误:原代码设置BSF OPTION_REG, 3(PSA=1),把预分频器分配给了看门狗(WDT),导致TMR0无预分频支持,中断触发频率远高于预期。
  • TMR0中断周期计算偏差:未结合PIC16F的指令周期(4MHz内部RC振荡器下,指令周期为1us)和预分频器参数计算重载值,中断触发时间完全不符合预设逻辑。
  • LED翻转逻辑错误:原代码用MOVLW 0x01 + MOVWF PORTA直接赋值,并非引脚电平翻转,无法实现闪烁效果。
  • 缺少秒级累加逻辑:仅对usec变量做简单累加,没有完成从微秒到毫秒再到秒的层级累计,根本无法实现每秒闪烁的目标。
  • 中断现场保护不完整:只保存了W寄存器,未保存STATUS寄存器,会破坏主程序的状态标志位,引发未知异常。

修正后的完整代码

#include "p16F676.inc"

; CONFIG:关闭看门狗,启用内部RC振荡器,关闭上电延时等
 __CONFIG _FOSC_INTRCIO & _WDTE_OFF & _PWRTE_OFF & _MCLRE_ON & _BOREN_ON & _CP_OFF & _CPD_OFF

; 定义变量:使用通用寄存器区0
ms_count   EQU 0x20   ; 毫秒级计数
sec_flag   EQU 0x21   ; 秒级触发标志

    org H'0000'
    goto INIT

; 中断向量
    org H'0004'
isr:
    ; 完整保存现场:W和STATUS寄存器
    MOVWF 0x5E        ; 保存W到临时寄存器
    SWAPF STATUS, W   ; 保存STATUS到W(避免改变原有状态)
    MOVWF 0x5F        ; 保存STATUS到临时寄存器

    ; 重载TMR0:预分频1:4时,(256-6)*4*1us=1000us=1ms,实现每1ms触发一次中断
    MOVLW 0x06
    MOVWF TMR0
    BCF INTCON, T0IF  ; 清除TMR0中断标志

    ; 累加毫秒计数,判断是否到达1秒
    INCF ms_count, F
    MOVLW 0x03E8      ; 1000ms = 1秒
    SUBWF ms_count, W
    BTFSS STATUS, Z   ; 未到1000ms则直接退出中断
    goto isr_exit

    ; 到达1秒,翻转RA0引脚并重置计数
    MOVLW 0x01
    XORWF PORTA, F    ; 翻转RA0引脚电平
    CLRF ms_count     ; 重置毫秒计数

isr_exit:
    ; 恢复现场
    SWAPF 0x5F, W     ; 恢复STATUS寄存器
    MOVWF STATUS
    SWAPF 0x5E, F
    SWAPF 0x5E, W     ; 恢复W寄存器(避免改变STATUS)
    RETFIE

INIT:
    ; 配置端口方向:PORTA所有引脚设为输出
    BSF STATUS, RP0   ; 切换到寄存器组1
    CLRF TRISA
    CLRF TRISC
    BCF STATUS, RP0   ; 切回寄存器组0

    ; 初始化端口电平
    CLRF PORTA
    CLRF PORTC

    ; 配置TMR0
    BSF STATUS, RP0
    BCF OPTION_REG, T0CS  ; TMR0使用内部指令时钟
    BCF OPTION_REG, PSA   ; 预分频器分配给TMR0
    BSF OPTION_REG, PS2   ; 设置预分频比为1:4(PS2=1, PS1=0, PS0=0)
    BCF OPTION_REG, PS1
    BCF OPTION_REG, PS0
    BCF STATUS, RP0

    ; 初始化TMR0和计数变量
    MOVLW 0x06
    MOVWF TMR0
    CLRF ms_count

    ; 启用中断
    BSF INTCON, T0IE  ; 启用TMR0中断
    BSF INTCON, GIE   ; 启用全局中断

loop:
    goto loop         ; 主循环空转

    end

关键修正点说明

  • 预分频器配置:设置BCF OPTION_REG, PSA将预分频器分配给TMR0,搭配PS2=1, PS1=0, PS0=0得到1:4的预分频比,结合TMR0重载值6,精准实现每1ms触发一次中断。
  • 中断现场保护:完整保存并恢复W和STATUS寄存器,避免中断操作破坏主程序的运行状态。
  • 层级计数逻辑:通过ms_count累计到1000次(即1秒)时触发LED翻转,确保每秒闪烁一次的效果。
  • LED翻转逻辑:使用XORWF PORTA, F实现RA0引脚电平的翻转,正确完成闪烁动作。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.11 05:25:12