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
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
Danke habe immer noch die kake wenn ich zu schnell werde bei aubfragen der zeit wollte nur 100us haben
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
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.