assembly 如何计算PIC MCU中的延迟,在pic-as中

cczfrluj  于 8个月前  发布在  其他
关注(0)|答案(1)|浏览(61)

我用mplab ide和pic-as汇编程序写了一个1秒延迟的led Flink 程序。但是LED没有打开。我看不出问题所在。我更改了多个延迟值。led强大的灯光一旦图片是供电和停留在关闭位置完全。
THE CODE:Processor - PIC 16F676
`

CONFIG  FOSC = INTRCIO      

  CONFIG  WDTE = OFF          
  CONFIG  PWRTE = ON            
  CONFIG  MCLRE = OFF         
  CONFIG  BOREN = OFF          
  CONFIG  CP = OFF             
  CONFIG  CPD = OFF            

#include <xc.inc>

COUNTER_0 EQU 0x20
COUNTER_1 EQU 0x21
COUNTER_2 EQU 0x22
COUNTER_3 EQU 0x23

MOV24L macro dest, imm32
 MOVLW (imm32 >> 0) AND 0xff
 MOVWF dest+0
 
 MOVLW (imm32 >> 8) AND 0xff
 MOVWF dest+1
 
 MOVLW (imm32 >> 16) AND 0xff ;SHIFT IMMEDIATE VALUE 16-bit RIGHT
 MOVWF dest+2

 MOVLW (imm32 >> 16) AND 0xff ;SHIFT IMMEDIATE VALUE 16-bit RIGHT
 MOVWF dest+3
 ENDM 
 
psect resetVect, local, class=CODE, delta=2 
 resetVect:
    ORG 0000h
    PAGESEL Main
    GOTO Main

    
psect Code, delta = 2
 Main:
    BSF RP0
    BCF TRISA, 0
    CLRF ANSEL
    MOVLW 63
    MOVWF OSCCAL
 BLINK:
    BCF RP0
    MOVLW 0x00
    MOVWF PORTA
    CALL DELAY_1s
    MOVLW 0x01
    MOVWF PORTA 
    CALL DELAY_1s
    GOTO BLINK
 DELAY_1s:
    MOV24L COUNTER_0, 333332

 DELAY_MAIN_1:
    DECFSZ COUNTER_3
    GOTO DELAY_MAIN_1
    DECFSZ COUNTER_2
    GOTO DELAY_MAIN_1
    DECFSZ COUNTER_1
    GOTO DELAY_MAIN_1
    DECFSZ COUNTER_0
    GOTO DELAY_MAIN_1
    NOP
    NOP
    RETURN

END resetVect`

一旦pic通电,led灯就会亮起来,并完全处于关闭状态。
注:我仔细检查了我的面包板连接与内置代码和它的罚款。
我尝试了Varios代码。它的确定

qoefvg9y

qoefvg9y1#

乍一看,你的输出配置错误,我发现你的输出初始化代码丢失了一些代码,无法正确初始化RA 0作为输出。查看PIC 16 F676的引脚图。RA 0引脚还与ADC模块一起与模拟比较器模块进行多路复用。因此,您应该禁用这两个引脚,以便将此引脚用作数字IO。

datasheet第3节示例1中,微芯片显示了一个初始化代码示例,用于将PORTA引脚设置为数字IO。

BCF     STATUS,RP0  ;Bank 0
CLRF    PORTA       ;Init PORTA
MOVLW   05h         ;Set RA<2:0> to
MOVWF   CMCON       ;digital I/O
BSF     STATUS,RP0  ;Bank 1
CLRF    ANSEL       ;digital I/O
MOVLW   0Ch         ;Set RA<3:2> as inputs
MOVWF   TRISA       ;and set RA<5:4,1:0> as outputs
BCF     STATUS,RP0  ;Bank 0

当涉及到你的延迟代码时,它看起来有点奇怪。首先,你使用一个宏来加载32位的立即值,但是dest+2dest+3加载的是相同的值。您的意图是用imm32 >> 24加载dest+3
虽然您修复了宏,但延迟值不会给您给予1秒延迟。让我们看看...

DELAY_1s:
    MOV24L COUNTER_0, 333332  ; 8 cycles here

 DELAY_MAIN_1:
    DECFSZ COUNTER_3    ; 1 cycle here because the MSB should be zero
    GOTO DELAY_MAIN_1   ; executed as NOP since COUNTER_3 is zero hence 1 cycle
    DECFSZ COUNTER_2    ; 5 * 2 * 2 = 20 cycles - first 2 comes from above 2 instructions and second 2 from below goto inst.
    GOTO DELAY_MAIN_1   ; 2 cycles
    DECFSZ COUNTER_1    ; 22 * 20 * 2 = 880 cycles
    GOTO DELAY_MAIN_1   ; 2 cycle
    DECFSZ COUNTER_0    ; 20 * 880 * 2 = 35200 cycles
    GOTO DELAY_MAIN_1   ; 2 cycle
    NOP                 ; 1 cycle
    NOP                 ; 1 cycle
    RETURN              ; 2 cycle

总周期8 + 35200 + 4 = 35212。
您尚未指定振荡器频率。如果我们假设它是4 MHz,
1指令周期时间= 1 /(4 MHz/ 4)= 1微秒。
那么总延迟将是35,212 us = 35,212 ms,甚至不接近1秒。
我建议你使用this question中的嵌套循环,这样你就可以通过外部循环来折叠内部延迟时间。

编辑

我忘了说33332的价值了。它是一个十进制值,除非您更改程序集的基数控制。它的十六进制表示是0x 51614
如果我们把它分成字节,那么它将是:
| | ||LSB| LSB |
| --|--|--|--|--|
| Hex| 0 |0x5| 0x16| 0x14|
| 小数| 0 | 5 | 22 | 20 |
| 根据你的宏||dest+3 & dest+2| dest+1| dest+0|
正如您在表中看到的,您的dest变量根据您的MOV24L宏加载了这些值。所以我已经根据这些值计算了循环值,唯一的区别是假设你打算用MSB加载dest 3,MSB为0。
然而,如果我根据你在未修改的宏中加载值的方式进行计算,在这种情况下,dest 3将与dest 2具有相同的值,即5。如果我们重新计算延迟周期,这次我们将得到176012 cycles = 176012us = ~176ms,也不接近1秒。希望这足够清楚地告诉你在你的设计中发生了什么。

相关问题