Forum: Mikrocontroller und Digitale Elektronik µC PIC18F45K22/interner Oszillator/Genauigkeit


von Da Mo (Gast)


Lesenswert?

Ich habe ein kleines Programm für den µC PIC18F45K22 geschrieben, um die 
Genauigkeit des internen Oszillator zu testen. Das Ziel waren 8 
blinkende Leuchtdioden auf dem PORTC, mit einer Leucht- und Dunkelzeit 
von 1s. Laut den Berechnungen, müsste dies auch funktionieren, aber die 
Messung mit dem Oszilloskop ergab jedoch 1,040s.

Liegt der Fehler an meinem Programm oder an der Ungenauigkeit des 
internen Oszillator?

Vielen Dank!
1
int counter=0;
2
3
void init()
4
{
5
 /*Oscillator*/
6
 OSCCON.SCS0=1;
7
 OSCCON.SCS1=1;
8
 OSCCON.OSTS=0;
9
 OSCCON.IRCF0=1;
10
 OSCCON.IRCF1=1;
11
 OSCCON.IRCF2=0;
12
 /*Timer2*/
13
 T2CON.T2CKPS0=0;
14
 T2CON.T2CKPS0=0;
15
 T2CON.TMR2ON=1;
16
 T2CON.T2OUTPS0=0;
17
 T2CON.T2OUTPS1=0;
18
 T2CON.T2OUTPS2=0;
19
 T2CON.T2OUTPS3=0;
20
 PR2=0xFA;
21
 /*Interrupt*/
22
 INTCON.GIE=1;
23
 INTCON.PEIE=1;
24
 PIE1.TMR2IE=1;
25
 /*Port C*/
26
 TRISC=0x00;
27
 LATC=0x00;
28
}
29
30
void interrupt()
31
{
32
  if(PIR1.TMR2IF==1)
33
  {
34
   counter++;
35
   PIR1.TMR2IF=0;
36
   TMR2=0;
37
  }
38
}
39
40
void main()
41
{
42
 init();
43
  do
44
 {
45
  if(counter==1000) //Eingabe der Leucht- und Dunkelzeit in ms
46
  {
47
   LATC=~LATC;
48
   counter=0;
49
  }
50
 }
51
 while(1);
52
}

von Chris (Gast)


Lesenswert?

Du hast zwei Fehlerquellen, eine in deinem Kopf, und die andere in der
Interruptroutine, bzw ist auch case 1).

von Da Mo (Gast)


Lesenswert?

Hallo Chris,

ich kann deinen Worten leider nicht folgen!?

von Chris (Gast)


Lesenswert?

Ich nehme an, du hast den Timer auf 1024µS eingestellt.
1024 * 1000 = 1.024 S. Da du den Timer aber auf 0 stellst TMR2=0 in der
Interrupt, neme ich mal an, daß das auch wieder ca 16 µS sind, also ca
16ms + 1024ms = 1030ms.  Anstelle von 16µS können das aber auch 26µS 
sein,
oder aber auch die Ungenauigkeit des Osc. Man braucht da schon ein 
Glaskugel
dafür. Nimm lieber sowas, 
http://www.piclist.com/techref/piclist/codegen/delay.htm , aber poste 
deinen Code sowie die Zeitrechnung.

von Anja (Gast)


Lesenswert?

Da Mo schrieb:
> Liegt der Fehler an meinem Programm

Da Mo schrieb:
> PR2=0xFA;

das sind 251 Takte (und nicht 250) bis zum Überlauf!!!

Gruß Anja

von Anja (Gast)


Lesenswert?

Da Mo schrieb:
> TMR2=0;

das darf natürlich auch nicht sein. Der Zähler könnte ja schon weiter 
gezählt haben.
Außerdem ist die Abfrage im Hauptprogramm "counter==1000" auch 
gefährlich.
Was machst Du wenn deine Interruptroutine den Zähler schon auf 1001 
gesetzt hat?
Ich würde das Handling des Counters komplett in die Interruptroutine 
legen und ggf. ein Flag setzen um die "Sekundentask" abzuarbeiten.

Gruß Anja

von usuru (Gast)


Lesenswert?

stell den internen Oscillator auf 250 kHz (Datenblatt ab S.27), mach 
Deinen Flankenwechsel und füge so viele NOPs an, um eine gut messbare 
Zeit zu bekommen. Alle Befehle (in Assembler) benötigen 1 Takt, mit 
Ausnahme des GOTO
1
loop:
2
   BSF LATC, 0
3
   BCF LATC, 0
4
   NOP
5
   NOP
6
   NOP
7
   NOP
8
   NOP
9
   NOP
10
   GOTO loop

benötigt 10 Takte, bei 250 kHz also 40 µsec, Du hast dann also 25 kHz am 
Ausgang, das kannst Du leicht messen.

Erfahrungsgemäss ist die Genauigkeit der internen Oscillatoren bei den 
PICs um 1% (siehe auch Datenblatt ab S.520), man kann den Oscillator bei 
vielen PICs aber mit dem Register OSCTUNE trimmen.

von Chris (Gast)


Lesenswert?

Ein Programm dafür könnte so aussehen , WDT ausgeschaltet und
clk von 4Mhz angenommen. Speicher für RAM A1 , A2, A3 zuweisen.

#define LED LATC,0

    BANKSEL LATC
    clrf  LATC
    BANKSEL TRISC
    clrf  TRISC
    BANKSEL LATC
main:
    movlw 1          ; init delay
loop:
    call DELAY_1S_W  ; 99997 clk = 1 Sek
    ; call DELAY_1S_8 ; für 8Mhz clk semicolon entfernen
    bsf  LED         ;     1 clk +
    call DELAY_1S_   ; 99998 clk +
    ; call DELAY_1S_8 ; für 8Mhz clk semicolon entfernen
    movlw .46        ;     1 clk = 1 Sek
    bcf  LED         ;     1 clk +
    goto loop        ;     2 clk +


DELAY_1S_8
    NOP
DELAY_1S   ; 99999 Clock cycles
    NOP
DELAY_1S_  ; 99998 Clock cycles
    MOVLW    D'46'
DELAY_1S_W ;
    MOVWF    A3
DELAY_1S_2
    MOVLW    D'189'
    MOVWF    A2
DELAY_1S_1
    MOVLW    D'37'
    MOVWF    A1
DELAY_1S_0
    DECFSZ   A1,F
    GOTO    DELAY_1S_0
    DECFSZ  A2,F
    GOTO    DELAY_1S_1
    DECFSZ  A3, F
    GOTO    DELAY_1S_2
    RETURN

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.