WDT、TIMER0 16F676 延时计算问题。 MPASM 中的预缩放问题

问题描述 投票:0回答:1

还有一个关于延误的问题。因为我是一名首发球员,所以我对延迟的计算感到头疼。当有人在代码中解释延迟时,我理解延迟。但当谈到我的代码时,我完全一团糟。 (按延迟2天计算)。这是代码;我想在 pic16f676 上的任何端口引脚上每 1 秒闪烁一次 LED:


#include "p16F676.inc"

; CONFIG
; __config 0xFFFC
 __CONFIG _FOSC_INTRCIO & _WDTE_ON & _PWRTE_OFF & _MCLRE_ON & _BOREN_ON & _CP_OFF & _CPD_OFF

usec EQU 0x20

sec EQU 0x23

UNKNOWN  EQU 0x5F

    org         H'0000'                     ;Origem no endereço 00h de memória
    goto        INIT                        ;Desvia para a label início

; --- Vetor de Interrupção ---
    org         H'0004'

isr:
    MOVWF 0x5E
    ; Reinit TMR0  : TMR0 = 8
    MOVLW 8
    MOVWF TMR0
    ; CLEAR TMR FLAG T0IF : T0IF=0
    BCF INTCON, 2
    ; increase 1 microsec
    ; usec++; increase
;-----------------------------------------------------------------------------------------------------
    MOVLW 0x1
    ADDWF usec, F

    MOVLW 0x0F
    SUBWF usec, 0
    MOVWF 0x51
    BTFSS STATUS, 0
    GOTO mangata
lalaind:
    BCF STATUS, RP0   ; RA0=~RA0; // togle RA0
    MOVLW 0x01
    (MOVWF PORTA ); XORWF PORTA, F ==> replaced both    
    MOVLW 0
    MOVWF usec

mangata:
    BCF STATUS, 0x5

    RETFIE

INIT:
    BSF STATUS, 5
    CLRF TRISA
    ; TRISA = 0x00;
    CLRF TRISC

    BCF STATUS, 5
    CLRF PORTA
    ; PORTC = 0;
    CLRF PORTC
    ; GIE = 1;
    BSF INTCON, 7
    ; T0IF = 0;
    BCF INTCON, 2
    ; T0IE = 1;
    BSF INTCON, 5
    ; T0CS = 0;
    BSF STATUS, 5
    BCF OPTION_REG, 5 ;(INternal instruuction cycle clock) (clkout)
    ; PSA = 1;
    BSF OPTION_REG, 3 ;Prescalar applied to WDT
    ; TMR0 = 8;
    MOVLW 8
    BCF STATUS, 0x5
    MOVWF TMR0
    CLRF usec
    ; while(1);

loop:
 GOTO loop

 end

除了延迟外,代码工作正常(在 MPLAB(MPASM) 中)。在正常 255 计数后,定时器 0 调用中断。 usec 减去 15:检查它是否被点燃(我认为当 usec > 15 时状态进位将切换)并在引脚 RA0 上点亮。我假设 DELAY = 255*(15*10) = 38250cycles(抱歉,如果我错了)。

microcontroller pic led mplab
1个回答
0
投票

让我们从现有代码的计算开始。

数据表第31页图4-1显示了相关详细信息:

  • T0CS
    (定时器 0 时钟选择)设置为 0,选择 Fosc/4 作为输入频率。正如您在您的其他问题中评论的那样,振荡器频率为 4 MHz,因此
    CLKOUT
    为 1 MHz。这是每个周期一个时钟周期。
  • PSA
    (预分频器分配)设置为 1,将预分频器分配给看门狗。我们可以在原理图中看到,这会将输入时钟不分频路由到计时器。
  • SYNC
    块适用于从引脚
    T0CKI
    为计时器计时的情况。在这种情况下,它不会改变频率,因此定时器的时钟为 1 MHz。根据数据表,唯一“可见”的结果是写入
    TMR0
    寄存器后启动延迟 2 个周期。
  • 现在,当定时器从 0xFF 溢出到 0x00(十进制 255 到 0)时,它会设置其中断标志
    T0IF
    。您已通过相应设置
    T0IE
    GIE
    启用中断。
  • 初始化时,将 8 写入
    TMR0
    ,将 0 写入
    usec
  • 在中断服务程序中,您将
    TMR0
    重置为8。中断延迟为3个周期,3条指令各1个周期,以及提到的2个周期的同步延迟,这总共是8个周期。偶然(还是故意?)这正是您写入
    TMR0
    的值。
  • 到下一次溢出触发中断,它将额外计数 256 - 8 = 248 个周期。因此中断发生的速率为:
    FT0int =
    CLKOUT
    / 256 = 1,000,000 赫兹 / 256 = = 3906.25 赫兹
    或者您可以认为每个中断触发有 256 个周期。
  • 接下来,变量
    usec
    从 0 计数到 14。PIC 有一种“反转”进位逻辑,如果有借位,则将
    C
    设置为 0。与您的分析相反,只要
    usec
    小于 15,进位标志就会被清除。
    subwf
    从变量中减去
    W
    ,并且如果
    C
    为 15(或更大),则设置
    usec
  • 无论如何,需要 15 个中断才能检测到溢出。所以完整的切换时间是:
    每个中断 256 个周期 * 15 个中断 = 3840 个周期。
    或者作为频率:
    F切换 = FT0int / 15 = 260,4166... Hz

现在要实现您的目标,您需要 1 秒的切换时间。为此,您有多种选择。这些是一些:

  1. 在附加变量中添加另一个除以 260 的除法器。
  2. 将预分频器分配给定时器。将
    PS2
    :
    PS0
    设置为 111,选择 1:256。定时器的输入频率除以256。

结果不完全是 1 秒,但相当接近。人类第一眼不会注意到差异。

备注:

您可能希望推迟启用中断,直到一切准备就绪。否则,根据情况,可能会发生不需要的中断。

由于每次溢出时都会向

TMR0
写入8,因此可以考虑避免这种情况并让计时器运行完毕。它将产生相同的溢出率。

如果您想要精确的时间(在晶体允许的范围内),请更改计时器的重载值,以便它例如每 200 个周期中断一次。然后除以变量再除以 5000 (200 * 5000 = 1000000)。或者使用 1:64 的预分频器,让计时器除以 125。使用另一个 125 的软件分频器,您可以达到相同的目标 (64 * 125 * 125 = 1000000)。秘密在于整数因数乘以 1000000。

© www.soinside.com 2019 - 2024. All rights reserved.