【问题标题】:Programming PIC16F84A processor precise delays with assembler使用汇编程序对 PIC16F84A 处理器精确延迟进行编程
【发布时间】:2014-05-09 08:53:16
【问题描述】:

我有这个代码 - 所有 LED 每 1 秒打开和关闭一次(使用 MPLAB X IDE,汇编程序,振荡器频率为 4MHz):

#include <p16f84a.inc>

    __CONFIG _WDTE_OFF & _PWRTE_OFF & _CP_OFF & _FOSC_HS

;General registers for delay
CounterA equ h'0c'
CounterB equ h'0d'
CounterC equ h'0e'

    org 0

Start:
    ; select bank 1
    bsf STATUS, RP0
    ; set port B as output
    movlw b'00000000'
    movwf TRISB
    ; select bank 0
    bcf STATUS, RP0

MainLoop:
    ; turn on LEDS
    movlw b'11111111'
    movwf PORTB
    call Delay_1s
    movlw b'00000000'
    movwf PORTB
    call Delay_1s
    goto MainLoop ;Repeat

Delay_1s:
    movlw d'6'
    movwf CounterC
    movlw d'24'
    movwf CounterB
    movlw d'168'
    movwf CounterA
loop:
    decfsz CounterA,1
    goto loop
    decfsz CounterB,1
    goto loop
    decfsz CounterC,1
    goto loop
    return

    end

有人能解释一下Delay_1s 是如何工作的吗?我试图乘以 168 * 24 * 6 = 24192 µS,但这​​是不正确的,我应该得到 1000000 µS..

编辑:

我越来越近了 - decfsz CounterA,1 需要 1 µS,goto loop 需要 2 µS 来处理。所以我认为答案应该是 (168 * 3) * (24 * 3) * (6 * 3) = 653184 µS。当然,在将值设置为 CounterACounterBCounterC 时,我应该增加 6 µS。有什么我想念的吗?

EDIT2:

我在下面的每个操作中添加了时间值。我理解的对吗?

Delay_1s:
    movlw d'6' ; 1µS
    movwf CounterC ; 1µS
    movlw d'24' ; 1µS
    movwf CounterB ; 1µS
    movlw d'168' ; 1µS
    movwf CounterA ; 1µS
loop:
    decfsz CounterA,1 ; 1µS
    goto loop ; 2µS (the same while skipping)
    decfsz CounterB,1 ; 1µS
    goto loop ; 2µS (the same while skipping)
    decfsz CounterC,1 ; 1µS
    goto loop ; 2µS (the same while skipping)
    return ; 1µS ??

【问题讨论】:

  • 自从我做了很多 PIC 汇编程序以来已经有一段时间了,但我认为诀窍可能是,例如 CounterA 第一次只会是 168,然后第二次会是 256,因为它不会被重置。如果你这样算,那会加起来吗?
  • 是的,它可能是 - 如果 CounterACounterB 从 256 开始(CounterC 只会变为零然后例程返回) - 那么结果是 390150,如果我将它相乘3µS - 然后我得到 1,170450 秒

标签: assembly delay pic mplab


【解决方案1】:

对不起,我不擅长解释,但我希望这能给你一些线索:

  Using a 4MHz Xtal OSC 
  Set OPTION_REG to b'11010100'
                     'xxxxx100' = 1 instruction :32 uSeconds
        32 uSeconds *    250 = 8 milliseconds
        8 milliseconds * 125 = 1 second 
        PORTB (all outs)     = B'00000000'                   

EIGHT_MS   EQU  0x10

INIT
      BSF  STATUS, RP0
      MOVLW      B'11010100'
      MOVWF      OPTION_REG
      MOVLW      B'00000000'
      MOVWF      TRISB
      BCF  STATUS, RP0
      CLRF       PORTB
      RETURN
START
L0    CLRF  TMR0
L1    MOVF  TMR0, W
      XORLW .250
      BTFSS STATUS, Z
      GOTO  L1
      CLRF  TMR0
      INCF  EIGHT_MS 
      MOVF  EIGHT_MS, W
      XORLW .125
      BTFSS STATUS, Z
      GOTO  L1
      CALL  LIGHT_LED
      GOTO  L1      

LIGHT_LED
      ...
      CALL DELAY
      ...

      RETURN


MAIN  
      CALL INIT
      CALL START
      GOTO MAIN

【讨论】:

    【解决方案2】:

    我查看了这个程序,发现这个例程花费的周期数是 1,003,827,相当于 1.003827 秒。

    我用了三种不同的方法,结果总是一样。

    方法一:公式 方法2:Python中的模拟 方法3:使用MPLAB仿真器,设置断点,观察函数调用前后的循环计数器。

    公式推导如下

    让我们先问问自己,像下面这样的程序需要多少个周期:

    循环: decfsz x, f 这条线运行x次,x-1次不跳转,1次跳转, 所以周期数是 x-1) +2 goto loop 这运行 x-1 次,所以周期为 2 (x-1) 总共,周期为 (x-1) + 2 + 2 (x-1) = 3x-1 个周期

    假设x介于1和256之间(包括1和256,如果x为0,则等于256)

    所以完整程序的循环数是

    计数器周期 A B第一次有初始值3A-1 计数器 B (B-1) * (3 * 256-1) 以下次数 计数器 C 的下一次 (C-1) * 256 * 767 计数器 B 周期 第一次当 C 是 6 3B-1 C(C-1)*767的以下次数 计数器 C 周期 第一次也是唯一一次3C-1 调用、返回和 6 个初始化行 10 ------------------------- 总计:3A + 770B + 197 122C-197879

    用 A 代替 168,B = 24 和 C = 6 得到 1,003,837 更好的值应该是 A = 172 B = 19 C = 6 产生 999,999 在变量初始化中添加 nop 将得到 1,000,000

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2022-11-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-09-03
      • 2012-05-25
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多