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...
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
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
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
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
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
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