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'
;**********************************************************************
;**********************************************************************
Gruß
Lesezeichen