DECFSZ funktioniert nicht auf PIC16LF1823

Ich habe ein Problem beim Versuch, eine Verzögerung auf einem PIC16LF1823 zu machen. Mein Programm versucht 30 ms lang, einige Bits auf PORTC umzuschalten. Ich habe eine einfache Verzögerung basierend auf dem Dekrement einer Variablen gemacht; jedoch jedes Mal, wenn der PIC die Verzögerung ausführt, bleibt er für immer in der Verzögerungs-Subroutine hängen. Ich habe alles versucht und das Problem auf die DECFSZ-Anweisung zurückgeführt (wenn sie entfernt wird, schalten die Bits ohne Verzögerung um und das Programm wird normal ausgeführt). Ist das ein bekanntes Problem? Oder mache ich etwas falsch? Meine Konfiguration: 31kHz Interner Oszillator. Verwendung von MPLAB X und MPASM v5.46. Ich hoffe, jemand kann mich in die richtige Richtung weisen; Ich versuche das jetzt seit einer Woche zu beheben. Danke, hier ist mein Code:

    INCLUDE "P16F1823.inc"

; CONFIG1
__CONFIG _CONFIG1, _FOSC_INTOSC & _WDTE_NSLEEP & _PWRTE_OFF & _MCLRE_OFF & _CP_OFF & _CPD_OFF & _BOREN_ON & _CLKOUTEN_OFF & _IESO_OFF & _FCMEN_OFF
; CONFIG2
__CONFIG _CONFIG2, _WRT_OFF & _PLLEN_OFF & _STVREN_ON & _BORV_LO & _LVP_ON

org 0x00
GOTO Start
org 0x04
GOTO Interrupt

#Define LCK 0x01
#Define LTC 0x04
#Define RLS 0x05

IOA EQU B'00000011'
IOC EQU B'00000000'
IOP EQU B'00000011'
ION EQU B'00000010'
INT EQU B'10001000'
OSC EQU B'00000000'
OPT EQU B'11010000'

CBLOCK
d1
ENDC

;;;;;;;;;;;;;;;;;;
;;INITIALIZATION;;
;;;;;;;;;;;;;;;;;;
Start
BANKSEL PORTA
CLRF PORTA
BANKSEL LATA
CLRF LATA
BANKSEL ANSELA
CLRF ANSELA
BANKSEL TRISA
MOVLW IOA
MOVWF TRISA

BANKSEL PORTC
CLRF PORTC
BANKSEL LATC
CLRF LATC
BANKSEL ANSELC
CLRF ANSELC
BANKSEL TRISC
MOVLW IOC
MOVWF TRISC

BANKSEL OSCCON
MOVLW OSC
MOVWF OSCCON

BANKSEL OPTION_REG
MOVLW OPT
MOVWF OPTION_REG

BANKSEL INTCON
MOVLW INT
MOVWF INTCON
BANKSEL IOCAP
MOVLW IOP
MOVWF IOCAP
BANKSEL IOCAN
MOVLW ION
MOVWF IOCAN

CLRF BSR
;;;;;;;;;;;;;;;;;;
;; MAIN PROGRAM ;;
;;;;;;;;;;;;;;;;;;
Loop
CALL Toggle
GOTO  Loop
;;;;;;;;;;;;;;;;;;
;;  INTERRUPTS  ;;
;;;;;;;;;;;;;;;;;;

;;;;;;;;;;;;;;;;;;
;; SUBROUTINES  ;;
;;;;;;;;;;;;;;;;;;
Toggle
   ;; LATCH ;;
CLRWDT
BSF  PORTC,LTC
CALL Delay30ms
BCF  PORTC,LTC
   ;; WAIT ;;
CALL Delay30ms
   ;;RELEASE;;
BSF  PORTC,RLS
CALL Delay30ms
BCF  PORTC,RLS
   ;; EXIT ;;
RETURN

Delay30ms
MOVLW   0x4C
MOVWF   d1
D30Loop
CLRWDT
DECFSZ  d1, f
GOTO D30Loop
RETURN
;;;;;;;;;;;;;;;;;;
;;END OF PROGRAM;;
;;;;;;;;;;;;;;;;;;
END
Sie verwenden BCF und BSF auf PORT-Bits. AFAIK, diese verbesserten PICs leiden immer noch unter der Read-Modify-Write-'Funktion'. Wenn Sie jetzt nicht wissen, was das ist, schlagen Sie es unbedingt nach !!
Mmmm, ich weiß nicht, ob Sie über den Unterschied zwischen PORT und LAT sprechen ... Wenn ja, obwohl es eine bessere Praxis ist, LAT für Ausgänge zu verwenden, hat PORT den gleichen Effekt (basierend auf dem Datenblatt); Ich werde es trotzdem in LATC ändern, danke für die Beobachtung.
Überprüfen Sie DS41413C-Seite 121, die Schaltung oben. Die LAT-Register lesen, was Sie geschrieben haben, die PORT-Register lesen den tatsächlichen Pegel des Ausgangspins. Das kann unterschiedlich sein. Ein BCF liest alle Pins, ändert einen und schreibt zurück. Daher kann (zum Beispiel) die Belastung eines zuvor gesetzten Pins dazu führen, dass er wieder gelöscht wird. LAT ist nicht nur eine bessere Vorgehensweise, die Verwendung von PORT mit einer Lese-Modifizier-Schreib-Anweisung ist eine sehr schlechte Programmierung.

Antworten (1)

CBLOCK benötigt einen Wert, sonst ist er Null und die Variable befindet sich nicht im RAM. Setzen Sie es auf 0x20, wodurch es an den Anfang des Allzweck-RAM-Blocks gesetzt wird.

Ich kann nichts Falsches an Ihrer Verzögerungsroutine erkennen und es funktionierte gut, als ich es simulierte, um sicherzugehen, dass CBLOCK auf 0x20 eingestellt war.

Entfernen Sie die CLRWDT-Anweisung und deaktivieren Sie die WDT.

Setzen

d1 res 1

am Ende Ihres Programms, wenn Sie Olins bevorzugte Technik verwenden möchten.

CBLOCK weist keine Variablen zu. Dafür ist RES da. CBLOCK dient nur zum Erstellen eines verwandten Satzes von Aufzählungskonstanten. Manchmal missbrauchen Leute CBLOCK, um eine Reihe von Symbolen zu erstellen, von denen dann nur sie wissen (nicht der Assembler oder Linker), dass sie für Adressen von Variablen stehen. Das ist WIRKLICH SCHLECHTE PRAXIS .
Leon, danke für die Antwort; Ich wusste, dass in dieser Erklärung etwas fehlte. Es funktioniert jedoch mit dem WDT; Es besteht keine Notwendigkeit, es zu entfernen.