如何计算 PIC MCU 中的延迟,如图所示

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

我使用mplab ide和pic-as汇编器编写了一个1秒延迟led闪烁程序。但 LED 不亮。我看不出问题所在。我更改了多个延迟值。一旦图片通电并完全保持在关闭位置,LED 就会亮起。

代码: 处理器 - 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`

一旦图片通电并完全保持在关闭位置,LED 就会亮起。

注意:我用内置代码仔细检查了我的面包板连接,结果很好。

我尝试了各种代码。没关系

assembly delay pic mplab
1个回答
0
投票
  1. DELAY_1s
    子程序不初始化计数器寄存器 使用前请先
    COUNTER_0
    COUNTER_1
    COUNTER_2
    COUNTER_3
    。 确保使用适当的值初始化这些计数器 在进入延迟循环之前。

  2. 延迟环路本身构造不正确。你是 递减计数器寄存器但不重新加载它们 初始值,这意味着循环只会执行一次。 您应该将初始延迟值加载到计数器寄存器中 在进入循环之前。

这是您的代码的可能更正版本

firmware.asm

    PROCESSOR 16f676
    INCLUDE "p16f676.inc"
    RADIX dec
    CONFIG FOSC = INTRCIO
    CONFIG WDTE = OFF
    CONFIG PWRTE = ON
    CONFIG MCLRE = OFF
    CONFIG BOREN = OFF
    CONFIG CP = OFF
    CONFIG CPD = OFF

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

    CODE 0x0000
MAIN:
    BSF RP0, 0
    BCF TRISA, 0
    CLRF ANSEL
    MOVLW 63
    MOVWF OSCCAL

BLINK:
    BCF RP0, 0
    MOVLW 0x00
    MOVWF PORTA
    CALL DELAY_1s
    MOVLW 0x01
    MOVWF PORTA
    CALL DELAY_1s
    GOTO BLINK

DELAY_1s:
    MOVLW 0x0F  ; Load COUNTER_3 with the value 15
    MOVWF COUNTER_3

DELAY_LOOP_3:
    MOVLW 0xFF  ; Load COUNTER_2 with the value 255
    MOVWF COUNTER_2

DELAY_LOOP_2:
    MOVLW 0xFF  ; Load COUNTER_1 with the value 255
    MOVWF COUNTER_1

DELAY_LOOP_1:
    MOVLW 0xFF  ; Load COUNTER_0 with the value 255
    MOVWF COUNTER_0

DELAY_MAIN_1:
    DECFSZ COUNTER_0, F
    GOTO DELAY_MAIN_1

    DECFSZ COUNTER_1, F
    GOTO DELAY_MAIN_1

    DECFSZ COUNTER_2, F
    GOTO DELAY_MAIN_1

    DECFSZ COUNTER_3, F
    GOTO DELAY_LOOP_3

    RETURN
    END

在此代码中:

  • 我已经初始化了计数器寄存器
    COUNTER_0
    COUNTER_1
    COUNTER_2
    COUNTER_3
    在输入之前使用适当的值 延迟循环。
  • 延迟循环已正确构建,并且计数器在每个嵌套循环中重新加载其初始值。
  • 我还为各个循环级别添加了标签,以使代码更加清晰 可读。

请尝试此代码,它应该会产生 1 秒的延迟 用于您的 LED 闪烁程序。

Makefile

TARGET := firmware.hex

all: $(TARGET)

%.hex: %.o
    gplink --map --object --optimize 2 --output $@ $^

%.o: %.asm
    gpasm --object --output $@ $<

clean:
    rm -f *.o *.lst *.map *.hex *.cod
© www.soinside.com 2019 - 2024. All rights reserved.