PIC-typische Abkürzungen im Zusammenhang mit Interrupts:Zitat:
Dazu wird bei jedem Durchlauf der ISR (Interrupt Service Routine)ein Zähler um eins erhöht
IRQ = Interrupt Request = eine Anforderung zur Programmunterbrechung aufgrund eines Ereignisses, z.B. Timerüberlauf, externes Triggersignal am INT-Eingang, ...
ISR = Interrupt Service Routine = der Programmteil, der die angemessene Reaktion auf das jeweilige Ereignis bewirkt
xxxIF = Interrupt Flag = ein ereignisanzeigendes Signalbit, aufgrund dessen eine ISR gestartet wird, kann meist auch ohne Interruptfreigabe vom Hauptprogramm gelesen werden
GIE = Global Interrupt Enable = der Hauptschalter
PIE = Peripheral Interrupt Enable = je Bit eine Freischaltung eines Hardwareinterrupts (UART, Timer, I2C, INT-Eingang ...)
Zur Ersetzung des GOTO:
GOTO braucht's bei den PICs fast an jeder Ecke für Verzweigungen; das Äquivalent zu CALL ( ) wäre GOSUB. Ich will das vorsichtshalber erwähnen, weil ich aus deinem letzten Posting eine Verdrehung diesbezüglich herausgelesen hatte. Nichts für ungut.Zitat:
GOTO und REM aus meiner Basiczeit, werde ich dann auch durch Call und ; ersetzen.
Ja, dass Kommentare wichtig sind, wird selten angezweifelt, keine Frage; die Geister scheiden sich gelegentlich am WIE.
Vielleicht hättest du mit meiner Art des Kommentierens und der vertikalen Gliederung der Sourcedateien ebenfalls Lesbarkeitsprobleme wie ich mit deiner beigefügten Datei; das ist auch eine Frage der Gewohnheit und daher (meist) kein Gegenstand für Kritik.
Zuletzt noch eine Sourcedatei von mir zur direkten Ansteuerung einer doppelten Vollbrücke (für einen (1) Schrittmotor) zum ankucken und evtl. abkupfern von Timer, Int. & Co.
Leider ist das unaufgeräumte Source aus einer ad hoc-Anpassung von bestehendem Code. Da sind noch einige Überbleibsel drin, aber es ist der assemblierfähige Code:
GrußCode:; ToDo:
; =====
; -
; -
; -
;
;
;**********************************************************************
; *
; Filename: VORZRUCK.asm *
; Date: *
; File Version: *
; *
; Author: Christian *
; Company: *
; *
; *
;**********************************************************************
; *
; Files Required: P16F876A.INC *
; *
;**********************************************************************
; *
; Hardwarekonfiguration: *
; -- kein (!) LCD *
; -- 1x Taste f�r Steuereingriffe *
; -- 1x Diagnose-LED *
; -- 2x digitale Eing�nge: Referenz-/Endschalter beider Achsen *
; -- 1x analoger Eingang: CNY70 o.�. zur Pseudo-Wanderkennung *
; -- 2x je 4 digitale Ausg�nge: Schrittmotoransteuerung *
; -- 1x Schaltausgang: Stiftabsenkung *
; *
;**********************************************************************
list p=16f876a ; list directive to define processor
#include <P16F876A.INC> ; processor specific variable definitions
__CONFIG _CP_OFF & _DEBUG_OFF & _WRT_OFF & _CPD_OFF & _LVP_OFF & _BODEN_OFF & _PWRTE_ON & _WDT_OFF & _HS_OSC
; ACHTUNG: Ein 4MHz- oder 10MHz-Oszillator mit _LP_OSC-Config-Bits l�uft nicht an !!!
;*****************************************************************************
; '__CONFIG' directive is used to embed configuration data within .asm file.
; The labels following the directive are located in the respective .inc file.
; See respective data sheet for additional information on configuration word.
;*****************************************************************************
; STATUS-Bits
#define _C STATUS,0 ; f�r die Kurzschreibung von Bitpr�fungen: "BTFSS _C"
#define _Z STATUS,2 ;
; Hardware-Signale
#define LED buf_rc,0 ; Diagnose-LED
#define PENDWN buf_rc,7 ; Stiftabsenkung
#define SWX sta_rc,6 ; Endschalter X-Achse
#define SWY sta_rc,5 ; Endschalter Y-Achse
#define KEY sta_rc,1 ; Steuertaste
; Flag-Bits
#define DRIGGD flax,0 ; =1: fraenk. fuer "Taste betaetigt"
#define BUMPED flax,1 ; =1: an die Wand gesto�en
#define DIR_FWD flax,2 ; =1: vorw�rts bewegen
#define DIR_REV flax,3 ; =1: r�ckw�rts bewegen
;***** KONSTANTEN
;numerische Konstanten
SACHT EQU d'2' ; Motorschritte nach jeweils (SACHT*1ms)
LIMDUNK EQU d'180' ; unterhalb Kollisionsbit setzen
LIMHELL EQU d'200' ; oberhalb Kollisionsbit l�schen
;***** BANK(0)-EXKLUSIVE REGISTER 0x20..0x6F
;== 0x20 ===
scr1 EQU 0x20 ; Scratch-Bytes f�r Subroutinen
scr2 EQU 0x21 ;
scr3 EQU 0x22 ;
scr4 EQU 0x23 ;
par0 EQU 0x24 ; Ersatz f�r Stack-Parameter�bergabe
par1 EQU 0x25 ;
par2 EQU 0x26 ;
flax EQU 0x27 ; diverse Flags
x28 EQU 0x28 ;
x29 EQU 0x29 ;
restweg EQU 0x2A ; verbleibender Verfahrweg in Halbschritten
x2b EQU 0x2B ;
x2c EQU 0x2C ;
slowpe EQU 0x2D ;
indexx EQU 0x2E ; 2 Zeiger auf die Bitmuster-Arrays
indexy EQU 0x2F ; zur Stepper-Ansteuerung
;== 0x30 ===
x30 EQU 0x30 ;
x31 EQU 0x31 ;
x32 EQU 0x32 ;
x33 EQU 0x33 ;
x34 EQU 0x34 ;
x35 EQU 0x35 ;
x36 EQU 0x36 ;
x37 EQU 0x37 ;
x38 EQU 0x38 ;
x39 EQU 0x39 ;
x3a EQU 0x3A ;
x3b EQU 0x3B ;
x3c EQU 0x3C ;
x3d EQU 0x3D ;
x3e EQU 0x3E ;
x3f EQU 0x3F ;
;== 0x40 ===
;x40 EQU 0x40 ;
; hier kommen zwei Arrays zu je 8 Byte f�r die Ansteuerung der Stepper
; sie werden sp�ter mit den ben�tigten Bitmustern bef�llt
pattx1 EQU 0x40 ; BASIS: Array[8] der X-Pattern
pattx2 EQU 0x41 ; Ansteuerungssequenz X-Achse
pattx3 EQU 0x42 ; bis ...
pattx4 EQU 0x43 ; ...
pattx5 EQU 0x44 ; ...
pattx6 EQU 0x45 ; ...
pattx7 EQU 0x46 ; ...
pattx8 EQU 0x47 ; ... hierher !
patty1 EQU 0x48 ; BASIS: Array[8] der Y-Pattern
patty2 EQU 0x49 ; Ansteuerungssequenz Y-Achse
patty3 EQU 0x4A ; bis ...
patty4 EQU 0x4B ; ...
patty5 EQU 0x4C ; ...
patty6 EQU 0x4D ; ...
patty7 EQU 0x4E ; ...
patty8 EQU 0x4F ; ... hierher !
;== 0x50 ===
x50 EQU 0x50 ;
x51 EQU 0x51 ;
x52 EQU 0x52 ;
x53 EQU 0x53 ;
x54 EQU 0x54 ;
x55 EQU 0x55 ;
x56 EQU 0x56 ;
x57 EQU 0x57 ;
x58 EQU 0x58 ;
x59 EQU 0x59 ;
x5a EQU 0x5A ;
x5b EQU 0x5B ;
x5c EQU 0x5C ;
x5d EQU 0x5D ;
x5e EQU 0x5E ;
x5f EQU 0x5F ;
;== 0x60 ===
buf_rb EQU 0x60 ; PORTB-Pufferregister gegen die read-modify-write-Falle
buf_rc EQU 0x61 ; dito Port C
sta_rc EQU 0x62 ; Binärstatus von Port C
val_wall EQU 0x63 ; Meßwert des Wandsensors
x64 EQU 0x64 ;
x65 EQU 0x65 ;
x66 EQU 0x66 ;
x67 EQU 0x67 ;
x68 EQU 0x68 ;
x69 EQU 0x69 ;
x6a EQU 0x6A ;
iscr EQU 0x6B ; scratch in der ISR
x6c EQU 0x6C ;
x6d EQU 0x6D ;
x6e EQU 0x6E ;
x6f EQU 0x6F ;
;***** BANK(1)-EXKLUSIVE REGISTER 0xA0..0xEF
;== 0xA0 ===
;== 0xB0 ===
;== 0xC0 ===
;== 0xD0 ===
;== 0xE0 ===
;***** BANK(2)-EXKLUSIVE REGISTER 0x110..0x11F (Nische)
;== 0x110 ===
;***** BANK(2)-EXKLUSIVE REGISTER 0x120..0x16F
;== 0x120 ===
;== 0x130 ===
;== 0x140 ===
;== 0x150 ===
;== 0x160 ===
;***** BANK(3)-EXKLUSIVE REGISTER 0x190..0x19F (Nische)
;== 0x190 ===
;***** BANK(3)-EXKLUSIVE REGISTER 0x1A0..0x1EF
;== 0x1A0 ===
;== 0x1B0 ===
;== 0x1C0 ===
;== 0x1D0 ===
;== 0x1E0 ===
;***** GLOBALE VARIABLEN 0x70..0x7F
x70 EQU 0x70 ;
x71 EQU 0x71 ;
x72 EQU 0x72 ;
x73 EQU 0x73 ;
x74 EQU 0x74 ;
x75 EQU 0x75 ;
x76 EQU 0x76 ;
x77 EQU 0x77 ;
x78 EQU 0x78 ;
dlycnt EQU 0x79 ; Delay-Restzyklen zu je 1ms
ticker EQU 0x7A ; virtuelle Unruh; immerzu in Bewegung
hitick EQU 0x7B ; �berlaufz�hler f�r ticker
temp_w EQU 0x7C ; variable used for context saving
temp_status EQU 0x7D ; variable used for context saving
temp_pclath EQU 0x7E ; variable used for context saving
temp_fsr EQU 0x7F ; variable used for context saving
;**********************************************************************
;**********************************************************************
ORG 0x0000 ; Begin of 2k-Code Page #0 (1st)
; processor reset vector
;**********************************************************************
;**********************************************************************
nop ; nop required for icd
goto MAIN ; go to beginning of program
nop
nop
;**********************************************************************
;**********************************************************************
ORG 0x0004 ; interrupt vector location
;**********************************************************************
;**********************************************************************
;********** Kontext sichern **********
movwf temp_w ; save off current W register contents
movf STATUS,w ; move status register into W register
movwf temp_status ; save off contents of STATUS register
movf PCLATH,w ; move pclath register into w register
movwf temp_pclath ; save off contents of PCLATH register
movf FSR,w ;
movwf temp_fsr ;
; Lead-In
;bcf INTCON,GIE ; globales IRQ-Disable ;;; das geschieht schon automatisch bei der IRQ response
bcf STATUS,RP0 ;
bcf STATUS,RP1 ; Bank 0 als default
bcf PCLATH,4 ;
bcf PCLATH,3 ; Code Page #0
;********** ISR f�r den Timer0-Interrupt
ISR_TMR0
; IRQ-flag l�schen und preload
bcf INTCON,T0IF ; Timer0-IRQ
movlw d'8' ; 256-(250-2!) = 8 f�r 1000,0 Hz @ 4,00MHz !!! DIESEN WERT AUCH BEIM INIT SETZEN !!!
movwf TMR0 ; preload = verk�rzter Anlauf zum n�chsten �berlauf-IRQ
;ADC auslesen und speichern
ISR_ADC_1
; warten, dann ablesen
btfsc ADCON0,GO_DONE ; Wandlung fertig?
goto ISR_ADC_1 ; nein!
movf ADRESH,w ;
movwf val_wall ;
; A/D-Wandlung starten
bsf ADCON0,GO_DONE ; den ca. 1ms lange gesampleten Kanal jetzt wandeln
; Eing�nge lesen
movf PORTC,w ;
movwf sta_rc ; Port C in Abbildvariable einlesen
ISR_TMR0_1
; Millisekunden-Eieruhr
movf dlycnt,f ; Z-Flag generieren
btfss _Z ;
decf dlycnt,f ; dekr., wenn nicht null (Z=0)
; Millisekunden-Ticker (= virtuelle Unruh)
incf ticker,f ;
; langsamer Ticker (quasi: HighByte)
movf ticker,w ;
btfsc _Z ; = 0, d.h. �berlauf?
incf hitick,f ;
ISR_FLASH
; LED ansteuern
bcf LED ;
btfsc hitick,0 ;
bsf LED ;
ISR_BUMP
movlw LIMDUNK ; eindeutig keine Reflexion
subwf val_wall,w ;
btfss _C ;
bsf BUMPED ; ja !
movlw LIMHELL ; eindeutige Reflexion
subwf val_wall,w ;
btfsc _C ;
bcf BUMPED ; ja!
ISR_STEP
ISR_STEP_1
movf restweg
btfsc _Z ; kein Restweg
goto ISR_STEP_END ; ... daher �berspringen
decfsz slowpe,f ; Schrittfreq. auf 1000Hz/SACHT verlangsamen
goto ISR_STEP_END ; noch nicht null, daher �berspringen
; Schritt ausf�hren
btfsc DIR_FWD ; Unterscheidung der Bewegungsrichtung
; btfss BUMPED ; Unterscheidung der Bewegungsrichtung
incf indexx,f ; anhand der Richtungsflags.
; btfsc BUMPED ; Unterscheidung der Bewegungsrichtung
btfsc DIR_REV ; Auch Stillstand ist m�glich!
decf indexx,f ;
ISR_STEP_2
movlw b'00000111' ; Indizes normieren auf Wertebereich 0..7 (Bits 2..0)
andwf indexx,f ;
clrf buf_rb ; tabula rasa
movlw pattx1 ; Basisadresse (literal, d.h. Speicherstelle) der x-Pattern
addwf indexx,w ; plus Offset
movwf FSR ;
movf INDF,w ; Bitmuster, indirekt adressiert
iorwf buf_rb,f ; Bits in Puffer einpr�gen
ISR_STEP_TAIL
; Nacharbeiten nach einem Schritt
decf restweg,f
movlw SACHT ;
; movf val_wall,f
movwf slowpe ; Verz�g.zeit neu starten
ISR_STEP_END
; Hier sollten alle Pins f�r die aktuelle Runde ermittelt sein, daher ...
;Ausgabe-Puffervariablen an die Ausgangspins des Chips durchreichen
movf buf_rb,w ;
movwf PORTB ; PORTB-bits auf die Ausg�nge
movf buf_rc,w ;
movwf PORTC ; PORTC-bits auf die Ausg�nge
; !!!! AB HIER NICHT MEHR AUF DIE PORTS SCHREIBEN !!!!
ISR_RESTORE
; Kontext wiederherstellen
movf temp_fsr,w ;
movwf FSR ;
movf temp_pclath,w ; retrieve copy of PCLATH register
movwf PCLATH ; restore pre-isr PCLATH register contents
movf temp_status,w ; retrieve copy of STATUS register
movwf STATUS ; restore pre-isr STATUS register contents
swapf temp_w,f ; Kniff, um W zu laden, ohne den Status zu verändern !
swapf temp_w,w ; restore pre-isr W register contents
retfie ; return from interrupt (impliziert ein "bsf INTCON,GIE")
;**********************************************************************
MAIN ; Das Hauptprogramm
;**********************************************************************
; banksel <labelname> ; das ist die MAKRO-Sytax
; pagesel <labelname> ; das ist die MAKRO-Sytax
; pageselw <labelname> ; das ist die MAKRO-Sytax
clrf INTCON ; alle Interruptquellen sperren, alle IRQs verwerfen
clrf PORTA ;
clrf PORTB ;
clrf PORTC ;
; I/O-Leitungen konfigurieren
bsf STATUS,RP0 ; Bank 1
movlw b'11111111' ; 5..1: (noch Analog-)Eing�nge
movwf TRISA ;
movlw b'00000000' ; 7..0: 2x4 Ausg�nge f�r Stepper
movwf TRISB ;
movlw b'01100010' ; 7: Stiftabsenkung out; 6,5: Endschalter in;
movwf TRISC ; 1: Taste in 0: LED out. Rest OUT gegen floatende Inputs
bcf STATUS,RP0 ; Bank 0
; ADC konfigurieren
bsf STATUS,RP0 ; Bank 1
bcf ADCON1,ADFM ; 0= left justified
bsf ADCON1,ADCS2 ; 1= clock select -> 1/64 erm�glichen
bcf ADCON1,PCFG3 ; (1110: nur AN0, ratiometrisch zu Vdd,Vss; Rest digital)
bcf ADCON1,PCFG2 ; (011x: alles dig. I/O)
bcf ADCON1,PCFG1 ; 0000: alles analoge Inputs, ratiometrisch zu Vdd,Vss
bcf ADCON1,PCFG0 ;
bcf STATUS,RP0 ; Bank 0
bsf ADCON0,ADCS1 ; 10bin= clock select -> 1/64 erm�glichen
bcf ADCON0,ADCS0 ;
bsf ADCON0,ADON ; ADC einschalten
; Timer0 konfigurieren
bsf STATUS,RP0 ; Bank 1
clrwdt ; WDT-Register und implizit Prescaler l�schen, das geh�rt sich so!
movlw b'10000001' ; int sys clk, 1:4, prescale assg. to TMR0
movwf OPTION_REG ;
bcf STATUS,RP0 ; Bank 0
movlw d'8' ; Presetwert vgl. Timer0-ISR
movwf TMR0 ;
; Startzust�nde herstellen
clrf indexx
clrf indexy
movlw d'0' ;
movwf ticker ;
movwf hitick ;
movwf buf_rb ;
movwf PORTB ; I/O-Leitungen
movwf buf_rc ;
movwf PORTC ; I/O-Leitungen
movwf flax ; acht Flag-Bits
movlw b'01100010' ; die Einsen sind die low-aktiven Eing�nge (Taster)
movwf sta_rc ;
movlw SACHT ; Teilungsfaktor f_irq --> f_step
movwf slowpe ;
movlw b'00001010' ; Ansteuerpattern x-Achse
movwf pattx1 ; acht Zust�nde wegen Halbschrittbetrieb
movlw b'00000010' ; f� das LOW-Nibble des Portbytes
movwf pattx2 ;
movlw b'00000110' ;
movwf pattx3 ;
movlw b'00000100' ;
movwf pattx4 ;
movlw b'00000101' ;
movwf pattx5 ;
movlw b'00000001' ;
movwf pattx6 ;
movlw b'00001001' ;
movwf pattx7 ;
movlw b'00001000' ;
movwf pattx8 ;
bsf STATUS,RP0 ; Bank 1
clrf PIE1 ;
clrf PIE2 ;
bcf STATUS,RP0 ; Bank 0
clrf PIR1 ;
clrf PIR2 ;
clrf INTCON ; alle Quellen und IRQs disablen/r�cksetzen
; Anlaufsperre via "Reset"-Taste.
; F�r Entwicklungszwecke ab und an recht hilfreich,
; nicht aber f�r die primitive Funktionalit�t des Schlittens im Alltagsbetrieb
KLINKE
; btfsc PORTC,1
; goto KLINKE
; Interrupts enablen bzw. in Gang setzen
bsf INTCON,T0IE ; Timer 0 enable
;bcf INTCON,T0IE ; Timer 0 disable
bsf INTCON,PEIE ; Gruppe der Peripherals
bsf INTCON,GIE ; globales Enable
; das "eigentliche Hauptprogramm"
;Referenzpunkt (Endschalter) anfahren
; pagesel REFERENZ
; call REFERENZ
; und hier endlich die Hauptprogrammschleife
LOOOP ; die Schleife �ber alles
pagesel FAHRPROG
call FAHRPROG
pagesel LOOOP ;
goto LOOOP ;
;**********************************************************************
P0_IDLE
; Prinzip: "Jeder Code Page ihre eigene Bummelfunktion"
; wartet stur, bis die ISR den Z�hler dlycnt bis Null heruntergez�hlt hat
movwf dlycnt ; Delayzeit wird im W-Register geliefert
P0_IDLE_1
movf dlycnt,f ; zero flag generieren
btfss _Z ; bei Z=1 ausbrechen
goto P0_IDLE_1 ;
return ;
;**********************************************************************
FAHRPROG
; Hinweg
bcf DIR_REV
bsf DIR_FWD
movlw d'240'
movwf restweg
FAHRPROG_1
movf restweg
btfss _Z
goto FAHRPROG_1 ; so lange noch Restweg vorhanden ist
movlw d'240'
movwf restweg
FAHRPROG_2
movf restweg
btfss _Z
goto FAHRPROG_2 ; so lange noch Restweg vorhanden ist
; R�ckweg
bcf DIR_FWD
bsf DIR_REV
movlw d'240'
movwf restweg
FAHRPROG_3
movf restweg
btfss _Z
goto FAHRPROG_3 ; so lange noch Restweg vorhanden ist
movlw d'240'
movwf restweg
FAHRPROG_4
movf restweg
btfss _Z
goto FAHRPROG_4 ; so lange noch Restweg vorhanden ist
return
;**********************************************************************
;**********************************************************************
ORG 0x0800 ; Begin of 2k-Code Page #1 (2nd)
;**********************************************************************
;**********************************************************************
P1_IDLE
; Prinzip: "Jeder Code Page ihre eigene Bummelfunktion"
; wartet stur, bis die ISR den Z�hler dlycnt bis Null heruntergez�hlt hat
movwf dlycnt ; Delayzeit wird im W-Register geliefert
P1_IDLE_1
movf dlycnt,f ; zero flag generieren
btfss _Z ; bei Z=1 ausbrechen
goto P1_IDLE_1 ;
return ;
;**********************************************************************
;**********************************************************************
ORG 0x1000 ; Begin of 2k-Code Page #2 (3rd)
;**********************************************************************
;**********************************************************************
P2_IDLE
; Prinzip: "Jeder Code Page ihre eigene Bummelfunktion"
; wartet stur, bis die ISR den Z�hler dlycnt bis Null heruntergez�hlt hat
movwf dlycnt ; Delayzeit wird im W-Register geliefert
P2_IDLE_1
movf dlycnt,f ; zero flag generieren
btfss _Z ; bei Z=1 ausbrechen
goto P2_IDLE_1 ;
return ;
;**********************************************************************
;**********************************************************************
ORG 0x1800 ; Begin of 2k-Code Page #3 (4th)
;**********************************************************************
;**********************************************************************
P3_IDLE
; Prinzip: "Jeder Code Page ihre eigene Bummelfunktion"
; wartet stur, bis die ISR den Zhler dlycnt bis Null heruntergezhlt hat
movwf dlycnt ; Delayzeit wird im W-Register geliefert
P3_IDLE_1
movf dlycnt,f ; zero flag generieren
btfss _Z ; bei Z=1 ausbrechen
goto P3_IDLE_1 ;
return ;
;**********************************************************************
;**********************************************************************
END ; directive 'end of program'
;**********************************************************************
;**********************************************************************
Christian.