Forum: Mikrocontroller und Digitale Elektronik Interrupts SAVING STATUS AND W REGISTERS IN RAM


von Messuung (Gast)


Lesenswert?

Hallo

habe problem mit Interrups smirt immer wider ab.
Kann einer sagen warum

Interrupt:

bcf  INTCON,GIE
movwf  w_sichern
swapf  STATUS,W
movwf  s_sichern

    call    Ledhp

movf  teimer,0
movwf  TMR0
bcf  INTCON,T0IF
swapf  s_sichern,W
movwf  STATUS
swapf   w_sichern,F
swapf  w_sichern,W
bsf    INTCON,GIE

retfie





INIT:

bsf    INTCON,GIE
bsf    INTCON,T0IE


bsf    STATUS,RP0

movlw  b'00000111'
movwf  OPTION_REG

bcf    STATUS,RP0

von Bernd R. (Firma: Promaxx.net) (bigwumpus)


Lesenswert?

Ich tippe mal auf einen PIC als Prozessor, ist hilfreich für die anderen 
interessierten Helfer.

Das löschen und setzen des GIE-Flags innerhalb der INT-Routine ist 
komplett sinnlos, weil innerhalb der INT-Routine gar keine INTs 
zugelassen sind.

Was in Ledhp passiert, können wir nicht bewerten, ich befürchte 
schlimmes!

Anfang und Ende der INT-Routine sollte man nochmal mit dem Datenblatt 
vergleichen, mir fehlt evtl. PCLATH...

von Ottmar K. (wil1)


Lesenswert?

Hallo Messung,

Probiere es mal so:
ISR
  bcf   INTCON, GIE  ; Global Interrupt Enabled AUS (wenn Du möchtes)
  movwf  tmp_W    ; WREG sichern
  swapf  STATUS,W  ; Status ins WREG HI-LO.Nibble vertauschen
  BANK0      ; macro zu Bank0 ohne Rücksicht auf akt. Bank
  movwf  tmp_STATUS  ; STATUS on bcf    STATUS, RP0 sichern
  bcf   INTCON, T0IF  ; Bit2=0 TMR0 "ist übergelaufen" zurücksetzen
        CALL......              ; Bank 0? 1, 2, 3 oder????

woher willst Du wissen in welcher Bank der Programmlauf gerade war, als 
der Interrupt eingetreten ist?

Vielleicht postest Du mal den Code - Hellsehen funktioniert nicht so 
richtig.
mfg Ottmar

von Messuung (Gast)


Lesenswert?

ok
ist nur ein teil wo auch der ferhalten auftrit der rest habe ich weg
;*********************************************************************** 
***********************
;** Demonstration zur Ansteuerung eines alphanumerischen LC-Display **
;** **
;** Pinbelegung: Port A: unbenutzt **
;** Port B: RB0: unbenutzt (Reserviert für Hintergrundbeleuchtung) **
;** RB1: RS **
;** RB2: R/W **
;** RB3: E **
;** RB4: D4 **
;** RB5: D5 **
;** RB6: D6 **
;** RB7: D7 **
;** Anmerkung: Die Bits sollten nach Möglichkeit nicht verändert werden, 
es kann jedoch **
;** ein anderer Port gewählt werden. **
;** **
;** Entwickler: Buchgeher Stefan **
;** Entwicklungsbeginn der Software: 21. Juli 2002 **
;** Funktionsfähig seit: 21. Juli 2002 **
;** Letzte Bearbeitung: 26. Februar 2004 **
;*********************************************************************** 
***********************
;---------- Includedateien ------------------------------

;---------- Includedateien ------------------------------
  LIST  P=16F84A        ; Verwendeter PIC= PIC16F84a
  include <P16f84A.INC>      ; Includefile for P16F84A

;**********************************************************************
;---------- Konfiguration ------------------------------
; bis 4 MHz: Power on Timer, no Watchdog, XT-Oscillator
;  __CONFIG  _CP_OFF & _PWRTE_ON & _WDT_OFF & _XT_OSC

;******************************** Register (in Registerseite 0) 
*******************************
;STAT equ 3 ;Statusregister
;PORTB equ 6 ;PortB-Register
;******************************** Register (in Registerseite 1) 
*******************************
;TRISB equ 6 ;Richtungsregister PortB
;******************************** Eigene Register (in Registerbank 0) 
*************************
TEMP1 equ 20 ;allgemeines Hilfsregister 1
TEMP2 equ 21 ;allgemeines Hilfsregister 2
;******************************** Bits in Registern der Registerbank 1 
************************
RP0 equ 5 ;Seitenauswahlbit im Statuswort-Registe
;**********************************************************************
;---------- Definitionen ------------------------------
; Hier werden einzelne Bits eine Ports oder ganze Ports als fester 
Ausdruck definiert.
#define      EINFAHRT  PORTA,2  ; PORTA Bit 2 wird als Einfahrt 
definiert
#define      AUSFAHRT  PORTA,1  ; PORTA Bit 1 wird als Ausfahrt 
definiert
#define      LED      PORTA,0  ; PORTA Bit 0 wird als LED definiert

;******************************** Portbelegung 
************************************************
;Port B
LCD_DATA     equ PORTB
LCD_DATA_TRIS   equ TRISB
LCD_CTRL     equ PORTB
LCD_CTRL_TRIS   equ TRISB
LCD_LED     equ 0
LCD_RS       equ 1
LCD_RW       equ 2
LCD_E       equ 3
eins       equ 0x40
zähn       equ 0x41
stunden      equ 0x42
stunde      equ 0x43
minuten      equ 0x44
minute      equ 0x45
sekunde      equ 0x46
sekunden    equ 0x47
max        equ 0x48
maxe      equ 0x49
W_TEMP      equ  0x50    ; Speicherzelle
S_TEMP    equ  0x51    ; Speicherzelle
teimer       equ 0x52
max2      equ 0x53
max3      equ 0x54
;******************************** Ziele der Registeroperationen 
*******************************
w equ 0
f equ 1
;******************************** Konfigurations-Bits 
*****************************************
_lp_osc equ h'3FFC'
_xt_osc equ h'3FFD'
_hs_osc equ h'3FFE'
_rc_osc equ h'3FFF'
_wdt_off equ h'3FFB'
_wdt_on equ h'3FFF'
_pwrt_off equ h'3FFF'
_pwrt_on equ h'3FF7'
_cp_off equ h'3FFF'
_cp_on equ h'000F'
__config _hs_osc & _wdt_off & _pwrt_off & _cp_off
ORG 0x000
goto BEGINN
ORG 0x004
;goto  ISR
;******************************** ISR 
*********************************************************
;==================================================
;Interruptroutine (ISR - Interrupt Service Routine)
;==================================================
  ORG   0x04           ; Hier beginnt die ISR




    SWAPF W_TEMP,F         ;Swap W_TEMP
    SWAPF STATUS,W   ;Swap status to be saved in
    MOVWF S_TEMP ;Save status to bank zero STATUS_TEMP register


  call ZEIT
  bcf    INTCON,T0IF      ; INTF Flag wieder löschen


    SWAPF S_TEMP,W         ;Swap STATUS_TEMP register into W
    MOVWF STATUS         ;Move W into STATUS register
    SWAPF W_TEMP,F         ;Swap W_TEMP
    SWAPF W_TEMP,W         ;Swap W_TEMP into W



  retfie

;******************************** Unterprogramme 
**********************************************
;*********************************************************************** 
***********************
;** Initialisierung des Prozessor: **
;** + Ports: Port A: (unbenutzt) **
;** Port B: Ausgänge **
;*********************************************************************** 
***********************
INIT:
  bsf      STATUS, RP0        ; Setze in Register STATUS das Bit RP0 auf 
1
  movlw  B'00001111'        ; Speicher B'00011110' in das 
Arbeitsregister W
  movwf  TRISA          ; Kopiere Inhalt von W in das Register TRISA
  movlw  B'00000001'        ; Speicher B'00000000' in das 
Arbeitsregister W
  movwf  TRISB          ; Kopiere Inhalt von W in das Register TRISB
  bcf     STATUS, RP0



  bsf    INTCON,GIE
  bsf    INTCON,T0IE


  bsf    STATUS,RP0        ; umschalten auf Bank1

  movlw  b'00000111'        ; Speicher d'07' in das Arbeitsregister W
  movwf  OPTION_REG      ; Kopiere Inhalt von W in OPTION_REG

  bcf    STATUS,RP0


  movlw  d'1'        ; Speicher B'00011110' in das Arbeitsregister W
  movwf  max
  movwf  max2

  movlw  d'0'        ; Speicher B'00011110' in das Arbeitsregister W
  movwf  sekunden
  movlw  d'0'        ; Speicher B'00011110' in das Arbeitsregister W
  movwf  sekunde



  return

;*********************************************************************** 
************************
;vor gefertigte zahlen für alles
;die zahl wir nach unten gezählt und in arbeit register gespeichert und 
ausgegeben
;man kann auch das für 7segment-anzeige muss dur angepast
;*********************************************************************** 
************************

DEZZAHLEN:
    addwf  PCL, F
    retlw  '0'  ; Ziffer 0
    retlw  '1'  ; Ziffer 1
    retlw  '2'  ; Ziffer 2
    retlw  '3'  ; Ziffer 3
    retlw  '4'  ; Ziffer 4
    retlw  '5'  ; Ziffer 5
    retlw  '6'  ; Ziffer 6
    retlw  '7'  ; Ziffer 7
    retlw  '8'  ; Ziffer 8
    retlw  '9'  ; Ziffer 9

;*********************************************************************** 
***********************
;** LCDINIT **
;** **
;** Aufgabe: **
;** Dieses Unterprogramm initialisiert das LC-Displays **
;** **
;** Vorgehensweise: **
;** + Die Steuerleitungen des LC-Displays (E, RS, R/W) auf Low legen **
;** + 15 ms warten **
;** + Befehl: 8-bit-Interface an LCD **
;** + 4,1 ms warten **
;** + Wiederholung des Befehls: 8-bit-Interface an LCD **
;** + 0,1 ms warten **
;** + Wiederholung des Befehls: 8-bit-Interface an LCD **
;** + Warten, bis LCD für weitere Anweisungen bereit ist **
;** + Befehl: 4-bit-Interface an LCD **
;** Achtung: ab nun müssen Befehle an das LCD mit dem Unterprogramm 
LCDBEFEHL erfolgen **
;** + Befehl: Display löschen und Cursor home **
;** + Befehl: 4 Bit, 2 Zeilen, 5x7 **
;** + Befehl: Display aus, Cursor aus, Blinken aus **
;** + Befehl: Shift aus **
;** + Befehl: Display ein **
;*********************************************************************** 
***********************
LCDINIT:
    bcf   LCD_CTRL,LCD_E ;Alle Control-Lines = Low
    bcf   LCD_CTRL,LCD_RS
    bcf   LCD_CTRL,LCD_RW
    movlw   .150 ;15 ms warten
    call   VERZ100US
    movlw   0x0F
    andwf   LCD_DATA,f ;Höherw. Nibble löschen
    movlw   0x30 ;Befehl für 8-Bit-Interface
    iorwf   LCD_DATA,f ;Befehl an LCD
    bsf   LCD_CTRL,LCD_E ; (durch toggeln der LCD-Enable-Leitung)
    bcf   LCD_CTRL,LCD_E

    movlw   .41 ;4.1 ms warten
    call   VERZ100US
    bsf   LCD_CTRL,LCD_E ;Befehl (8-bit-Interface) wiederholen
    bcf   LCD_CTRL,LCD_E ; (durch toggeln der LCD-Enable-Leitung)
    movlw   .1 ;100us warten
    call   VERZ100US
    bsf   LCD_CTRL,LCD_E ;Befehl (8-bit-Interface) wiederholen
    bcf   LCD_CTRL,LCD_E ; (durch toggeln der LCD-Enable-Leitung)
    call   LCDBUSY ;Warten bis LCD bereit
    movlw   0x0F
    andwf   LCD_DATA,f ;Höherw. Nibble löschen
    movlw   0x20 ;Befehl für 4-Bit Interface
    iorwf   LCD_DATA,f ;Befehl an LCD
    bsf   LCD_CTRL,LCD_E ; (durch toggeln der LCD-Enable-Leitung)
    bcf   LCD_CTRL,LCD_E
    movlw   0x01 ;Display löschen und Cursor home
    call   LCDBEFEHL ;Befehl an LCD
    movlw   0x28 ;4 Bit, 2 Zeilen, 5x7
    call   LCDBEFEHL ;Befehl an LCD
    movlw   0x08 ;Display aus, Cursor aus, Blinken aus
    call   LCDBEFEHL ;Befehl an LCD
    movlw   0x06 ;Shift aus
    call   LCDBEFEHL ;Befehl an LCD
    movlw   0x0C ;Display ein
    call   LCDBEFEHL ;Befehl an LCD






    return
;*********************************************************************** 
***********************
;** LCDBEFEHL **
;** **
;** Aufgabe: **
;** Dieses Unterprogramm sendet einen Befehl nibbleweise an das 
LC-Display. **
;** **
;** Vorgehensweise: **
;** + Der Befehl, welcher an das LC-Display übertragen wird, befindet 
sich als 8-Bit- **
;** Wert im Arbeitsregister (w-Register). Diesen zunächst im temporären 
Register **
;** TEMP1 zwischenspeichern **
;** + Warten bis das LC-Display für eine Befehl bereit ist. (Dazu ist 
das Unterprogramm **
;** LCDBUSY zuständig) **
;** + für die Kommunikation mit dem LC-Display steht "nur" ein 
4-Bit-Datenbus zur Ver- **
;** fügung. Der 8-bit-Befehl wird daher nibbleweise an das LC-Display 
übertragen. **
;** Zuerst wird das höherwertigere Nibble auf den 4-Bit-Datenbus gelegt. 
Dabei **
;** dürfen nur die für den Datenbus definierten Leitungen verändert 
werden. Die **
;** restlichen vier Portpins dürfen nicht verändert werden. **
;** + Read-Write-Steuerleitung löschen, da es sich hier um eine 
Schreibanweisung **
;** handelt. **
;** + Register-Select-Steuerleitung löschen, da es sich hier um einen 
Befehl handelt. **
;** + Eine fallende Flanke auf der Enable-Steuerleitung durch Toggeln 
erzeugen. (Das LC- **
;** Display liest nun das höherwertigere Befehlsnibble ein) **
;** + Nun das niederwertigere Befehlsnibble auf den 4-Bit-Datenbus 
legen. Auch hier **
;** dürfen nur die für den Datenbus definierten Leitungen verändert 
werden. Die **
;** restlichen vier Portpins dürfen nicht verändert werden. **
;** + Eine fallende Flanke auf der Enable-Steuerleitung durch Toggeln 
erzeugen. (Das LC- **
;** Display liest nun das niederwertigere Befehlsnibble ein) **
;** **
;** Anmerkungen: **
;** + Dieses Unterprogramm unterscheidet sich zum Unterprogramm 
LCDZEICHEN nur dadurch, **
;** dass hier die Register-Select-Steuerleitung gelöscht ist, da mit 
diesem Unter- **
;** programm Befehle an das LC-Display übertragen werden. **
;** + Das temporäre Register TEMP1 dient hier nur als Hilfsregister. Es 
wird hier nur **
;** kurzzeitig verwendet und kann daher auch in anderen Unterprogrammen 
verwendet **
;** werden. **
;*********************************************************************** 
***********************
LCDBEFEHL:
    movwf   TEMP1 ;Auszugebendes Zeichen (befindet sich im w-; Register) 
in TEMP1 zwischenspeichern
    call   LCDBUSY ;Warten bis LCD bereit ist
    movlw   0x0F
    andwf  LCD_DATA,f ;Höherwertiges Nibble löschen
    movf   TEMP1,w
    andlw   0xF0 ;Höherwertiges Nibble ausmaskieren
    iorwf  LCD_DATA,f ;High-Nibble an LCD übergeben
    bcf    LCD_CTRL,LCD_RW ;LCD im Schreiben-Mode
    bcf   LCD_CTRL,LCD_RS ;LCD im Befehl-Mode
    bsf   LCD_CTRL,LCD_E ;Enable (LCD)
    bcf   LCD_CTRL,LCD_E ; toggeln
    movlw   0x0F
    andwf   LCD_DATA,f ;Höherwertiges Nibble löschen
    swapf   TEMP1,w
    andlw   0xF0 ;Niederwert. Nibble ausmaskieren
    iorwf   LCD_DATA,f ;Low-Nibble an LCD übergeben
    bsf   LCD_CTRL,LCD_E ;Enable (LCD)
    bcf   LCD_CTRL,LCD_E ; toggeln
    bsf   LCD_CTRL,LCD_LED ;Enable (LCD)

    return
;*********************************************************************** 
***********************
;** LCDZEICHEN **
;** **
;** Aufgabe: **
;** Diese Unterprogramm sendet ein Zeichen, welches am LC-Display 
ausgegeben wird, **
;** nibbleweise an das LC-Display. **
;** **
;** Vorgehensweise: **
;** + Das Zeichen, welches am LC-Display ausgegeben werden soll, 
befindet sich als 8-Bit- **
;** Wert im Arbeitsregister (w-Register). Diesen Wert zunächst im 
temporären **
;** Register TEMP1 zwischenspeichern **
;** + Warten bis das LC-Display für ein Zeichen bereit ist. (Dazu ist 
das Unterprogramm **
;** LCDBUSY zuständig) **
;** + für die Kommunikation mit dem LC-Display steht "nur" ein 
4-bit-Datenbus zur ver- **
;** fügung. Der 8-bit-Wert wird daher nibbleweise an das LC-Display 
übertragen. **
;** Zuerst wird das höherwertigere Nibble auf den 4-Bit-Datenbus gelegt. 
Dabei **
;** dürfen nur die für den Datenbus definierten Leitungen verändert 
werden. Die **
;** restlichen vier Portpins dürfen nicht verändert werden. **
;** + Read-Write-Steuerleitung löschen, da es sich hier um eine 
Schreibanweisung **
;** handelt. **
;** + Register-Select-Steuerleitung setzen, da es sich hier um eine 
Zeichen handelt, **
;** welches am LC-Display ausgegeben werden soll. **
;** + Eine fallende Flanke auf der Enable-Steuerleitung durch Toggeln 
erzeugen. (Das LC- **
;** Display liest nun das höherwertigere Zeichennibble ein) **
;** + Nun das niederwertigere Zeichennibble auf den 4-Bit-Datenbus 
legen. Auch hier **
;** dürfen nur die für den Datenbus definierten Leitungen verändert 
werden. Die **
;** restlichen vier Portpins dürfen nicht verändert werden. **
;** + Eine fallende Flanke auf der Enable-Steuerleitung durch Toggeln 
erzeugen. (Das LC- **
;** Display liest nun das niederwertigere Zeichennibble ein). **
;** **
;** Anmerkung: **
;** + Dieses Unterprogramm unterscheidet sich zum Unterprogramm 
LCDBEFEHL nur dadurch, **
;** dass hier die Register-Select-Steuerleitung gesetzt ist, da mit 
diesem Unter- **
;** programm am LC-Display auszugebende Zeichen an das LC-Display 
übertragen werden. **
;** + Das temporäre Register TEMP1 dient hier nur als Hilfsregister. Es 
wird hier nur **
;** kurzzeitig verwendet und kann daher auch in anderen Unterprogrammen 
verwendet **
;** werden. **
;*********************************************************************** 
***********************
LCDZEICHEN:
    movwf  TEMP1 ;Auszugebendes Zeichen (befindet sich im;w-Register) in 
TEMP1 zwischenspeichern
    call   LCDBUSY ;Warten bis LCD bereit ist
    movlw   0x0F
    andwf   LCD_DATA,f ;Höherwertiges Nibble löschen
    movf   TEMP1,w
    andlw   0xF1 ;Höherwertiges Nibble ausmaskieren
    iorwf   LCD_DATA,f ;High-Nibble an LCD übergeben
    bcf   LCD_CTRL,LCD_RW ;LCD im Schreiben-Mode
    bsf   LCD_CTRL,LCD_RS ;LCD im Daten-Mode
    bsf   LCD_CTRL,LCD_E ;Enable (LCD)
    bcf   LCD_CTRL,LCD_E ; toggeln
    movlw   0x0F
    andwf   LCD_DATA,f ;Höherwertiges Nibble löschen
    swapf   TEMP1,w
    andlw   0xF1 ;Niederwert. Nibble ausmaskieren
    iorwf   LCD_DATA,f ;Low-Nibble an LCD übergeben
    bsf   LCD_CTRL,LCD_E ;Enable (LCD)
    bcf   LCD_CTRL,LCD_E ; toggeln

    return
;*********************************************************************** 
***********************
;** LCDBUSY **
;** **
;** Aufgabe: **
;** Diese Unterprogramm prüft das Busy-Flag des LC-Display, und verlässt 
es erst wenn **
;** das Busy-Flag low ist, also wenn das LC-Display bereit für eine 
Befehl oder für **
;** ein auszugebendes Zeichen ist. **
;** **
;** Vorgehensweise: **
;** + Der Datenport muss als Eingang definiert werden, da nun der 
Zustand (insbesondere **
;** der Zustand das Busy-Flag) des LC-Display gelesen wird. Dazu muss 
aber in die **
;** Registerbank 1 des PIC gewechselt werden und anschließend wieder 
zurück zur **
;** Registerbank 0. **
;** + Register-Select-Steuerleitung löschen, da es sich hier um einen 
Befehl handelt. **
;** + Read-Write-Steuerleitung setzen, da es sich hier um eine 
Leseanweisung handelt. **
;** + Eine fallende Flanke auf der Enable-Steuerleitung durch Toggeln 
erzeugen. (Das LC- **
;** Display gibt nun das höherwertigere Nibble auf den 4-Bit-Datenbus.) 
**
;** + Den 4-Bit-Wert vom Datenbus einlesen und im Hilfsregister TEMP2 
sichern. **
;** + Eine weiter fallende Flanke auf der Enable-Steuerleitung durch 
Toggeln er- **
;** zeugen. (Das LC-Display gibt nun das niederwertigere Nibble auf den 
4-Bit-Datenbus) **
;** + Den 4-Bit-Wert vom Datenbus einlesen und mit dem Hilfsregister 
TEMP2 zu einem 8- **
;** Bit-Wert verschmelzen. **
;** + Das Busy-Flag (Bit 7 von TEMP2) überprüfen. Ist dieses Flag 
gesetzt, die soeben **
;** durchgeführten Schritte so oft wiederholen bis das LC-Display das 
Busy-Flag **
;** löscht. **
;** + Ist das Busy-Flag low, (also gelöscht) die 
Read-Write-Steuerleitung wieder **
;** zurücksetzen und den Datenport wieder als Ausgang definieren. Dazu 
muss aber **
;** wieder in die Registerbank 1 des PIC gewechselt werden und 
anschließend wieder **
;** zurück zur Registerbank 0. **
;** **
;** Anmerkung: **
;** Das temporäre Register TEMP2 dient hier nur als Hilfsregister. Es 
wird hier nur **
;** kurzzeitig verwendet und kann daher auch in anderen Unterprogrammen 
verwendet werden **
;*********************************************************************** 
***********************
LCDBUSY:
    bsf   STATUS,RP0 ;Registerbank 1
    movlw   0xF0 ;Höherwertigen HalbPort
    iorwf   LCD_DATA_TRIS,w ; als Eingang definieren
    movwf   LCD_DATA_TRIS
    bcf   STATUS,RP0 ;Registerbank 0
    bcf   LCD_CTRL,LCD_RS ;LCD im Befehls-Mode
    bsf   LCD_CTRL,LCD_RW ;LCD im Lesen-Mode
    bsf   LCD_CTRL,LCD_E ;Enable (LCD)
    bcf   LCD_CTRL,LCD_E ; toggeln
    movf   LCD_DATA,w
    andlw   0xF0 ;Niederw.Nibble ausmaskieren
    movwf   TEMP2
    bsf   LCD_CTRL,LCD_E ;Enable (LCD)
    bcf   LCD_CTRL,LCD_E ; toggeln
    swapf   LCD_DATA,w ;Niederwertiges Nibble Busy-Flag
    andlw   0x0F ;Höherwertiges Nibble ausmaskieren
    iorwf   TEMP2,w ;Nibbles verbinden
    btfsc   TEMP2,7 ;Busy-Flag prüfen (High=busy)
    goto   LCDBUSY ;Dieses UP so oft abarbeiten, bis das Busy-Flag; low 
ist
    bcf   LCD_CTRL,LCD_RW ;Busy = low: LCD im Schreiben-Mode
    bsf   STATUS,RP0 ;Registerbank 1
    movlw   0x0F ;Höherwertigen HalbPort
    andwf   LCD_DATA,w ; als Ausgang definieren
    movwf   LCD_DATA_TRIS
    bcf   STATUS,RP0 ;Registerbank 0

    return
;*********************************************************************** 
***********************
;** Warteschleifen **
;** **
;** Aufgabe: **
;** Dieses Unterprogramm erzeugt eine Zeitverzögerung. Der 
Übergabeparameter (im w- **
;** Register) gibt dabei an, wie oft eine Zeitverzögerung von 100us 
erfolgen soll. Der **
;** mögliche Zeitverzögerungsbereich liegt hier daher im Bereich von 
100us und 25,5ms **
;** (=255 x 100us). **
;** **
;** Anmerkungen: **
;** + Die temporären Register TEMP1 und TEMP2 dienen hier nur als 
Übergabe- bzw. als **
;** Hilfsregister. Diese Register werden hier nur kurzzeitig verwendet 
und können **
;** daher auch in anderen Unterprogrammen verwendet werden. **
;** + Das Hilfsregister TEMP2 muss je nach verwendetem Takt mit 
unterschiedlichen Werten **
;** geladen werden: **
;** Takt Wert von TEMP2 **
;** --------------------------------
;** 12 MHz 75 **
;** 20 MHz 125 **
;*********************************************************************** 
***********************
VERZ100US:
    movwf   TEMP1 ;Übergabeparameter in TEMP1 sichern

VERZSCHL1:
    movlw   .25 ;Bei Verwendung eines 4-MHz-Taktes
    ;movlw   .75 ;Bei Verwendung eines 12-MHz-Taktes
    ;movlw   .125 ;Bei Verwendung eines 20-MHz-Taktes
    movwf   TEMP2
VERZSCHL2:
     nop
    decfsz   TEMP2,f
    goto   VERZSCHL2
    decfsz   TEMP1,f
    goto   VERZSCHL1

    return
;3*********************************************************************
;hier wirdes gezeigt
;wird aus Biner ind Dezi umgewandelt

DEZIMAL:


  movwf   eins    ;
  clrf  zähn

UMWANDELN:
   movlw  d'10'
  subwf  eins,f      ; subtrahiere zahlenwert - 10
  incf  zähn,f      ; zehner +1
  btfsc  STATUS,0    ; Carryabfrage
  goto  UMWANDELN
  decf  zähn,f
  movlw  d'10'
  addwf  eins,w      ; addiere die Einer in Zahlenwert
  movwf   eins
  Return
;*********************************************************************** 
***********************
;** AUSGABE **
;** **
;** Aufgabe: **
;** Dieses Unterprogramm gibt in der ersten Zeile den Text "Hallo..." 
und in der zweiten **
;** Zeile den Text "...wie geht's" am LC-Display aus. **
;** **
;** Vorgehensweise: **
;** + Display löschen (dabei wird auch gleichzeitig der Cursor auf die 
erste Stelle am **
;** LC-Display gesetzt) **
;** + Den Text der ersten Zeile Zeichen für Zeichen mit dem 
Unterprogramm LCDZEICHEN am **
;** LC-Display ausgeben. **
;** + Den Cursor auf die zweite Zeile setzen. Dies erfolgt mit dem 
Befehl 'C0' **
;** + Den Text der zweiten Zeile Zeichen für Zeichen mit dem 
Unterprogramm LCDZEICHEN **
;** am LC-Display ausgeben. **
;*********************************************************************** 
***********************
AUSGABE

    movlw     0x01 ;Display löschen
    call     LCDBEFEHL
    movlw    'N'
    call     LCDZEICHEN
    movlw     'a'
    call     LCDZEICHEN
    movlw     't'
    call     LCDZEICHEN
    movlw     'a'
    call     LCDZEICHEN
    movlw     's'
    call     LCDZEICHEN
    movlw     'c'
    call     LCDZEICHEN
    movlw     'h'
    call     LCDZEICHEN
    movlw     'a'
    call     LCDZEICHEN
    movlw     20
    call     LCDZEICHEN
    movlw     '+'
    call     LCDZEICHEN
    movlw     20
    call     LCDZEICHEN
    movlw     'A'
    call     LCDZEICHEN
    movlw     'l'
    call     LCDZEICHEN
    movlw     'e'
    call     LCDZEICHEN
    movlw     'x'
    call     LCDZEICHEN
    movlw     '!'
    call     LCDZEICHEN

    movlw     0xC0 ;2.Zeile
    call     LCDBEFEHL
    movlw     'L'
    call     LCDZEICHEN
    movlw     'i'
    call     LCDZEICHEN
    movlw     'e'
    call     LCDZEICHEN
    movlw     'b'
    call     LCDZEICHEN
    movlw     'e'
    call     LCDZEICHEN
    movlw     b'00010000'
    call     LCDZEICHEN
    movlw     20 ;Leerzeichen
    call     LCDZEICHEN
    movlw     'd'
    call     LCDZEICHEN
    movlw     'i'
    call     LCDZEICHEN
    movlw     'c'
    call     LCDZEICHEN
    movlw     'h'
    call     LCDZEICHEN
    movlw     '!'
    call     LCDZEICHEN
    movlw     ':'
    call     LCDZEICHEN
    movlw     '.'
    call     LCDZEICHEN
    movlw     ')'
    call     LCDZEICHEN
    movlw     '!'
    call     LCDZEICHEN

    return

;*********************************************************************** 
***********************
;** AUSGABE **
;** **
;** Aufgabe: **
;** Dieses Unterprogramm gibt in der ersten Zeile den Text "Hallo..." 
und in der zweiten **
;** Zeile den Text "...wie geht's" am LC-Display aus. **
;** **
;** Vorgehensweise: **
;** + Display löschen (dabei wird auch gleichzeitig der Cursor auf die 
erste Stelle am **
;** LC-Display gesetzt) **
;** + Den Text der ersten Zeile Zeichen für Zeichen mit dem 
Unterprogramm LCDZEICHEN am **
;** LC-Display ausgeben. **
;** + Den Cursor auf die zweite Zeile setzen. Dies erfolgt mit dem 
Befehl 'C0' **
;** + Den Text der zweiten Zeile Zeichen für Zeichen mit dem 
Unterprogramm LCDZEICHEN **
;** am LC-Display ausgeben. **
;*********************************************************************** 
***********************
AUSGABE2

  movlw 0x01 ;Display löschen
  call LCDBEFEHL
  movlw 'U'
  call LCDZEICHEN
  movlw 'h'
  call LCDZEICHEN
  movlw 'r'
  call LCDZEICHEN

  movlw 0xC0 ;2.Zeile
  call LCDBEFEHL
  movlw 20
  call LCDZEICHEN
  movlw 20
  call LCDZEICHEN
  movlw 20
  call LCDZEICHEN
  movlw 20
  call LCDZEICHEN

  movf stunden,w
  call DEZZAHLEN
  call LCDZEICHEN

  movf stunde,w
  call DEZZAHLEN
  call LCDZEICHEN

  movlw ':'
  call LCDZEICHEN

  movf minuten,w
  call DEZZAHLEN
  call LCDZEICHEN

  movf minute,w
  call DEZZAHLEN
  call LCDZEICHEN

  return

;******************************** Hauptprogramm 
***********************************************
;*********************************************************************** 
***********************
;** Aufgaben des Hauptprogramms: **
;** + Controller initialisieren (Unterprogramm INIT) **
;** + LCD initialisieren (Unterprogramm LCDINIT) **
;** + In einer Endlosschleife ununterbrochen einen beliebigen Text am 
LC-Display ausgeben **
;** und 15ms warten **
;*********************************************************************** 
***********************
BEGINN
  call   INIT ;Controller initialisieren
  call  LCDINIT ;Display initialisieren


SCHLEIFER:
  call  UHR
  movlw   .150 ; und anschließend 15ms warten
  call   VERZ100US
  movlw   .250 ; und anschließend 15ms warten
  call   VERZ100US
  movlw   .250 ; und anschließend 15ms warten
  call   VERZ100US
  movlw   .250 ; und anschließend 15ms warten
  call   VERZ100US
  movlw   .250 ; und anschließend 15ms warten
  call   VERZ100US
  movlw   .250 ; und anschließend 15ms warten
  call   VERZ100US
  movlw   .250 ; und anschließend 15ms warten
  call   VERZ100US
  movlw   .250 ; und anschließend 15ms warten
  call   VERZ100US
  movlw   .250 ; und anschließend 15ms warten
  call   VERZ100US
  movlw   .250 ; und anschließend 15ms warten
  call   VERZ100US
  movlw   .250 ; und anschließend 15ms warten
  call   VERZ100US
  movlw   .250 ; und anschließend 15ms warten
  call   VERZ100US
  movlw   .250 ; und anschließend 15ms warten
  call   VERZ100US
  movlw   .250 ; und anschließend 15ms warten
  call   VERZ100US
  movlw   .250 ; und anschließend 15ms warten
  call   VERZ100US
  movlw   .250 ; und anschließend 15ms warten
  call   VERZ100US
  btfsc  EINFAHRT  ; wenn EINFAHRT (PORTA,2) =0 nächsten Befehl 
überspringen
  call  Ich      ; rufe Entprellenein auf


  btfsc  AUSFAHRT  ; wenn AUSFAHRT (PORTA,1) =0 nächsten Befehl 
überspringen
  call  UHR      ; rufe Entprellenaus auf


  movlw   .150 ; und anschließend 15ms warten
  call   VERZ100US
  goto SCHLEIFER


UHR:
  btfsc  AUSFAHRT  ; wenn AUSFAHRT (PORTA,1) =0 nächsten Befehl 
überspringen
  goto  UHR

  movlw  d'60'
  subwf  sekunde,1      ; subtrahiere zahlenwert - 10
;  incf  sekunden,1      ; zehner +1
  btfsc  STATUS,0    ; Carryabfrage
  goto  UHR
;  decf  sekunden,1
  movlw  d'60'
  addwf  sekunde,1      ; addiere die Einer in Zahlenwert

  movlw  d'24'
  subwf  sekunden,1      ; subtrahiere zahlenwert - 10
  btfsc  STATUS,0    ; Carryabfrage
  goto  HR
  movlw  d'24'
  addwf  sekunden,1
HR


    movf    sekunde,w
    call     DEZIMAL
    movf     eins,w
    movwf    minute
    movf    zähn,w
    movwf     minuten

    movf     sekunden,w
    call     DEZIMAL
    movf    eins,w
    movwf     stunde
    movf     zähn,w
    movwf     stunden
    call    AUSGABE2
    movlw   .150 ; und anschließend 15ms warten
    call   VERZ100US

return

Ich:
  btfsc  EINFAHRT  ; wenn EINFAHRT (PORTA,2) =0 nächsten Befehl 
überspringen
  goto  Ich

  call   AUSGABE ;Einen Text am LC-Display ausgeben
  movlw   .150 ; und anschließend 15ms warten
  call   VERZ100US
return


ZEIT:



    decfsz   max,f
    goto   RE
       incf  sekunde,f
    DECFSZ  0x70
    GOTO RE2
    movlw  d'60'
    movwf  0x60
    incf  sekunden,1
    movlw  d'40'
    movwf  max
    goto RE
RE2
    movlw  d'15'
    movwf  max


RE
return














end

von Ottmar K. (wil1)


Lesenswert?

Hallo,
ist ja schon eine Aufgabe das wirre Gewusel aufzulösen! Solch eine Datei 
fügt man als Anlage dem Thread bei (Durchsuchen, Weitere Datei 
anhängen). Dann hat jeder die Möglichkeit das komplette ASM-File in 
MPLAB zu laden, um nachzusehen was da im Argen liegt.

Zum organisatorischen Aufbau eines AMS-Files schau Dir bitte mal in
MPLAB\MPASM Suite\Template eines der dort zum 16F84 beigefügten 
ASM-Files an.

Lese bitte auch mal zu den Interrupts im Datenblatt und zum TMR0 und 
Interrupt nochmals nach!

  bsf   INTCON,GIE    ; Interrupts generell zulassen
  bsf  INTCON, T0IE   ; TMR0-Interrupt bei Überlauf 255->0 zulassen
  bcf  INTCON, T0IF   ; Signalflag wieder zurücksetzen
;----------------------------------------------------------------------- 
--

ISR
  [Register retten)
  BCF  INTCON, T0IE  ; Flag zurücksetzen,  verhindert
               ; erneuten Aufruf eines TMR0-Interrupts

  ; Programmcode ab hier einfügen
  CALL Zeit


  [Register zurückschreiben]
  bcf  INTCON, T0IF  ; Signalflag wieder zurücksetzen
  bsf  INTCON, T0IE  ; TMR0-Interrupt bei Überlauf 255->0
         ; wieder zulassen
  RETFIE

;----------------------------------------------------------------------- 
--

Wenn Du ein lauffähiges Beispiel-Programm suchst hier findest Du es samt 
vielen Informationen:
[http://www.s hierprut.de/electronic/pic/programm/lcd.htm]
Das funktionsfähige Listing:
[http://www.sprut.de/electronic/pic/programm/lcd.zip}

mfG Ottmar

von Messuung (Gast)


Lesenswert?

danke
soll nur zeit unanhenig zeit erzeugen

ORG   0x04           ; Hier beginnt die ISR


    SWAPF W_TEMP,F         ;Swap W_TEMP
    SWAPF STATUS,W   ;Swap status to be saved in
    MOVWF S_TEMP ;Save status to bank zero STATUS_TEMP register
    BCF  INTCON, T0IE  ; Flag zurücksetzen,  verhindert

  decfsz   max,f
  goto   RE
  incf  sekunde,f
  movlw  d'15'
  movwf  max

RE

    bcf  INTCON, T0IF  ; Signalflag wieder zurücksetzen
    bsf  INTCON, T0IE  ; TMR0-Interrupt bei Überlauf 255->0

    SWAPF S_TEMP,W        ;Swap STATUS_TEMP register into W
    MOVWF STATUS         ;Move W into STATUS register
    SWAPF W_TEMP,F        ;Swap W_TEMP
    SWAPF W_TEMP,W         ;Swap W_TEMP into W

    retfie

von Ottmar K. (wil1)


Angehängte Dateien:

Lesenswert?

Hallo,
Im Dateianhang findest Du ein ASM-File mit den wichtigsten Hinweisen zu 
einem grundsätzlich funktionierenden Programm, das aber noch mit Deinen 
eigenen Anforderungen ergänzt werden muss. Dies bedeutet nicht, dass 
mein Beispiel hervorragend ist, jedenfalls besteht es aush Code der so 
schon mal bei mir gelaufen ist.

Bitte beachte, dass es um den TMR0-Interrupt nutzen zu können, 
zusätzlicher Vorbereitungen bedarf! So muss der Vorteiler vor den TMR0 
"geschaltet" werden um bei z.B. bei fosc=4MHz mit dem Vorteiler 1:16 und 
dem TMR0-Überlauf (Preset 7) einen Interrupt im 4ms-Abstand auszulösen 
(250x4ms=1Sekunde). Das kannst Du nach Deinen Anfroderungen anpassen.

mfG Ottmar

von Messuung (Gast)


Lesenswert?

Danke
habe immer noch die kake
wenn ich zu schnell werde bei aubfragen der zeit wollte nur 100us haben

von Ottmar K. (wil1)


Lesenswert?

Hallo
Du kannst keine 100µs-Interrupts fahren, wenn Deine ISR schon so lange 
oder länger braucht (CALL....). Wenn Du eine Uhr nachbilden willst, dann 
nimm längere Intervalle für den Interuptaufruf.

Nochmals: TMR0 undPrescaler im Datenblatt durcharbeiten.

Nimme Dir MPLAB vor, wähle den Debugger MPLAB-Simulator und gehe Dein 
Programm Schritt für Schritt durch.
Verwende dazu: Das Watch-Fenster - zeigt Dir die Inhalte von Variablen / 
Registern und nimm die Stopwatch zum Messen der Zeitabläufe.

Mein Programmgerüst müßte eigentlich Deine Probleme minimieren.

mfg Ottmar

von Messuung (Gast)


Lesenswert?

ICH HABE MIT DEINEN PROG AUSPROBIRT
läuft nicht

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.