Sida 1 av 1

Frekvens för PIC med intern oscillator?

Postat: 27 februari 2006, 08:46:10
av PHermansson
Har kopplat upp en PIC12F675 utan kristall, kör enbart med den interna 4MHz oscillatorn. En kod jag skrivit använder Timer1 för att skapa en interrupt 2 ggr per sekund och blinka en led, och i simulatorn tar det 499997 uS mellan interrupten. När jag sedan kör koden i den riktiga kretsen är frekvensen relativt långt ifrån 1Hz, när jag jämför ledblinkandet med väggklockans tick verkar det som dioden blinkar kanske 11-12 ggr per 10 sekunder.
Programmeraren tar hänsyn till Oscal.
Visst ska man använda kristall till tidskritiska applikationer, men ska diffen i frekvens verkligen vara så här stor?

Postat: 27 februari 2006, 08:54:36
av Icecap
Avvikelsen som kan finnas står i databladet.

Vad jag vet är PIC16F628A, den har ±1% på den inbyggda 4MHz'en.

Postat: 27 februari 2006, 09:04:42
av matseng
Detta under förutsättning att det fabrikskalibrarade värdet finns kvar intakt i picen.

Prova att läsa ut det och se om det är 00 eller FF. Då kan man ju misstänka att värdet har blivit överskrivet nån gång.

Annars så du väl kallibrera den själv. Det finns en appnot som beskriver en enkel autokallibrerare.

Postat: 27 februari 2006, 10:01:50
av PHermansson
Tack för snabba svar! Jag har nu läst appnoten (http://ww1.microchip.com/downloads/en/d ... 31002a.pdf) och testat tipsen där. Har dock inte haft möjlighet att kolla frekvensen.
Jag har läst ut Osccal från Pic'en, värdet blir 84 så jag tror det är korrekt. Jag testade då att sätta Osccal till 0 och CALSLW till 1 vilket ska ge lägsta möjliga frekvens. Men det går fortfarande för fort?! Får nog försöka kolla oscillatorfrekvensen...

Postat: 27 februari 2006, 10:49:25
av sodjan
11-12 gånger på 10 sek, är ju 10-20 % för mycket, vilket ser konstigt ut.
Svårt att säga, kanske programbug eller felinställning i MPSIM !?

Postat: 27 februari 2006, 12:08:30
av PHermansson
MPSim säger 500.004000 mS och PIC Simulator IDE säger 499997 uS. Själv säger jag att 10 blinkningar tar ca 9s. The search goes on...

Hmm... jag har 'preloadat' Timer1 med Tmr1L=E0 och Tmr1H=0B vilket ger ovanstående värden. Dessa värdet har jag tagit fram med trial'n'error, vilket här verkar bli error. I detta fall räknar Tmr1L 31 steg och Tmr1H 244 steg, vilket med en prescaler på 8 ger 60512 steg.
500000uS / 8 ger 62500. Om jag då preloadar Tmr1H med 03 istället bör tiden bli mer korrekt. Men det går fortfarande för fort!
Tror jag har någon form av hjärnsläpp nu, får nog göra något annat en stund...

Postat: 27 februari 2006, 12:41:48
av sodjan
Posta ett "test-case" som uppvisar problemet, så får vi se...

Postat: 27 februari 2006, 13:15:22
av PHermansson
test-case??

Postat: 27 februari 2006, 13:52:10
av sodjan
Ja, en kod-snutt som visar problemet, och som (t.ex) jag kan testa med...

Postat: 27 februari 2006, 14:12:24
av PHermansson
aha ok då är jag med :)

Kod: Markera allt

	list p=12f675
	include "p12f675.inc"

 __config B'110010100'

START_USER_MEMORY  EQU 0x20 
w_temp             EQU START_USER_MEMORY    ; for isr context saving
status_temp        EQU START_USER_MEMORY+1  ; for isr context saving

ledstate		equ	0x22

;----------------

    org    0x00
	goto main

; Interrupt handling
    org    0x04

push     movwf w_temp            ;save w & status
            swapf STATUS,W
            movwf status_temp
isr        
           bcf PIR1, TMR1IF ; Clear the flag bit after the interrupt
           ;Toggle led
           movlw	0x10
	   xorwf	ledstate,1
	   movf	ledstate,0
           movwf	GPIO
			
timerload
	   ;Preload timer.
	   movlw 	0xE0
	   movwf	TMR1L
	   ;Preload timer
           movlw 	0x03
           movwf	TMR1H

pop       swapf status_temp,W        ; restore w & status
            movwf STATUS
            swapf w_temp, F
            swapf w_temp, W
            retfie
main:

	clrf GPIO 
	movlw 0x7 
	movwf CMCON ; disable comparator 
	bsf STATUS, RP0 ;Bank1 
	movlw 0x0 
	movwf TRISIO ; All pins outputs 
	bcf STATUS, RP0 ;Bank0

	;Adjust IntOsc
	movlw	b'00000100' 
	movwf	OSCCAL

	;Setup Timer1
	BCF	T1CON, TMR1GE
	BSF	T1CON, T1CKPS1	;Prescaler
	BSF	T1CON, T1CKPS0
	BCF	T1CON, T1OSCEN	;LpOsc
	BCF	T1CON, NOT_T1SYNC
	BCF	T1CON, TMR1CS	;ClockSource

	bcf PIR1, TMR1IF ; Clear the flag bit 

	bsf STATUS,RP0 ;Bank 1
	bsf PIE1, TMR1IE ; Enable Tmr1 interrupt
	BCF STATUS, RP0 ; Bank0
    
	bsf INTCON, PEIE ; 
        bsf INTCON, GIE  ; Enable all interrupts

	;Preload timer
	movlw 	0xE0
	movwf	TMR1L
	;Preload timer
	movlw	0x03
	movwf	TMR1H

	BSF	T1CON, TMR1ON	;Start timer

infinite:
	goto infinite
	
	end

Postat: 27 februari 2006, 16:37:08
av sodjan
Nedanstående ger (nästan) 1 Hz i MPSIM och 1.011 Hz på oscilloskopet.
Inga större ändringar.
- Plockade bort "push/pop" eftersom det ändå inte finns något att spara.
- Ändrade till ext-MCLR för att kunna köra med Wisp628. (Använd gärna de riktiga CONFIG symbolerna från INC filern !)
- Nya värden för tmr1-preload (tmr1H_pl och tmr1L_pl).
- La dit korrekt hantering av OSCCAL.

Kod: Markera allt

   list p=12f675
   include "p12f675.inc"

 __config h'01B4'

ledstate      equ   0x22

tmr1H_pl = h'0B'
tmr1L_pl = h'DE'

;----------------

   org    0x00
   goto main

; Interrupt handling
    org    0x04

isr       
   ;Toggle led
   movlw   0x10
   xorwf   ledstate,1
   movf    ledstate,0
   movwf   GPIO
         
timerload
   ;Preload timer.
   movlw   tmr1L_pl
   movwf   TMR1L
   movlw   tmr1H_pl
   movwf   TMR1H

   bcf PIR1, TMR1IF
   retfie

main:

   clrf GPIO
   movlw 0x7
   movwf CMCON ; disable comparator
   bsf STATUS, RP0 ;Bank1
   movlw 0x0
   movwf TRISIO ; All pins outputs
   bcf STATUS, RP0 ;Bank0

   ;Adjust IntOsc
   bsf STATUS, RP0 ;Bank 1
   call 3FFh ;Get the cal value
   movwf OSCCAL ;Calibrate
   bcf STATUS, RP0 ;Bank 0


   ;Setup Timer1
   BCF   T1CON, TMR1GE
   BSF   T1CON, T1CKPS1   ;Prescaler
   BSF   T1CON, T1CKPS0
   BCF   T1CON, T1OSCEN   ;LpOsc
   BCF   T1CON, NOT_T1SYNC
   BCF   T1CON, TMR1CS   ;ClockSource

   bcf PIR1, TMR1IF ; Clear the flag bit

   bsf STATUS,RP0 ;Bank 1
   bsf PIE1, TMR1IE ; Enable Tmr1 interrupt
   BCF STATUS, RP0 ; Bank0
   
   bsf INTCON, PEIE ;
   bsf INTCON, GIE  ; Enable all interrupts

   ;Preload timer
   movlw   tmr1L_pl
   movwf   TMR1L
   movlw   tmr1H_pl
   movwf   TMR1H

   BSF   T1CON, TMR1ON   ;Start timer

infinite:
   goto infinite
   
   end 

Postat: 27 februari 2006, 23:24:28
av PHermansson
Tackar! Jag testade din kod och det ser ut att fungera bättre :)
Jag lade till en räknare för att kunna räkna en minut, och har upprepade gånger mätt perioden till 59,4 sekunder. 1,011Hz ger en tid på 0,989s, och tar man detta gånger 60 blir det 59,35. Trots att jag inte har något oscilloskop tillgängligt kan jag konstatera att din kod fungerar. Varför är ju en annan fråga...
Tack för hjälpen!

Postat: 28 februari 2006, 10:06:20
av sodjan
Fint.
Måste sticka ut på stan en sväng, men ska titta en extra gång på din kod senare så får vi se om jag ser något...

EDIT: När jag läser om ditt senaste inlägg, så ser jag att du kanske
menade varför *min* kod fungerar !? Ja ja, *det* behöver jag inte kolla
närmare på... :-)