使用汇编程序对PIC16F84A处理器进行精确延迟编程

时间:2014-05-09 08:53:17

标签: assembly delay pic mplab

我有这个代码 - 所有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。对于cource,我应该在将值设置为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 ??

2 个答案:

答案 0 :(得分: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

答案 1 :(得分:1)

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

我通过三种不同的方法做到了,而且我总是得到相同的结果。

方法1:公式 方法2:用Python模拟 方法3:使用MPLAB仿真器,在函数调用之前和之后设置断点并观察周期计数器。

公式推导如下

让我们首先问自己一个程序,如下所示需要花费多少周期:

循环: decfsz x,f此行运行x次,x-1次不跳,而1次跳, 所以循环数是x-1)+2 goto循环运行x-1次,因此周期为2(x-1) 总的来说,周期是(x-1)+ 2 + 2(x-1)= 3x-1个周期

让我们考虑x在1到256之间(包括1到256,如果x为0等于2​​56)

所以整个程序的循环数是

反周期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 调用,Return和6个初始化行 ------------------------- 总计: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