Unterschiedliche Programme mit einem Schalter "wählen" (PIC 16F630) Im Unterforum Microcontroller - Beschreibung: Hardware - Software - Ideen - Projekte
Autor |
Unterschiedliche Programme mit einem Schalter "wählen" (PIC 16F630) Suche nach: schalter (25810) pic (2056) |
|
|
|
|
BID = 373802
Peo Gesprächig
Beiträge: 181 Wohnort: Baden-W.
|
|
Hallo
Ich würde gerne auf meinem PIC 16F630 mehrere Programme laufen haben, die ich mit Hilfe eines Tasters nacheinander aufrufen möchte.
Dazu müsste ich doch PORTA, bit 3, lediglich als Input konfigurieren und dann mit btfss/btfsc PORTA,3 abfragen können, ob dort der Schalter geschlossen ist oder nicht.
Der Rest von PortA müsste doch als Output weiterhin zur Verfügung stehen?
Sehe ich das richtig?
mfg
Peo |
|
BID = 373830
Ltof Inventar
Beiträge: 9347 Wohnort: Hommingberg
|
|
Zitat :
Peo hat am 30 Sep 2006 16:13 geschrieben :
|
die ich mit Hilfe eines Tasters nacheinander aufrufen möchte...
...ob dort der Schalter geschlossen ist oder nicht.
|
Schalter oder Taster?
RA3 ist immer Input, egal wie der Port sonst konfiguriert ist. Wenn der für eine solche Funktion verwendet wird, hat der PIC natürlich keinen externen Reset mehr.
Dem Controller ist es egal , ob er in Abhängigkeit eines Portpins verschiedene "Hauptprogramme" oder Unterprogramme abarbeitet. Weder programmiertechnisch noch sonstwie macht das einen Unterschied.
Ein Schalter für zwei Programme ist natürlich einfacher zu programmieren. Den Portpin fragt das Programm ab und zu ab und entscheidet dann, ob es in dem Programm bleibt oder in das andere springt.
Sollen es mehr als zwei Programme sein und ein Taster zum Einsatz kommen, geht das beispielsweise mit einem Interrupt. Das macht dann Sinn, wenn das Programm recht lange läuft, es aber sofort auf die Taste reagieren soll. Wenn das Programm eine recht kurze Durchlaufzeit hat, reicht es, den Port zyklisch abzufragen.
Der Taster muss entprellt werden. Nach Bemerken des Tastendrucks muss einige Millisekunden gewartet werden. Danach kann noch eine Abfrage rein, ob der Taster wieder losgelassen wurde.
Gruß,
Ltof
_________________
„Schreibe nichts der Böswilligkeit zu, was durch Dummheit hinreichend erklärbar ist.“
(Hanlon’s Razor)
[ Diese Nachricht wurde geändert von: Ltof am 30 Sep 2006 18:09 ] |
|
BID = 373946
Peo Gesprächig
Beiträge: 181 Wohnort: Baden-W.
|
Danke für die schnelle Antwort und entschuldige bitte meine unpräzise Ausdrucksweise.
Es ging mir um den Taster.
Die Frage, die mich jetzt hier hauptsächlich bewegt ist, wie ich den Interrupt machen kann, da das geplante Programm (eine Ampelsteuerung) ziemlich lange läuft (ca. 40 Sekunden).
Nunmehr habe ich das Problem, dass ich mit den Datenblättern nicht weiter komme, da ich, zugegebener Maßen, zu wenig Ahnung von Pcs habe.
Wie mache ich das mit dem Interrupt?
Wenn man mir damit helfen könnte, wäre das wunderbar.
mpg
Peo
|
BID = 373996
Ltof Inventar
Beiträge: 9347 Wohnort: Hommingberg
|
Moin Peo,
zunächst mal eine Ergänzung meiner obigen Behauptung bezüglich mehrerer "Hauptprogramme" im Pic:
Gleichnamige Sprungmarken dürfen nicht mehrmals auftauchen. Variablen, die in allen Programmen verwendet werden, verändern natürlich den Wert. Variable X hat beim erneuten Sprung in "Programm 1" natürlich nicht mehr den ursprünglichen Wert, wenn diese in "Programm 2" auch verwendet wurde.
Sind Deine Hauptprogramme alleine bereits lauffähig gewesen, so sind zum zusammen Benutzen gegebenenfalls Variablennamen und Sprungmarken anzupassen.
Interrupts kann ich auch nicht besser erklären als Sprut:
http://www.sprut.de/electronic/pic/int/int.htm
Wenn irgend möglich, würde ich auf Interrupts verzichten (und Andere, die etwas davon verstehen, empfehlen das auch).
Für Deine Anwendung fällt mir noch eine dritte Möglichkeit ein:
Statt die Taste direkt abzufragen und darauf zu reagieren, wird an geeigneter Stelle (z.B. in den Warteschleifen der Ampelsteuerung) auf Tastendruck eine Flagge ("flag") gesetzt. Diese Flagge ist einfach ein Bit einer selbst deklarierten Variable. Der Tastendruck wird also gespeichert und an den richtigen Stellen wird darauf reagiert. Die Information des Tastendruckes geht also nicht verloren, selbst wenn die Taste längst wieder losgelasen wurde. Die Flagge wird dann nach Abarbeiten der Reaktion zurückgesetzt.
Gruß,
Ltof
_________________
„Schreibe nichts der Böswilligkeit zu, was durch Dummheit hinreichend erklärbar ist.“
(Hanlon’s Razor)
[ Diese Nachricht wurde geändert von: Ltof am 1 Okt 2006 8:56 ]
|
BID = 374105
Peo Gesprächig
Beiträge: 181 Wohnort: Baden-W.
|
Du meinst also, dass ich z. B. die Variable TASTER habe, die in der Initialisierung den Wert '00000000' erhält, und folgenden Code eingebe:
btfsc TRISA,3 ;RA3 wird hier abgefragt
movlw .1
btfsc TRISA,3
movwf TASTER
Dann könnte ich in einem späteren Programmabschnitt abfragen, ob der Taster gedrückt wurde, da ja die Variable TASTER nun den Wert 1 hat?
Wenn dem so ist, wie Frage ich den Wert der Variable ab?
mfg
Peo
|
BID = 374159
Ltof Inventar
Beiträge: 9347 Wohnort: Hommingberg
|
So umständlich muss es nicht sein und außerdem enthält es einen gravierenden Fehler:
Nicht TRISA,3 wird abgefragt, sondern PORTA,3
Also etwa so:
btfsc porta,3
bsf Tastendruck
"Tastendruck" ist ein Bit, welches so deklariert wird:
Flags equ 0x25 (oder eine andere freie Ram-Adresse)
#define Tastendruck Flags,0
Nun ist Bit0 des Bytes "Flags" das Bit für das Speichern des Tastendrucks.
Das kannst Du genauso mit btfs* abfragen wie ein Portbit.
Du musst es dann nur an passender Stelle wieder selbst löschen, sonst denkt der µC ständig, er müsse auf den Tastendruck reagieren.
Eine Frage:
Hast Du bereits ein selbst geschriebenes, lauffähiges Programm? Z.B. die Ampelsteuerung?
Gruß,
Ltof
_________________
„Schreibe nichts der Böswilligkeit zu, was durch Dummheit hinreichend erklärbar ist.“
(Hanlon’s Razor)
|
BID = 374170
Peo Gesprächig
Beiträge: 181 Wohnort: Baden-W.
|
Hallo
Wenn ich also das Flag setze, frage ich vor dem Springen nur, ob das Flag besetzt ist oder nicht. z.B.
btfss Tastendruck
goto Programm1
btfsc Tastendruck
goto Programm2
kann ich das Flagbit auch mit
decfsz Tastendruck
nop
jeweils zwischen 0 und 1 wechseln?
Das Programm unten ist etwas verschachtelt.
Die Ampelsteuerung ist zu Versuchszwecken mit schnellem Blinken ersetzt worden.
Das Programm startet im AMPEL und wenn der Taster gedrückt wird, also RA3 Spannung erhält, dann wird im delayloop1 auf wechselzuloop2 verwiesen. Dort bleibt der µC, bis der Taster losgelassen wird (Abfrage jede Millisekunde), dann springt der µC in Loop2 - das zweite Hauptprogramm.
Wenn der Taster wieder gedrückt wird, geschieht in delayloop2 das Gleiche wie oben. In wechselzuloop1 wird gewartet, bis der Taster losgelassen wird, danach springt der µC in AMPEL zurück.
__________________________
AMPEL
movlw .255
movwf PORTC
call delayloop1
movlw .0
movwf PORTC
call delayloop1
goto AMPEL
loop2
movlw .255
movwf PORTC
call delayloop2
call delayloop2
movlw .0
movwf PORTC
call delayloop2
call delayloop2
goto loop2
;-------------------------------------------------------------------
;Delay Routine
delayloop1
movlw .1
movwf delayA
loopA
movlw .256
nop
movwf delayB
loopB
btfss TRISA,3
goto wechselzuloop2
movlw .255
movwf delayC
loopC
decfsz delayC, f
goto loopC
decfsz delayB, f
goto loopB
decfsz delayA, f
goto loopA
return
delayloop2
movlw .1
movwf delayA
loopAA
movlw .255
nop
movwf delayB
loopBB
btfss TRISA,3
goto wechselzuloop1
movlw .255
movwf delayC
loopCC
decfsz delayC, f
goto loopCC
decfsz delayB, f
goto loopBB
decfsz delayA, f
goto loopAA
return
wechselzuloop1
movlw .255
movfw PORTC
movfw delayC
Schmidt1
decfsz delayC
goto Schmidt1
btfsc TRISA,3
goto AMPEL
goto wechselzuloop1
wechselzuloop2
movlw .255
movfw PORTC
movfw delayC
Schmidt2
decfsz delayC
goto Schmidt2
btfsc TRISA,3
goto loop2
goto wechselzuloop2
[ Diese Nachricht wurde geändert von: Peo am 1 Okt 2006 19:40 ]
[ Diese Nachricht wurde geändert von: Peo am 1 Okt 2006 19:41 ]
|
BID = 374186
Ltof Inventar
Beiträge: 9347 Wohnort: Hommingberg
|
Ich bin jetzt gerade zu faul, die Programmstruktur nachzuvollziehen. Schau Dir mal die kommentierten Codeschnipsel in Ruhe an. Vielleicht hilfts ja.
Gruß,
Ltof
_________________
„Schreibe nichts der Böswilligkeit zu, was durch Dummheit hinreichend erklärbar ist.“
(Hanlon’s Razor)
|
BID = 374208
Peo Gesprächig
Beiträge: 181 Wohnort: Baden-W.
|
Danke für das Programm.
Hier ist aber kein Flag gesetzt, so wie du das oben vorgeschlagen hast.
#define Taster TRISA,3 (TRISA,3 funktioniert anscheinend, da das Programm oben läuft) heißt doch nur, dass man statt TRISA,3 einfach Taster schreiben kann.
Bei der hier angehängten Programmstruktur wird ja immer nur zu Beginn des jeweiligen "Hauptprogramms" nach dem Taster gefragt. Ich bräuchte, auf Grund der Länge des Programms, dies aber ständig. Und da kommt das Flag wieder ins Spiel.
Das werde ich jetzt mal testen.
mfg
Peo
[ Diese Nachricht wurde geändert von: Peo am 1 Okt 2006 21:28 ]
|
BID = 374221
Ltof Inventar
Beiträge: 9347 Wohnort: Hommingberg
|
Zitat :
Peo hat am 1 Okt 2006 21:26 geschrieben :
|
#define Taster TRISA,3 (TRISA,3 funktioniert anscheinend
|
Wenn das funktioniert, kann das nur ein Bug auf dem Chip sein! Das solltest Du Dir ganz schnell abgewöhnen und den Port korrekt abfragen! Beim nächsten PIC funktioniert das garantiert nicht mehr.
Zitat :
|
Hier ist aber kein Flag gesetzt, so wie du das oben vorgeschlagen hast.
|
Dann hast Du noch nicht alles gelesen.
_________________
„Schreibe nichts der Böswilligkeit zu, was durch Dummheit hinreichend erklärbar ist.“
(Hanlon’s Razor)
[ Diese Nachricht wurde geändert von: Ltof am 1 Okt 2006 22:09 ]
|
BID = 374224
Peo Gesprächig
Beiträge: 181 Wohnort: Baden-W.
|
Danke für deine Tipps.
Ich habe gerade mit Flags gearbeitet, genauer mit einem Flag.
Funktioniert super und ist programmtechnisch fast kein Aufwand.
Das Schwierigste ist, bei den "Skip If" Abfragen den Überblick zu behalten, was wie übersprungen werden soll und was nicht, damit man das Flag auch richtig rauf und runter setzt.
Wenn ich jetzt mit zwei Flags arbeiten würde, könnte ich theoretisch vier Programme abspulen, mit drei Flags schon acht. Allerdings ist dann die Frage, ob ich die Logik hinter der Logik noch für mich umgesetzt bekomme
Nochmals Danke
mfg
Peo
|
BID = 374279
Ltof Inventar
Beiträge: 9347 Wohnort: Hommingberg
|
Zitat :
Peo hat am 1 Okt 2006 22:10 geschrieben :
|
Wenn ich jetzt mit zwei Flags arbeiten würde, könnte ich theoretisch vier Programme abspulen, mit drei Flags schon acht.
|
In dem Beispiel sind beliebig viele Programme mit einem Flag abzuspulen. Es geht lediglich darum, den Tastendruck nicht zu vergessen.
Dabei ist es egal, ob, wie in dem Beispiel, von der Hauptschleife aus eins nach dem anderen Programm angesprungen wird, oder ob aus Programm1 bei erkanntem Tastendruck in Programm2 gesprungen wird, von 2 nach 3, von 3 nach 4 usw. Dafür reicht wirklich ein Flag.
Was Du beschreibst, ist ein Zustandszähler. Den würde man aber nicht mehr mit Bit-Abfragen auswerten, sondern durch Vergleiche mit Konstanten.
Zufällig habe ich ein paar 16F630 hier und habe Dein Programm auf PICkit2 (nachdem ich ein paar Initialisierungs-Zeilen hinzugefügt hatte) ausprobiert. Tatsächlich wechselt der PIC zwischen schnellem und langsamen Blinken auf Tastendruck. Was da passiert ist mir schleierhaft.
Nachdem das Proggi drauf ist, verweigert der PIC (oder PICkt2?) jegliche weitere Kommunikation. Da ist jemand zutiefst beleidigt.
Das geht erst wieder, nachdem ich den PIC mit PICstart gelöscht habe.
Welchen Datumscode haben Deine 16F630? Meine haben 051108V.
Gruß,
Ltof
_________________
„Schreibe nichts der Böswilligkeit zu, was durch Dummheit hinreichend erklärbar ist.“
(Hanlon’s Razor)
[ Diese Nachricht wurde geändert von: Ltof am 2 Okt 2006 8:16 ]
|
BID = 374285
Ltof Inventar
Beiträge: 9347 Wohnort: Hommingberg
|
Das hätte ich auch gleich sehen können...
Die Abfrage von TRISA greift wegen der fehlenden Bankumschaltung tatsächlich auf PORTA zu. Deshalb funzt das.
@Peo
das sind zwei Fehler im Programm, die sich zufällig gegenseitig aufheben.
Viel Glück weiterhin!
Hoffentlich landen Deine Programme niemals in irgendwelchen sicherheitsrelevanten Systemen...
_________________
„Schreibe nichts der Böswilligkeit zu, was durch Dummheit hinreichend erklärbar ist.“
(Hanlon’s Razor)
|
BID = 374445
Peo Gesprächig
Beiträge: 181 Wohnort: Baden-W.
|
Zitat :
|
Was Du beschreibst, ist ein Zustandszähler. Den würde man aber nicht mehr mit Bit-Abfragen auswerten, sondern durch Vergleiche mit Konstanten.
|
Was mich zur nächsten Frage bringt, wie vergleiche ich Konstanten?
Zitat :
|
Die Abfrage von TRISA greift wegen der fehlenden Bankumschaltung tatsächlich auf PORTA zu. Deshalb funzt das.
|
Das mit den Bänken habe ich auch noch nicht verstanden. Ich habe dies immer aus dem PICKIT Programm kopiert
Wozu ist das gut und woher weiß ich, in welche Bank ich schalten muss (du meinst doch sicher damit die Register-Banks/Pages?)
Zitat :
|
Hoffentlich landen Deine Programme niemals in irgendwelchen sicherheitsrelevanten Systemen...
|
Schlimmstenfalls zur Zugsteuerung auf einer Modelleisenbahn
Danke nochmal
anbei das "geflaggte" Programm. Es ist dank deiner Hilfe deutlich kürzer als das weiter oben.
mfg
Peo
_______________________
list p=16f630 ; list directive to define processor
#include <p16F630.inc> ; processor specific variable definitions
errorlevel -302 ; suppress message 302 from list file
__CONFIG _CP_OFF & _CPD_OFF & _BODEN_OFF & _MCLRE_OFF & _WDT_OFF & _PWRTE_ON & _INTRC_OSC_NOCLKOUT
; '__CONFIG' directive is used to embed configuration word within .asm file.
; The lables following the directive are located in the respective .inc file.
; See data sheet for additional information on configuration word settings.
VARIABLES UDATA_SHR
delayA RES 1
delayB RES 1
delayC RES 1
Flags equ 0x25 ;(oder eine andere freie Ram-Adresse)
#define Taster Flags,0
;**********************************************************************
RESET_VECTOR CODE 0x000 ; processor reset vector
goto main ; go to beginning of program
PROGRAM CODE
main
movwf OSCCAL ; update register with factory cal value
call 0x3FF ; retrieve factory calibration value
bsf STATUS,RP0 ; set file register bank to 1
movlw B'00000000'
movwf TRISA
movwf TRISC
bcf STATUS,RP0 ; set file register bank to 0
clrf PORTA
clrf PORTC
bcf Taster
loop1
movlw .255
movwf PORTC
call delayloop1
movlw .0
movwf PORTC
call delayloop1
goto loop1
loop2
movlw .255
movwf PORTC
call delayloop1
call delayloop1
call delayloop1
movlw .0
movwf PORTC
call delayloop1
call delayloop1
call delayloop1
goto loop2
;-------------------------------------------------------------------
;Delay Routine
delayloop1
movlw .1
movwf delayA
loopA
movlw .256
nop
movwf delayB
loopB
btfss PORTA,3
goto entprellen
movlw .256
movwf delayC
loopC
decfsz delayC, f
goto loopC
decfsz delayB, f
goto loopB
decfsz delayA, f
goto loopA
return
entprellen
btfsc Taster
call einsweniger
einsmehr
bsf Taster
call entprellenschleife
einsweniger
bcf Taster
entprellenschleife
movlw .255
movwf delayA
warten
decfsz delayA
goto warten
btfss PORTA,3
goto entprellenschleife
btfss Taster
goto loop1
goto loop2
;-------------------------------------------------------------------
END ; directive 'end of program'
[ Diese Nachricht wurde geändert von: Peo am 2 Okt 2006 19:41 ]
|
BID = 374538
Ltof Inventar
Beiträge: 9347 Wohnort: Hommingberg
|
Zitat :
Peo hat am 2 Okt 2006 19:39 geschrieben :
|
Das mit den Bänken habe ich auch noch nicht verstanden. |
Dieses und anderes elementare Grundwissen zu dem von Dir verwendeten µC einfach auszulassen, ist dreist!
Trotzdem ein lauffähiges Programm zu schreiben, oder besser: zu erschaffen, ist - hmm - ich würde es als höhere Kunst bezeichnen...
Zu den Banken (oder "Bänken"? - hat jemand einen Duden zur Hand?):
Das ist eine - häufig kritisierte - Eigenheit der PICs. Die Special-Function-Register, also die Speicherzellen zum Einrichten und Steuern der µC-eigenen Hardware (Ports, Timer, usw.) liegen in zwei Banken. Es gibt auch PICs mit nur einer Bank und womöglich auch mit mehr als zwei - das weiß ich jetzt nicht. Dazu sollte man jeweils das Datenlatt studieren. Bleiben wir bei dem 16F630.
Beispiel ( bitte ausdrucken und aufmerksam lesen):
Das Register PORTA liegt an Adresse 05h in Bank0. Das Register TRISA liegt an Adresse 85h in Bank1. Ein direkter Zugriff dahin ist nicht möglich. Man muss dem µC vorher mitteilen, in welcher Bank das Register liegt, auf das man zugreifen will.
Das ist wie eine Reihe von Parkplätzen rechts und links der Fahrspur. Die Parkplätze links (Bank0) haben die Nummern 00h bis 1Fh und die Parkplätze rechts von 80h bis 9Fh (Bank1). Der Parkplatzzähler kann auf beiden Seiten nur von 0 bis 1F zählen. Das höchste Bit der Adresse existiert nur in der Bezeichnung der Parkplatznummer. Bekomme ich einen Parkplatz zugeteilt, so muss mein Navigationssystem neben der Parkplatznummer auch die Information über die Reihe (rechts oder links) bekommen. Bekomme ich den Parkplatz 85h (TRISA) zugeteilt. Der Wächter vergisst mir aber zu sagen, dass der in der rechten Reihe liegt, so lande ich in der linken Reihe auf Platz 05h (PORTA). Wenn es dumm läuft, stand da schon ein Auto, welches ich dann in den Graben schiebe. Das ist dann weg. Will das später jemand abholen, benutzt er mein Auto, welches nun auf "seinem" Platz steht.
Anders als im wirklichen Leben, sind die Autos nicht weg, wenn man sie abholt. Man benutzt quasi eine Kopie des Autos. Nur wenn vorher ein Auto falsch geparkt wurde, benutzt man eine falsche Kopie.
Die Flagge, die mir den Weg nach links oder rechts weist, ist das Bit RP0 im Register STATUS. Ist es auf 0, ist die linke Reihe gemeint, ist es auf 1, ist die rechte Reihe gemeint. Der Inhalt des Status-Registers ist in beiden Banken identisch. Deshalb funktioniert das überhaupt.
Du hast von TRISA gesprochen. Für das Funktionieren des Programmes war an der Stelle eigentlich PORTA gefragt. Da aber TRISA auf Bank0 angesprochen wurde (STATUS,RP0 war 0), wurde tatsächlich in BANK0 Adresse 05h angesprochen, also zufällig das richtige Register. Das war Glück!
Üblicherweise führt das Auslassen der Bankumschaltung zum Versagen des Programmes.
Schau mal in Kapitel 2.2.2 im Datenblatt, wo die Register alle liegen.
Du hast übrigens noch so einen künstlerischen Doppelfehler ohne Wirkung in Deinem Programm. Gleich die ersten beiden Programmzeilen! Das Register OSCCAL liegt in Bank 1. OSCCAL ist zum Kalibrieren der Taktfrequenz des internen Oszillators. In Adresse 0x3FF steht der Kalibrierwert für den internen Oszillator, damit er möglichst genau mit 4 MHz läuft. Das Holen des Kalibrierwertes (call 0x3FF) muss natürlich VOR dem Schreiben in OSCCAL gemacht werden und nicht danach! Und dann muss eben auch auf die richtige Bank geschaltet werden. Dein Oszillator läuft also mit einer unkalibrierten Frequenz. Wenn die genaue Frequenz unkritisch ist, merkt das keiner! Das Programm bleibt trotzdem lauffähig.
Gruß,
Ltof
_________________
„Schreibe nichts der Böswilligkeit zu, was durch Dummheit hinreichend erklärbar ist.“
(Hanlon’s Razor)
[ Diese Nachricht wurde geändert von: Ltof am 3 Okt 2006 10:05 ]
|
|
Zum Ersatzteileshop
Bezeichnungen von Produkten, Abbildungen und Logos , die in diesem Forum oder im Shop verwendet werden, sind Eigentum des entsprechenden Herstellers oder Besitzers. Diese dienen lediglich zur Identifikation!
Impressum
Datenschutz
Copyright © Baldur Brock Fernsehtechnik und Versand Ersatzteile in Heilbronn Deutschland
gerechnet auf die letzten 30 Tage haben wir 22 Beiträge im Durchschnitt pro Tag heute wurden bisher 28 Beiträge verfasst © x sparkkelsputz Besucher : 182653126 Heute : 8200 Gestern : 6686 Online : 145 2.1.2025 23:00 5 Besucher in den letzten 60 Sekunden alle 12.00 Sekunden ein neuer Besucher ---- logout ----viewtopic ---- logout ----
|
xcvb
ycvb
0.0544860363007
|