mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik PIC12F629 GPIO3 Problem


Autor: Matthias Laubnitz (mcl024)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Zusammnen,

ich arbeite zur Zeit mit einem PIC12F629. Hier habe ich ein Takt Signal 
(grün) an GPIO3 hängen. Meine IO_Pins sind folgendermaßen initialisiert:
void port_init(void)
{
    TRISIO  =  0b00101000; // Register for define the I/O Pins as Input or Output
}

meine Interrupt Init sieht so aus:
void Interrupt_Init(void)
{
  GIE    = 1;  // Global Interrupt Enable
  GPIE  = 1;  // Port Change Interrupt Enable
  IOC3  = 1;  // GPIO3 Interrupt on Change Enable
  GPIF  = 0;  // Interrupt on Change Bit cleared
}

Daraus sieht man das ich den GPIO3 als Interrupt on Change konfiguriert 
habe. Nun möchte ich bei jeder negativen Flanken des Takt-Signals in der 
ISR etwas tun. Dazu habe ich meine ISR folgendermaßen aufgebaut.
static void interrupt  clk_ISR(void)
{
  if(!TAKTSIGNAL && GPIF)
        {
             TRIG = !TRIG
             //etwas tun
             GPIF = 0;
        }
}

Hier schaue ich ob das Takt-Signal nach einsetzen des Interrupt == 0 
ist. Somit stelle ich fest ob es sich um eine negative Flanke handelt. 
Dann toggle ich erstmal einen Trigger (gelb).

Bei den ersten 11 negativen Flanken geht das auch gut, doch dann (rot 
gekennzeichnet) gehe ich bereits bei einer positiven Flanke in die 
if-Anweisung.

Woran kann das liegen?
Liegt das vielleicht an dem speziellen GPIO3.
Hat jemand Erfahrung.

Autor: Matthias Laubnitz (mcl024)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Die falsche Auswertung des Takt-Signals erfolgt nach längerer Analyse 
mit dem Oszi sehr unregelmäßig. Sobald ich die if-Anweisung wiederhole 
tritt der Fehler nicht mehr auf.
static void interrupt  clk_ISR(void)
{
  if(!TAKTSIGNAL && GPIF)
  {
      if(!TAKTSIGNAL && GPIF)
      {
          TRIG = !TRIG
          //etwas tun
           GPIF = 0;
       }
   }
}

Das kann doch nicht sein! Der Interrupt tritt ja erst bei einer Änderung 
des IO-Pins auf.

Autor: Matthias Laubnitz (mcl024)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hat noch keiner ne Idee oder ähnliche Erfahrungen gemacht?

Autor: Eschi (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
...naja, falls es am GPIO3 liegt könntest Du ja einen anderen Eingang 
probieren - falls möglich.
Wird der IRQ nicht auch von der pos. Fanke ausgelöst, aber das Flag dann 
nicht zurückgesetzt. Das Prg. also ständig zum im IRQ läuft? Probier mal 
das GPIF=0 aus der Klammer rauszunehmen. Das Setzen des Trig. Ausgangs 
erlärt es aber nicht.
Lt. Datasheet wird das GPIF auch durch ein erneutes Einlesen 
zurückgesetzt (kein Plan was Dein Programm sonst noch treibt).

Gruss Martin

Autor: Martin S. (drunkenmunky)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Was ist denn überhaupt TRIG? Ist das ein Ausgang?

Auf Seite 23 des Datenblattes steht, dass du zum Rücksetzen des 
Interruptflag den GPIO lesen oder schreiben MUSST. Das ist leider keine 
ODER-Verknüpfung im Datenblatt, sondern eine UND. Wenn dein TRIG 
direkt(!) ein Ausgang ist, sollte das eigentlich reichen. Sonst füge 
doch noch ein
GPIO;
bevor du das Flag zurücksetzt.

Hast du den IOC auch nur bei diesem einen Pin eingeschalten und bei 
sonst keinem?

Ein Tipp: Schau dir mal den 12F1822 an. Bei dem musst du den Port nicht 
extra lesen oder schreiben zum zurücksetzen. Und man kann für jeden Pin 
einstellen ob ein Interrupt bei der steigenden oder fallenden Flanke 
oder bei beiden ausgelöst werden soll. Und jeder Pin hat auch sein 
eigenes Interruptflag. Kostet nur 3 Cent mehr ;-)

Autor: Matthias Laubnitz (mcl024)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hey

Danke für die Antworten.

Also TRIG ist eine Ausgang (GPIO1). Sollte es am zurücksetzen des GPIF 
liegen sollte der Fehlerfall dann nicht immer auftreten? Der Fehler 
tritt total unregelmäßig auf.

Es ist nur Interrupt on Change an Pin 3 aktiviert (siehe Interrupt_Init)

Autor: Dani (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Dein Taktsignal sieht nicht wirklich regelmässig aus... Was ist denn das 
für eine Taktquelle? Kannst du mit Sicherheit ausschliessen dass die 
Taktquelle prellt?

Gruss Dani

Autor: Matthias Laubnitz (mcl024)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
ja das kann ich definitiv. Ich habe das Takt-Signal schon genau mit Oszi 
unter die Lupe genommen.
Das kann es nicht das Problem sein.

Autor: Martin S. (drunkenmunky)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hast du den IOC auch nur bei diesem einen Pin eingeschalten und bei
sonst keinem?

Sonst poste doch mal das ganze Programm, dann kann man auch besser 
helfen.

Autor: Uwe Nagel (ulegan)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Das solltest du umschreiben:
static void interrupt  clk_ISR(void)
{
  if(GPIF)
    {
      if(!TAKTSIGNAL)
        {
             TRIG = !TRIG
             //etwas tun
        }
      GPIF = 0;
    }
}
sonst wird nach einer steigenden Flanke das Interruptflag nicht 
gelöscht. Dann springt der Prozessor immer wieder in die 
Interruptroutine, bis irgendwann mal der Eingang 0 wird.
Erklären tut das den Effekt leider noch nicht...
Eigentlich sollte es den Prozessor nur weitgehend lahmlegen, während der 
Eingang 1 ist. Das könntest du testen, indem du im Hauptprogramm nur 
einen Ausgang toggelst. Das sollte während 1 am Eingang wesentlich 
ausgebremst werden.
Hier sieht es ja so aus, als würde im Interrupt für eine steigende 
Flanke noch eine 0 vom Port gelesen, oder das Signal prellt doch. Und 
das so kurz, dass in der Interruptroutine für die steigende Flanke schon 
wieder eine 0 gelesen wird, die nachfolgende steigende Flanke aber noch 
keinen neuen Interrupt auslösen kann. Sonst hättest du einen kurzen 
Impuls an der steigenden Flanke.

Autor: Michael L. (michaelx)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Matthias Laubnitz schrieb:
> ...
>
> ...
>   if(!TAKTSIGNAL && GPIF)
>   {
>       if(!TAKTSIGNAL && GPIF)
>       {
>           ...
> 
>
> Das kann doch nicht sein! ...

Durch die doppelte Prüfung wird wohl ein kurzes Prellen des Taktes 
ausgeblendet. An sonsten gilt was Uwe geschrieben hat. Interessant wäre 
auch, welche Frequenz dein Einganlssignal (Takt) hat, und mit welcher 
Taktfrequenz der PIC selbst läuft.

Autor: Matthias Laubnitz (mcl024)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@Martin S.
Es ist ein Interrupt on Change an Pin 3 aktiviert (siehe Interrupt_Init)

@Uwe Nagel
im Datenblatt auf Seite 23 steht:

The user, in the Interrupt Service Routine, can clear the
interrupt in the following manner:
a) Any read or write of GPIO. This will end the
mismatch condition.
b) Clear the flag bit GPIF.

nach dieser Ausage müßte es egal sein ob ich das GPIF Flag lösche, da 
ich es ja immer lese.

Ich habe jetzt bemerkt das es sich wohl tatsächlich um ein Timingproblem 
vom PIC handeln muss. Denn wenn ich die ISR so gestalte wie Uwe Nagel 
aber GPIF = 0 weg lasse:
static void interrupt  clk_ISR(void)
{
  if(GPIF)
    {
      if(!TAKTSIGNAL)
        {
             TRIG = !TRIG
             //etwas tun
        }
    }
}

tritt der Fehler nicht mehr auf, aber nur weil ich wieder durch die zwei 
if-Anweisungen ein Zeitvorteil erhalte. So meine Vermutung.

Autor: Matthias Laubnitz (mcl024)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Sorry die Ausage das es egal ist ob ich das GPIF Null setze oder den 
IO-Pin lese, wie ich es im Datenblatt verstanden habe nehme ich zurück. 
Dann muss ich das wohl falsch verstanden haben.

Aber wie Uwe Nagel schon gesagt hat ändert das nichts am eigentlichen 
Problem.

Autor: Matthias Laubnitz (mcl024)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich habe die ISR jetzt mal so geschrieben.
static void interrupt  clk_ISR(void)
{
  if(GPIF && !TAKTSIGNAL)
        {
             TRIG = !TRIG
             //etwas tun
             GPIF = 0;
        }
}

TAKTSIGNAL und GPIF getauscht. Es scheint zu funktionieren.

Autor: Martin S. (drunkenmunky)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Matthias Laubnitz schrieb:
>
> The user, in the Interrupt Service Routine, can clear the
> interrupt in the following manner:
> a) Any read or write of GPIO. This will end the
> mismatch condition.
> b) Clear the flag bit GPIF.
>
> nach dieser Ausage müßte es egal sein ob ich das GPIF Flag lösche, da
> ich es ja immer lese.

Das ist, wie schon gesagt, eine UND-Verknüpfung von a) und b). Also du 
musst schon beides machen.

Sonst versuche es doch mal so:
static void interrupt  clk_ISR(void)
{
  if( (GPIF != 0) && (TAKTSIGNAL == 0) )
        {
             TRIG ^= 1;
             //etwas tun
             GPIF = 0;
        }
}

Ist denke ich sicherer her von der Abfrage.

Was für einen Compiler benutzt du überhaupt? Welche Version?

Autor: Matthias Laubnitz (mcl024)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Jetzt habe ich es auch verstanden mit der UND-Verknüpfung.

So wie ich im Beitrag zuvor geschreiben habe funktioniert es. Es tritt 
kein Fehler mehr bei der Abfrage auf nur durch drehen der Abfragen.

Compiler: HI-TECH V9.8

allerding im Lite Mode

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.