Forum: Mikrocontroller und Digitale Elektronik PWM Signal mit PIC18F lesen


von Stefan  . (phreakshow)


Lesenswert?

Hi zusammen,

folgendes Problem:

Ich möchte mit einem PIC18F einen SMT160-30 Temperatursensor einlesen. 
Der SMT deswegen, weil der ein PWM-Signal schickt. Die Auswertung und 
vor allem das Einlesen der Rohwerte kostet kaum Rechenzeit, weil das per 
Interrupt "nebenbei" passiert ohne dass ich den Prozessor zwischendurch 
"anhalten" müsste, wie beispielsweise bei einem Dallas.

Wie dem auch sei, ich krieg es nicht zum Laufen. Meine Vorgehensweise:

Der PIC18 hat einen 16MHz Quarz, PLL ist aktiv, was 64MHz ergibt. Als 
erstes initialisiere ich Timer und Capture:
1
OpenTimer3(TIMER_INT_OFF & T3_SOURCE_FOSC & T3_PS_1_2 & T3_OSC1EN_OFF, TIMER_GATE_OFF);
2
OpenCapture5(CAP_EVERY_RISE_EDGE & CAPTURE_INT_ON & CCP_5_SEL_TMR34);

Der Timer3 läuft alle 4,096ms über, dh jeder Zählschritt braucht 62,5ns.
Im Moment gebe ich zum Testen ein 1kHz Rechtecksignal auf den Pin, dh 
jede AN-Phase dauert 500µs.
Ich sehe dass der Capture-Interrupt richtig konfiguriert ist, denn er 
erkennt sowohl die fallende als auch die steigende Flanke.

Mein Interrupt sieht so aus:
1
if (PIR4bits.CCP5IF && PIE4bits.CCP5IE)
2
{
3
  gCCP[0] = 1;
4
  if (CCP5CONbits.CCP5M == 0b0101)
5
  {
6
    CCP5CONbits.CCP5M = 0b0110;
7
  
8
    gCCP[1] = CCPR5;
9
    gCCP[0] = 2;
10
    }
11
  
12
  else if (CCP5CONbits.CCP5M == 0b0110)
13
  {
14
    CCP5CONbits.CCP5M = 0b0101;
15
    
16
    gCCP[2] = CCPR5;
17
    gCCP[0] = 3;
18
  }
19
  
20
  PIR4bits.CCP5IF = 0;
21
}

gCCP gebe ich mir per CAN in der Hauptschleife aus. Byte0 zeigt sowohl 2 
als auch 3, dh er erkennt beide Flanken.
Der Wert für CCPR5 ist aber konstant, und immer 0x4E43. Das wäre ja 
dezimal 20035, was einer Zeit von 1,25ms entspricht.
Vor allem ist der Wert konstant, egal ob ich mit 1kHz Test-Rechteck 
reinschieße oder mit dem SMT160 selbst, der eine AN-Zeit von ungefähr 
133µs bei Raumtemperatur hat.

Ich hatte das zuerst mit direktem Zugriff auf die Timerregister 
versucht, das Ergebnis war das gleiche. Daher habe ich jetzt mal die 
Library-Funktionen verwendet.

Wie kann ich das jetzt am besten zum Laufen bringen? Das kann doch ned 
so schwer sein die Zeit zu messen, die zwischen den Flanken vergeht...

von Noch einer (Gast)


Lesenswert?

Die Timer Register ändern sich auch nicht? Hat das OpenTimer3 das TMR3ON 
vergessen?

Die meisten Microchip Datenblätter haben am Ende eines Kapitels eine 
Übersicht, welche Register Auswirkungen auf das Modul haben. Wenn es 
fehlt - ein ähnliches Datenblatt runterladen.

CCP5M = 0b0110 sieht seltsam aus. "Capture mode: Every 4th rising edge"

von Stefan  . (phreakshow)


Lesenswert?

Ach Mist, du hast natürlich völlig recht. Bei 0b0110 bin ich in der 
Zeile verrutscht. TMR3ON hatte ich auch mal manuell gesetzt, das hat 
keinen Unterschied gemacht.
Direkten Zugriff auf den Zählerstand des Timer hatte ich zwischendurch 
mal getestet, der hat auch brav gezuckt (um ein paar Zähler hin oder 
her), so wie man das erwartet, Jitter sei dank.
Aber aus dem angezeigten Wert konnte ich auf keine AN-Zeit rechnen, die 
sinnvoll war. Mit dem falschen Wert für das CCP5M ist das natürlich auch 
kein Wunder... morgen direkt mal testen, danke.

von Stefan  . (phreakshow)


Lesenswert?

Nach Korrektur des doofen Fehler im CCP5M krieg ich jetzt folgendes:
1
OpenTimer3(TIMER_INT_OFF & T3_SOURCE_FOSC & T3_PS_1_8 & T3_SYNC_EXT_OFF & T3_OSC1EN_OFF, TIMER_GATE_OFF);

Ich habe hier den Teiler noch auf acht gestellt, sonst blieb in der 
Intitialisierung alles gleich.
1
if (PIR4bits.CCP5IF && PIE4bits.CCP5IE)
2
{
3
  gCCP[0] = 1;
4
  if (CCP5CONbits.CCP5M == 0b0101)    //every rising edge
5
  {
6
    gCCP[0] = 2;
7
          
8
    TMR3H = 0;
9
    TMR3L = 0;
10
    
11
    CCP5CONbits.CCP5M = 0b0100;
12
  }
13
  
14
  else if (CCP5CONbits.CCP5M == 0b0100)  //every falling edge
15
  {
16
    gCCP[0] = 3;
17
    
18
    gCCP[1] = TMR3H;
19
    gCCP[2] = TMR3L;
20
    
21
    CCP5CONbits.CCP5M = 0b0101;
22
  }
23
  
24
  PIR4bits.CCP5IF = 0;
25
}

Steigende Flanke nullt den Zählerstand, fallende Flanke schreibt den 
neuen Stand raus. Auf dem CAN sehe ich ziemlich konstante 0x0091, mit 
leichtem Zucken auf 0x0090 und 0x0092. So wie ich es erwarten würde.

Aber wie passt 0x91 bzw dezimal 145 zu meinen Timer-Settings? Der Timer3 
müsste eigentlich mit 8,192ms bis zum Überlauf zählen, dh pro 
Zählschritt habe ich jetzt 125ns.

: Bearbeitet durch User
von Peter D. (peda)


Lesenswert?

Stefan M. schrieb:
> Steigende Flanke nullt den Zählerstand

Nö, das erfolgt erst Interruptlatenz + Epilog + einige Instruktionen 
später.

Beim Capture merkt man sich den vorherigen Stand und bildet die 
Differenz. Nur dann ist man Zyklusgenau.

von Stefan  . (phreakshow)


Lesenswert?

Ja, da hast du natürlich recht. Aber wenn ich beim Zugriff auf das CCP 
Register nur konstanten Unfug bekomme?
Ich hätte erwartet, dass ich mit dem aktuellen Code ungefähr im Bereich 
der richtigen Zeit lande, also irgendwas um 500µs.

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.