µC PIC18F45K22/interner Oszillator/Genauigkeit

Gast #2646654
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
}
Gast #2646691
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.
Gast #2646725
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
Gast #2647135
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.
Gast #2647660
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

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren