Forum: Mikrocontroller und Digitale Elektronik Achtung: Anfänger! PIC16F628 Fehlermeldung beim Assemblieren


von Norbert P. (poff)


Angehängte Dateien:

Lesenswert?

Hallo,
seid ein paar Tagen versuche ich mich im Programmieren eines 
Mikrocontrollers in Assembler (Microchip MPLAB IDE V8.90). Der 
Mikrocontroller, den ich mit meinen Versuchen quäle, ist ein PIC16F628. 
Zum Brennen verwende ich den Sprut-Brenner P8. Das Brennen von fertigen 
HEX-Dateien und auch das Assemblieren von leicht geänderten *.asm-Files 
klappt auch.
Jetzt habe ich ein eigenes Programm geschrieben und erhalte beim 
Assemblieren folgende Fehlermeldung in Zeile 71 und somit kein HEX-File:
Symbol not previously defined (ZeVs)
Ich kann in dieser Zeile keinen Fehler erkennen. Zumindest keinen 
Tippfehler.
Kann mir jemand einen Tip geben?
Falls im Programmablauf ein Fehler sein sollte, bitte nicht daraufhin 
weisen. Dass will ich selber herausfinden.
Danke, Norbert

von Chris B. (dekatz)


Lesenswert?

"ZeVs" ist nicht das Gleiche wie "ZeVS" - Groß/Kleinschreibung beachten!

von Fuerst-Rene (Gast)


Lesenswert?

Wo definierst du?
  movwf  Zeit    ;Wert für

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

Fuerst-Rene schrieb:
> Wo definierst du?
>   movwf  Zeit    ;Wert für

Das ist ein Unterprogramm:
  Call  Zeit

Aber ein recht eigenartiges, das den Stack versaut:
Zeit
  movf  Wert,0
  Goto  MainShift

Solche Unterprogramme/Funktionen sollten per RET(URN) beendet werden, 
weil übliche Assembler bei einem CALL die Rücksprungadresse auf den 
Stack legen. Oder ist das beim PIC anders? (Es würde mich nicht 
wundern... ;-)

von Chris B. (dekatz)


Lesenswert?

Fuerst-Rene schrieb:
> Wo definierst du?
>
>   movwf  Zeit    ;Wert für

Tja seltsam, aber der Assembler macht daraus
00F    00AD     MOVWF 0x2d    73:      movwf  Zeit    ;Wert für

und BUILD SUCCEEDED!!??

von Chris B. (dekatz)


Lesenswert?

Chris B. schrieb:
> Das ist ein Unterprogramm:
>
>   Call  Zeit

ahh stimmt, zu spät gesehen.
Aber da ist noch mehr faul...d1,d2,d3 kollidieren mit Wert, ZeVS 
usw......

von Norbert P. (poff)


Lesenswert?

Das ging ja schnell! :-)
Danke für eure Hilfe. Zigmal durchgelesen und doch ein Tipfehler.
Jetzt gibt es keine Fehlermeldung mehr. Zumindest beim Assemblieren.
Schöne Grüße, Norbert

von GroberKlotz (Gast)


Lesenswert?

Hallo Norbert,
Dein Fehler ist ein Missverständnis im Gebrauch von Labels und von 
Variablen.
;LABELS & KONSTANTEN
#define Wert 0x20 ;Speicherzelle für den Wert der Zeitkonstante
#define ZeVS 0x21 ;ZeVS = Zelle zum Zwischenspeichern
#define ZeAd 0x22 ;ZeAd = Zelle zum Zwischenspeichern eines

Du möchtest Wert, ZeVS, ZeAD, sämtlich Labels und keine Variablen, den 
Inhalt der RAM-Adresse 0x20 - 0x22 zuweisen.

Zugleich verwendest Du aber bei der Deklaration von Variablen
clrf ZeVS
clrf ZeAd
die gleichen Namen als Variable. Da meckert der Assembler!

Richtig wäre z.B.

Zeitverzoegerung equ d'20' ;Konstante, Wert für delay 20x100ms
also reale Zahl, keinen Registerinhalt zuweisen!

Dann kannst im Programmlauf z.B. so
  movlw Zeitverzoegerung    ;Label (enthält .20)
  movwf ZeVS                ;Variable!
übers WREG den Wert in die Variable Delaytime kopieren
Nicht vergessen die Variable zu deklarieren:
  CBLOCK  0x20  ;Variablen ab Adresse 20h anlegen
    d1,d2,d3  ;Zähler in Sub Delay100ms
    ZeVS
  ENDC

oder aber:

movlw Zeitverzoegerung
CALL Delay100ms
den Wert übers WREG direkt an das Unterprogramm übergeben.

Mit solch einem Label sind auch einfache Berechnungen möglich. Vgl. dazu 
die MPLAB-Hilfe "arithmetische operatoren" z.B:

movlw Zeitverzögerung * 5  ;Die Rechnung macht der Compiler beim 
assemblieren für Dich
movwf Delaytime ;Delaytime hat jetzt den Wert .100.

#define verwendet man um komplexere Inhalte einfach lesbar zu machen:
#define LED_EIN bsf PORTB,3
#define LED_AUS bcf PORTB,3

Jetzt genügt es im Programmlauf zu schreiben
LED_EIN ;der Assembler schreibt nun in das Programm-Memory (vgl. MPLAB - 
View) "bsf PORTB,3", also den Inhalt des Labels "LED_EIN". Probier es 
einfach mal aus.

Ich hoffe Dich jetzt in die richtige Richtung geschubst zu haben.

mfG GroberKlotz

von Chris B. (dekatz)


Lesenswert?

GroberKlotz schrieb:
> Zugleich verwendest Du aber bei der Deklaration von Variablen
>
> clrf ZeVS
>
> clrf ZeAd
>
> die gleichen Namen als Variable. Da meckert der Assembler!

Das bemängelt der Assembler überhaupt nicht! Bis auf die vertauschte 
Groß/Kleinschreibung wird OHNE Fehlermeldung assembliert.

Nur in der Praxis liegen seine "ZeVs" usw. auf den gleichen RAM-Adressen 
die die Variablen d1,..... für die "Delay_100ms".

Entweder verwendet man CBLOCK oder #define - das aber Konsequent sonst 
verliert man total die Übersicht.

von GroberKlotz (Gast)


Lesenswert?

Chris B. schrieb:
> Das bemängelt der Assembler überhaupt nicht!

OK, stimmt, habs jetzt ausprobiert. Na ja, bin aber Gott sei Dank bisher 
noch nie auf die Idee gekommen #define bzw. cblock zu vermischen... :-) 
Stimme völlig zu dass das nur Verwirrung stiftet.

@ Norbert:
Verwendest Du den MPLAB-Simulator? Falls nicht, solltest Du Dich damit 
unbedingt beschäftigen, dann bemerkst Du sofort wo in nachstehender 
Zählschleife aus Deinem Programm der Wurm drin ist und diese so nicht 
funktionieren kann:

MainShift
  movwf  ZeVS           ;WREG->ZeVS
  CALL   Delay100ms     ;dort zigfach movlw...
  decfsz ZeVS,1         ;ZeVS-1, Ergebnis in ZeVS
  GOTO  MainShift

mfG GroberKlotz

von Norbert P. (poff)


Lesenswert?

@ Chris:
Damit kämpfe ich gerade.

Chris B. schrieb:
> Entweder verwendet man CBLOCK oder #define - das aber Konsequent sonst
> verliert man total die Übersicht.

Heißt das, dass man in einem Programm entweder nur CBLOCK oder nur 
#define verwenden soll? Ich versuche es jetzt so:

;VARIABLEN
  CBLOCK  0x20  ;Variablen ab Adresse 20h anlegen
  d1,d2,d3  ;Zähler in Sub Delay100ms
  CBLOCK  0x24  ;Variablen ab Adresse 24h anlegen (damit andere 
RAM-Adressen benutzt werden)
  ZeVs    ;Zelle zum Zwischenspeicher der Verzögerungsschleife
  ZeAd    ;Zelle zum Zwischenspeichern eines Summanden für
      ;die Addition mit LEDPORT
  ENDC
  ;
;LABELS & KONSTANTEN
  #define  LEDPORT    PORTB
  #define  LEDTRIS    TRISB
  Delay  equ  d'20'  ;Delay den Wert "20" zuweisen

@ GroberKlotz:
Auch daran, dass das der Inhalt vom W-Register vor Call Delay100ms 
gerettet werden muss, arbeite ich.
MPLAB-Simulator? Kenne ich noch nicht.

von Chris B. (dekatz)


Lesenswert?

Norbert Potthoff schrieb:
> Heißt das, dass man in einem Programm entweder nur CBLOCK oder nur
>
> #define verwenden soll? Ich versuche es jetzt so:
>
>
>
> ;VARIABLEN
>
>   CBLOCK  0x20  ;Variablen ab Adresse 20h anlegen
>   d1,d2,d3  ;Zähler in Sub Delay100ms
>   CBLOCK  0x24  ;Variablen ab Adresse 24h anlegen (damit andere
> RAM-Adressen benutzt werden)
>   ZeVs    ;Zelle zum Zwischenspeicher der Verzögerungsschleife
>   ZeAd    ;Zelle zum Zwischenspeichern eines Summanden für
>       ;die Addition mit LEDPORT
>   ENDC


Ja - entweder oder - ausser du willst dir das Programmieren und 
Fehlersuchen unnötig schwer machen.

CBLOCK  0x20  ;Variablen ab Adresse 20h anlegen
  d1,d2,d3  ;Zähler in Sub Delay100ms
ENDC

CBLOCK  0x24
  ZeVs    ;Zelle zum Zwischenspeicher der Verzögerungsschleife
  ZeAd    ;Zelle zum Zwischenspeichern eines Summanden für
           ;die Addition mit LEDPORT
ENDC

(CBLOCK...ENDC gehören zusammen, weiss jetzt nicht ob MPLAB mehrere 
CBLOCK ohne dazugehörige ENDC "frisst" ;-) )

von GroberKlotz (Gast)


Lesenswert?

Norbert Potthoff schrieb:
>Auch daran, dass das der Inhalt vom W-Register vor Call Delay100ms
>gerettet werden muss, arbeite ich.

NEIN! Du mußt die Variable "ZeVs" davor bewahren dass diese durch 
"movwf" mit dem Inhalt des WREG zu überschrieben wird, nachdem Du den 
Wert von "ZeVs" mittels "decfsz" um 1 vermindert hast!
Denke dabei daran, dass "decfsz ZeVs,1" das Ergebnis ZeVs - 1 in die 
Variable ZeVs zurückschreibt!

> MPLAB-Simulator? Kenne ich noch nicht.

Dann gehe mal so vor um MPLAB SIM aktivieren:
   MPLAB starten, dann nachfolgende Menüs durchgehen

1. Menü [Debugger] - Select Tool - 4. MPLAB SIM [Click)
2. Menü [Debugger] - Settings - [Click]
                     Processor Settings: eintragen z.B. fosc 4MHz
                     Animation / Real Time Updates
                     Haken vor enable real time watch
                     [OK]
Watch-Window aktivieren
Damit kann man den Inhalt von Registern, also z.B. PORTA, PORTB, 
Variable und deren Veränderung im Programmlauf beobachten.
1. Menü [View] - Watch [Click]
   jetzt ist das Watch-Fenster sichtbar.
2. Mausklick auf oberste freien Platz im Fenster setzen
   und z.B. WREG eintragen. Ist jetzt ein Programm aktiv, ist der Inhalt
   des W-Registers zu sehen, gleiches mit PORTB, oder der Variablen 
"Test"
   natürlich müssen diese Register in Deinem Programm existieren, 
Variable
   müssen deklariert sein.
3. Probiere das alles mal aus.

Nützliche Literatur zu MPLAB SIM:
   MPLAB User Guide (englisch) im Verzeichnis von MPLAB
   Kleine Einführung in die Simulation mittels Microchip MPLAB IDE
   [http://www.fernando-heitor.de/index.php/downloads/Dokumente/MPLAB-Tutorial/]
   in Deutsch, runterladen und nicht vergessen: Tante groogle nach
   weiteren Informationen intensiv befragen!

Zu guter Letzt: MPLAB hat eine eingebaute Hilfe mit der man fast alles 
zum Assembler (Befehle, Labels, Variable usw) erfahren kann, allerdings 
durchweg in englischer Sprache.

mfG GroberKlotz

von GroberKlotz (Gast)


Lesenswert?

Chris B. schrieb:
> (CBLOCK...ENDC gehören zusammen, weiss jetzt nicht ob MPLAB mehrere
> CBLOCK ohne dazugehörige ENDC "frisst" ;-) )

Falsch:
 cblock 0x20      ;Variablen ab Adresse 20h anlegen
        d1,d2,d3  ;Zähler in Sub Delay100ms
 cblock 0x30
        BCD0
 endc

Richtig! Aber nur sinnvoll wenn man weiß zu was so was gut ist!
 cblock 0x20      ;Variablen ab Adresse 20h anlegen
        d1,d2,d3  ;Zähler in Sub Delay100ms
 endc
 cblock 0x30      ;so können die Register 0x24 bis 0x29 z.B.
        BCD0      ;für FSR/INDF-Operationen freigehalten werden

 ENDC

mfG GroberKlotz

von Norbert P. (poff)


Lesenswert?

Besten Dank für eure Hilfe!!!
Ich werde eure Tips hoffentlich fehlerfrei umsetzen. Ich melde mich 
wieder, wenn es läuft. Oder, was ich nicht möchte, wenn es nicht 
geklappt hat.
Nochmals Danke und bis bald.
Schöne Grüße aus Münster, Norbert

von W.S. (Gast)


Lesenswert?

Ja, dieses Manko bei der Variablendefinition hatte mich schon in den 
90ern geärgert - und mich veranlaßt, mir meinen eigenen Assembler zu 
schreiben, wo ich Segmente (CODE und RAM) und Organisatorisches (ORG, 
DS, DATA usw) eingeführt habe.

Wenn man den häßlichen originalen Assembler von Microchip benutzen will, 
dann sollte man sich als Denkhilfe ein paar Konventionen ausdenken, an 
die man sich dann strikt hält.

Zum Beispiel:

- alle definierten Konstanten mit wf_ beginnen lassen ("Wert Für" 
etwas).
#define wf_PortA   B'10110'

    MOVLW  wf_PortA
    MOVWF  PortA

- niemals 0 oder 1 bei dem 2. Parameter schreiben, sondern immer W oder 
F (notfalls selber vorher definieren), also

    MOVF  PortA,W
    XORWF PortB,F

- bei lokalen Marken einen Unterstrich als erstes, und NIEMALS woanders 
den Unterstrich als erstes benutzen.

         MOVLW 100
_warten: ADDLW  -1
         BTFSS  Status,Z
         GOTO   _warten

Ähem, mal ne andere Frage am Rande: Kann man bie der neuesten Kreation 
des MPLAB inzwischen einen eigenen Assembler einbinden?

W.S.

von Ottmar K. (wil1)


Lesenswert?

W.S. schrieb:
>...mich veranlaßt, mir meinen eigenen Assembler zu schreiben

prinzipiell stimme ich Dir ja zu, aber warum preist Du Deinen 
selbstgeschriebenen Assembler seit Jahren gebetsmühlenhaft an?
Frag mal Opa Guugle nach  "W.S. (Gast)" AND  "eigenen Assembler"

Ich finde übrigens den MPLAB-Assembler gar nicht so schlecht und komme 
damit schon seit Jahren sehr gut zurecht.

Wir wollen hier aber bitte keine Diskussion über den besten Assembler 
vom Zaune brechen, helfen wir lieber dem Norbert bei der Lösung seiner 
Probleme.

mfG Ottmar

von Norbert P. (poff)


Angehängte Dateien:

Lesenswert?

!!!! J U C H U U U U !!!!
Es läuft!!! Keine Fehlermeldung beim Assemblieren, alle LEDs schalten 
nacheinander ein und bleiben auch an!!!
@GroberKlotz:
Nachdem ich verstanden habe, wie die Zeitschleife "Delay100ms" 
funktioniert, wusste ich auch was du mit (Zitat):
Du mußt die Variable "ZeVs" davor bewahren dass diese durch
"movwf" mit dem Inhalt des WREG zu überschrieben wird...
gemeint hast.

@Chris:
Danke für den Hinweis mit der Kollision der Speicherzellen D1, D2, D3, 
...

Eine Kleinigkeit muss ich noch herausfinden. Die Zeitschleife bei mir 
ist wesentlich länger als die 100ms, die es bei einem 4MHz-Quarz sein 
sollen.
Noch habe ich keine Idee. Der Quarz auf meiner Testplatine hat 4MHz.

Euch allen nochmal ein dickes, fettes D A N K E !!! :-)))

von GroberKlotz (Gast)


Lesenswert?

Hallo Norbert,
schön, dass es geklappt hat! Wie mißt Du die Dauer der 
Verzögerungsschleife?

Diese Verzögerungsschleife
       movlw .20
       movwf ZeVs
MainShift
       movf ZeVs,W
       CALL Delay100ms
       .....
       GOTO MainShift

macht genau das Richtige, um 2 Sekunden Delay zu erhalten (genau 
1.999985 Arbeitszyklen mit 4MHz-Quarz). Es kann nur sein dass ZeVs beim 
wiederholten Schleifendurchlauf nicht mehr den ursprünglichen WErt von 
.20 hat! Lass Dir was einfallen! Vielleicht ist es Absicht von Dir dass 
ZeVs bei jedem Schleifendurchlauf um 1 vermindert wird ???

Diese Dinge bekommst Du mit MPLAB-Sim locker in den Griff, versuch es 
einfach mal!

Ist Dir bekannt dass im Menü "Debugger" eine Stoppuhr vorhanden ist? 
Allerdings muss dazu wie von mir schon beschrieben der MPLAB-Simulator 
aktiviert sein.
Dann setzt Du im Simulator einfach einen Haltpunkt, ab welchem die Zeit 
bzw. Zyklenzahl gemessen werden soll und dann noch einen Haltepunkt an 
dem die Zeitmessung endet.
Haltepunkt 1 - Stopwatch auf Null setzen
Haltepunkt 2 - Stoppuhr ablesen

Wie schon von W.S. erwähnt ist es auf Dauer von Vorteil bei Befehlen 
welche das Ergebnis im WREG bzw. im File ablegen, nicht die 0 oder 1 zu 
verwenden sondern eindeutig:
       movf    PORTB,W        ;W wie WREG (NICHT: PORTB,0
       decfst  Variabel,F     ;F wie File (NICHT: Variable,1)
Das macht Dein Programm auch für andere besser lesbar.

Übrigens: Dein Programm kann wesentlich vereinfacht werden. Ohne zu 
schwindeln, ohne faule Tricks: Bei mir hat "Main" gerade mal 12 
Codezeilen und schaltet eine LED nach der anderen im 2 Sekundentakt zu. 
Zusätzlich ist nur noch die Delay-Routine vorhanden. Wenn Du nicht 
weiterkommsen solltest, lasse ich Dir (auf Anfrage) das ASM-File gerne 
zukommen.

mfG GroberKlotz

von W.S. (Gast)


Lesenswert?

Ottmar K. schrieb:
> prinzipiell stimme ich Dir ja zu, aber..

warum so gereizt?

Wenn's einen interessiert, ist es gut, wenn nicht dann ist es auch gut. 
Von Anpreisen kann wohl keine Rede sein, wohl aber davon, daß meine 
Intimkenntnisse des Microchip-Assemblers eher steinalt sind - aus 
besagtem Grunde.

Würde mich aber trotzdem interessieren, ob es jemand geschafft hat, in 
MPLAB ein eigenes Übersetzungstool einzubauen - und wenn, wie.

W.S.

von Norbert P. (poff)


Lesenswert?

Hallo GroberKlotz,
ich habe das Programm vereinfachen können. Das Problem mit der Schleife 
ist aber noch immer vorhanden. Statt des Wertes den ich für die Schleife 
vorgebe, wird immer "irgendein" Wert in d3 geschrieben. Jetzt suche ich 
noch nach der Ursache.
Das arbeiten mit dem Simulator macht die Sache tatsächlich einfacher, 
selbst für einen Anfänger wie mich, für den Alles neu ist.
Über meine Fortschritte halte ich dich auf den laufenden.
Danke für deine Unterstützung, bis bald, Norbert

von GroberKlotz (Gast)


Lesenswert?

Norbert Potthoff schrieb:
> statt des Wertes den ich für die Schleife
> vorgebe, wird immer "irgendein" Wert in d3 geschrieben.

Na dann ist nur möglich dass beim Aufruf "CALL Delay100ms" nicht der von 
Dir gewollte Wert im WREG steht. Falls Du den Wert mittels einer 
Variablen
"movf ZeVs, W" ins Wreg geschrieben hast, dann hatte eben die Variable 
ZeVs den falschen Wert!

   movf ZeVs,W      ;Wert von ZeVs?
   CALL Delay100ms
   .....

   Delay100ms
   movwf d3         ;Wert von WREG?
   .....
   RETURN

mfG GroberKlotz

von Norbert P. (poff)


Angehängte Dateien:

Lesenswert?

Hallo GroberKlotz,
12 ??????????????
Nachdem ich das Programm "vereinfacht" und den Fehler für die falsche 
Berechnung der Zeit gefunden habe, läuft es mit 24 Befehlen in "Main".
Wäre schön, wenn du mir deine Assembler-Datei zukommen lassen würdest, 
es interessiert mich ja doch, wie du die Aufgabe lösen konntest.

Das nächste Übungsprojekt wird das Abfragen von Eingängen, um z.B. auf 
Taster reagieren zu können. Z.B. die Zeit für die Zeitschleife mit Plus- 
und Minus-Tasten zu ändern, oder und ein Abschalten der Leds in 
umgekehrter Reihenfolge zu realisieren.

Schöne Grüße, Norbert

von GroberKlotz (Gast)


Angehängte Dateien:

Lesenswert?

Hallo Norbert,
hier die Auflösung!
mfG GroberKlotz

von Norbert P. (poff)


Angehängte Dateien:

Lesenswert?

... oder so! :-)))
Danke für diese Lösung.
Ich habe in der Zwischenzeit weiter "programmiert" und ausprobiert.
Jetzt habe ich es geschafft, per Taster an RA0 eine LED an RB0 ein- und 
auszuschalten. (siehe ASM-Datei)
Dazu habe ich zum Entprellen eine Zeitschleife eingebaut. Nachdem ich 
versucht habe (und das auch erstmal wieder verworfen), die Dauer des 
Tastendrucks in das Programm einfließen zu lassen, kamen mir Zweifel 
auf, ob das der richtige Weg ist.
Bei meinen Versuchen wurde das Programm immer länger und größer, nur um 
die Schaltzustände der Tasten zu überwachen und auszuwerten. Während 
dessen "steht" das eigentliche Programm (z.B.: Taste 2 Sekunden drücken, 
dann springe zu...). Das kann nicht richtig sein.
In diesem Forum und auch auf anderen Seiten, liest man, dass man das 
Auswerten von Tasterzuständen mit Hilfe eines Timers und Interrupt lösen 
sollte. Ist das der richtige Weg? Wird während dessen das eigentliche 
Programm weiter ausgeführt?
Schöne Grüße, Norbert

von Ottmar K. (wil1)


Lesenswert?

Hallo Norbert

Zum Ein- und Ausschalten einer LED per Taster ist es wohl ausreichend 
die Entprellung mittels einer Zeitschleife vorzunehmen. Sollen aber auch 
andere Funktionen parallel ausgeführt werden geht das so nicht.

Leider ist die MCU (MicroController Unit) in der Zeitschleife gefangen 
und kann bis zu deren Ende keine anderen Aufgaben erfüllen. Nimm mal an, 
dass Du eine Uhr programmiert hast. Dann möchtest Du aus irgendwelchen 
Gründen per Tastendruck an einem Pin ein LED einschalten, oder eine 
externe zeit stoppen (kann ja auch noch was anderes sein).

Während der Zeitschleife wird Deine Uhr nicht mehr weitergestellt. Nach 
dem Tastendruck der ja z.B. beliebig lange dauern kann, wird die Uhr 
nachgehen, denn sie wurde ja nicht mehr weiter gestellt.

Es gibt diese Möglichkeiten:
Interrupt (Kapitel 14.5 Datenblatt)
Tasterabfrage per Interrupt, dessen Zeittakt man festlegen kann. Z.B. 
100ms Die ISR (Interrupt-Service- Routine) stellt die Uhr während z.B. 
jedem 10. Interruptdurchlauf um 1 Sekunde weiter. Alle 1/10 Sekunden 
werden die Tasten abgefragt. Falls eine Taste gedrückt ist, setzt man 
ein Flag und verarbeitet dieses Flag im Hauptprogramm weiter. Dabei 
zählt man auch einen Zähler hoch, der z.B. jede 1/10s incrementiert. 
Dabei frägt man den Zustand des Tasters ab und erst wenn z.B. 5x 
hintereinander der gleiche Tasterzustand erkannt wurde, wird die Aktion 
welche der Taster auslösen soll ausgeführt.

Dazu solltest Du Dir mal im Datenblatt das Kapitel zum Interrupt 
durchlesen und mit Interrupts zu experimentieren beginnen. Wenn es 
klemmt kannst Du Dir ja hier Rat holen.

Compare (Kapitel 9, Datenblatt)
Der 16F628 hat ein Compare-Modul. Da legst Du mit einem Register fest, 
bei welchem Zählerstand der Timer 1 ein Ereignis auslösen soll. Dies 
wird z.B. durch den Zustand des Flags "CCP1IF"  im  Register PIR1 
angezeigt. Dann kannst Du z.B. die Sub "LED einschalten" so abfragen:

Main
...irgendwelcher code
btfsc  PIR1,CCP1IF
 Call LED_einschalten
...irgendwelcher code
GOTO Main

Jetzt wird nur dann die LED eingeschaltet wenn die durch den Timer 1 
vorgegebene Zeit abgelaufen ist und das Flag CCPIF den zustand "1" 
eingenommen hat.
So, dass müsste mal fürs erste reichen.

Ist ein interessantes Thema und Du musst Dich halt einarbeiten, Im 
Internet gibt es so wie hier im Forum jede Menge Informationen.

mfG Ottmar

von Norbert P. (poff)


Lesenswert?

Danke Ottmar,
Mikrocontroller insgesamt ist ein sehr interessantes Thema. Mir macht es 
jedenfalls Spaß, besonders jetzt wo ich hin und wieder kleine 
Erfolgserlebnisse habe.
Ich versuche mich jetzt mal an den Interrupts und Timern.
Das von mir ausgedruckte Datenblatt des PIC16F628 sieht schon ziemlich 
gebraucht aus, auch das griffbereit liegende English-Deutsch-Wörterbuch. 
Ist schon so lange her mit dem English ... :-)
Danke nochmal und bis bald, Norbert

von Ottmar K. (wil1)


Angehängte Dateien:

Lesenswert?

Hallo Norbert,
mein erstes Datenblatt des 16F628 habe ich mir auch ausgedruckt, 
zumindest die mich interessierenden Passagen. Insgesamt ist es aber zu 
aufwendig. Ich hoffe Du weißt dass man das Datenblatt in das 
Projektfenster von MPLAB ganz einfach per Drag and Drop als Link 
reinschieben - und von dort aus mit einfachem Mausklick öffnen kann? 
Dazu habe ich den unglaublich großen Adobe-PDF-Reader abgeschaftt und 
den kostenlosen Sumatra-PDF installiert 
[http://blog.kowalczyk.info/software/sumatrapdf/free-pdf-reader-de.html]. 
So lässt sich das Datenblatt im PDF-Reader öffnen und wenn ich nach 
einem Begriff im Datenblatt suche, hilft das Suchen-Fenster im Reader, 
bzw. die Indexspalte rasch weiter.

Aus meinem Code-Vorrat habe ich Dir eine Interrupt-Routine zur 
Zeitmessung und Tastenabfrage beigefügt. Schau die Code-Schnipsel an, 
vielleicht verkürzen diese Deinen Lernprozess.

mfG Ottmar

von Norbert P. (poff)


Lesenswert?

Ottmar K. schrieb:
> Ich hoffe Du weißt dass man das Datenblatt in das
> Projektfenster von MPLAB ganz einfach per Drag and Drop als Link
> reinschieben - und von dort aus mit einfachem Mausklick öffnen kann?
> mfG Ottmar

Hallo Ottmar,
jetzt ja. :-) Ich nutze den PDF-XChange-Viewer. Klappt damit auch sehr 
gut. Hab es gerade ausprobiert. Ich habe aber lieber was zum Blättern in 
der Hand.

Vielen, vielen Dank für die Hilfe und die Tips und natürlich für die 
Interrupt-Routine. :-)))
Schöne Grüße, Norbert

von Ottmar K. (wil1)


Lesenswert?

Prima, wenn ich Dir ein wenig weiterhelfen konnte :-)!
Noch was: in der ISR hat sich da doch eine Zeile heimlich davon gemacht:

FALSCH:
  movlw  d'250'            ;Zähler wieder auf 250 setzen
  call    Uhr_Intern       ;Interne Uhr 1 Sekunde weiterschalten

RICHTIG:
  movlw  d'250'            ;Zähler wieder auf 250 setzen
  movwf   cnt4ms           ;und wieder bereit zum herunterzählen
  call    Uhr_Intern       ;Interne Uhr 1 Sekunde weiterschalten

mfG Ottmar

von Norbert P. (poff)


Angehängte Dateien:

Lesenswert?

Guten Morgen,
nach einer langen PIC-Programmier-Pause, habe ich hoffentlich nur ein 
kleines Problem. Ich vermute, das ich irgendetwas übersehen habe.
Ich habe eine kleine Schaltung mit einem PIC16F628A als SMD, um  das 
Programmieren in einer Schaltung (ICSP) und den internen Oscilator 
auszubrobieren. Die Aufgabe soll sein, das nach einem Reset ein Ausgang 
RB0 für eine paar Sekunden einen MOS-FET durchschaltet. Das klappt so 
weit ganz gut. Nun gibt es folgenden Effekt:
Während der Reset-Taster gedrückt wird, läuft das Programm im PIC 
ungestört weiter. Es startet zwar nach Ablauf der Zeit erneut wenn der 
Reset-Taster gedrückt wird, aber eben nicht während das Programm läuft.
Ich nutze den internen Oscilator und habe alle Pins auf Ausgang 
gestellt, außer PIN RA5 für den Reset, der ja eh nur die Funktion eines 
Eingangs bekommen kann.
Was habe ich übersehen?
Aus dem Datenblatt ist zu entnehmen, das der PIC sofort stoppt, wenn 
Reset an RA5 ausgelöst wird und solange der Taster gedrückt wird. So 
kenne ich das auch von meinen anderen Programmier-Versuchen mit externen 
Oscilator.
Schöne Grüße, Norbert

von Ottmar K. (wil1)


Lesenswert?

Hallo Norbert,
...so trifft man sich wieder :-). Schau mal in das Datenblatt des 
16F628, S.99. Dort ist ein Blockschaltbild zum RESET. Verfolge den Weg 
der RESET-Leitung und Du wirst sehen, dass diese an einem RS-Flip-Flop 
endet. Das bedeutet, egal wie lange Du auf dem Resettaster bleibst, beim 
ersten Tastendruck(Low-Inpuls) am Reseteingang, löst das FlipFlop den 
internen Chip-Reset aus.
Meines Wissens ist das RS-Flip-Flop mit dominantem Rücksetzeingang 
versehen. Der nächste Oszillatorimpuls des On-Chip-Oszillators setzt den 
internen Chip-Reset wieder zurück. Das Spielchen hält wohl so lange an, 
wie Du den Resettaster drückst.

Dein Verfahren, den PIC per Reset zu steuern ist gelinde gesagt 
unüblich. Lass doch den PIC durchlaufen:
1. Tastendruck - wird der FET durchgeschaltet
2. FET wird eingeschaltet
3. Delay
4. FET wird abgeschaltet
5. Warten auf den nächsten Tastendruck
6. Tastendruck
7. Weiter bei 1.

mfG Ottmar

von Norbert P. (poff)


Lesenswert?

Hallo Ottmar,
vielen Dank für deine Geduld und die Info.
Das Programm habe ich auch für einen "richtigen" Taster geschrieben und 
es läuft auch.
Vielleicht habe ich mich nicht richtig ausgedrückt. Was ich schreiben 
wollte ist folgendes:
Der SMD-Pic P16F628A scheint sich in der gleichen Schaltung anders zu 
verhalten, wie sein "großer" Bruder in DIL-Bauweise.
Letzterer beendet sofort sein Programm sobald ich den Reset-Taster 
betätige, während der SMD-Baustein munter weiter tobt. Ist bei ihm 
regulär das Programm beendet, startet das Programm neu, läßt sich 
während des Ablaufs aber nicht von der Reset-Taste beeindrucken.
Ich habe für die SMD-Schaltung eine Platine geätzt, die DIL-Version auf 
einem Steckbrett zusammen getüddelt.
Beide Versionen funktionieren mit dem "richtigen" Taster einwandfrei, 
nur eben die Reset-Funktion ist eine andere, bzw. hat eine andere 
Wirkung.
Nachdem mir das mit der Reset-Funktion aufgefallen ist, habe ich das 
Programm geändert und frage mich, ob die SMD-Version sich anders verhält 
oder ich irgendetwas übersehen habe, oder ich bei ICSP im Brenner noch 
irgendwo was umstellen muss - oder beides ;-)
Ich suche weiter...

von Ottmar K. (wil1)


Lesenswert?

Das heißt also dass der PIC auf den Resettaster gar nicht reagiert?

Dann bleiben ja nur diese Möglichkeiten:
a) Fehler auf der Platine
b) Configword fehlerhaft (_MCLRE_OFF ist aktiviert)
c) Fehlerhafter Anschluss RA5  (Pull Up nach +5V evtl. C ca. 100nF nach 
GND??


Ansonsten solltest du diese Frage mal im microchip-forum stellen.

mfG Ottmar

von Norbert P. (poff)


Lesenswert?

Eine Funktion hat der Resettaster. Nach Ablauf des Programmes wird das 
Programm gestartet, sobald ich die Resettaste betätigt habe. Es startet 
auch dann, wenn ich die Taste gedrückt halte.

- Configword MCLRE_ON ist im Programm eingetragen
- Pull-Up-Widerstand ist vorhanden und auch von Pin RA5 gegen UB meßbar
  (RA5 wird auch bei Betätigung des Taster auf Masse gezogen)
- Im Platinen-Layout konnte ich keinen Fehler feststellen. Ich fertige 
ein komplett neues an und probiere es dann nochmal.
Der einzige für mich erkennbare Unterschied zwischen Steckbrett und 
SMD-Platine ist der, dass ich auf dem Steckbrett einen BC546 und auf der 
SMD-Platine einen MOS-FET als Schalter nutze.

Ich melde mich sobald ich herausbekommen habe, woran es liegt, bzw. lag.

Danke für deine Hilfe!
Schönen Abend noch, Norbert

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.