PIC12F675 Oscillator Calibration

Find out how to setup your programmer's software and how to solve many common problems.

Moderator: phalanx

Old Frank
Posts: 13
Joined: Tue Sep 01, 2015 12:46 pm

PIC12F675 Oscillator Calibration

Post by Old Frank » Tue Sep 01, 2015 2:52 pm

I realise this problem has been well aired, but have not found a solution that works for me.
The OSCCAL calibration bits at top of memory are overwritten each time I load a program, in spite of starting my program with the manual's recommended code (page 54):
bsf STATUS,RP0
call 03FFh
movwf OSCCAL
bcf STATUS,RP0.
I've searched other forums and tried ORG 03FFh at the start of code (same result), but see no alternative to reading each chip to note the calib. bits then writing them into the program with movlw NNh.
I'm using a K150 with associated OSHONSOFT software on a Windows 7 machine. I've acted on the advice to get round the Windows 7 problem and, so far, I've only had successful simulations of LED flashing.
What obvious step am I missing, please?

User avatar
phalanx
Non-SFE Guru
Posts: 1947
Joined: Sun Nov 30, 2003 8:57 am
Location: Candia, NH

Re: PIC12F675 Oscillator Calibration

Post by phalanx » Wed Sep 02, 2015 7:47 am

Hi Frank,

From the factory the oscillator calibration value comes stored in the last program memory address which is 0x03FF for the PIC you are using. Because it's in program memory, the value is erased every time you erase the part which is necessary evil when you reprogram it. Because of this, Microchip's programming spec for the 12F675 requires the programming software to first read the value at 0x03FF, then erase the part, program the user code, then replace the saved calibration value. Microchip's IDE and programming tools account for this and preserve the value but because you are using a 3rd party IDE and programming equipment, I can't say for sure if they are actually doing this (it would appear that they are not).

I would dig through your programmer and IDE settings and see if there is anything related to programming calibration values. In Microchip's universe, there are specific settings in the programmer's configuration that allows you to overwrite the calibration value but this is not enabled by default since most people have no reason to change it.

Ultimately if you want to restore a value to that location, you would structure your program as follows:

Code: Select all

ORG	  0x03FF    ;Calibration value location
retlw	0x00		;this can be whatever value you want.

ORG	  0x00		;Reset Vector
goto	 Main		;Goto your main routine.
-Bill

Old Frank
Posts: 13
Joined: Tue Sep 01, 2015 12:46 pm

Re: PIC12F675 Oscillator Calibration

Post by Old Frank » Wed Sep 02, 2015 10:35 am

Thanks, Bill. On other forums, I've seen references to RETLW and ORG, but not as a detailed part of a program. I'll give it a try this evening.
I dabbled in assembler (6800) many years ago, but I don't remember oscillator calibration being an issue then. I might not have many brain cells left, but I'll make the blighters work as it seems to be good for the rest of me.
Thanks again.
Frank

User avatar
phalanx
Non-SFE Guru
Posts: 1947
Joined: Sun Nov 30, 2003 8:57 am
Location: Candia, NH

Re: PIC12F675 Oscillator Calibration

Post by phalanx » Wed Sep 02, 2015 10:59 am

No problem Frank. For some quick clarity, ORG is a directive that tells the linker where to locate the code that follows it. RETLW is an instruction run by the microcontroller which is used to return from a called subroutine with a literal value in the W register.

Small PIC devices like the 12F675 are often run using the built-in fast RC oscillator in order to save pins. Since it would be prohibitively expensive to produce the parts with highly accurate oscillators, there's an internal mechanism that lets you trim the speed up or down by a small amount. Microchip tests the part during production and writes the recommended offset value as a RETLW 0x?? instruction to the last program memory location in the PIC (0x03FF in your case). When your program first starts, you "CALL 0x03FF" which makes your program jump to that location where the value stored there is immediately returned in the W register. You then move that value into the OSCCAL register to complete the calibration.

Properly implemented programming environments will prevent you from overwriting the factory calibration value unless you fully intend to change it. Since you believe that it's been wiped out, you can experimentally try different values in the OSCCAL register and use a scope or logic analyzer to verify specific timing. If your program doesn't require a highly accurate time base (event based processing), you can leave it be and not bother with the calibration. If you do require accurate timing, I would recommend using an actual crystal.

-Bill

Old Frank
Posts: 13
Joined: Tue Sep 01, 2015 12:46 pm

Re: PIC12F675 Oscillator Calibration

Post by Old Frank » Wed Sep 02, 2015 1:43 pm

As I was aware of this problem, I read the top of memory in each of my PICs (10F, 12F and 16F types) and stuck a label on each with the NN from 34NNh. I then tried a simple LED flash program in the Oshonsoft simulator, which seems very good. Using a 12F675, I've repeated this with your code at the start and 3448h in the last location. Each time I load the HEX file, the last location is reset to 3FFFh and the calib. bits are sent to T1CON, OSCCAL remaining unchanged as 10h.
This doesn't bother me for my own little projects, but I want to do a cheap strobe (1Hz - 255Hz in two ranges) for next year's workshops at a couple of conferences for teachers and technicians. I'd have to program at least 60 PICs. I had one working in a PICAXE, written in a version of BASIC, but linearity was poor. Hence my wish to use a naked PIC. I also want to be able to do this sort of thing "from the ground up" and not rely on others' hidden software such as the Microchip Pickit stuff. I feel I'd understand it better.
Am I "wishing for the Moon - with jam on it"?
Many thanks again for your help, but if I'm becoming a pain in the left big toe, tell me.

Old Frank
Posts: 13
Joined: Tue Sep 01, 2015 12:46 pm

Re: PIC12F675 Oscillator Calibration

Post by Old Frank » Wed Sep 02, 2015 2:17 pm

I found this that I'd tried about a week ago.
org 03FFh
movwf OSCCAL
org 0000h
It made sense to me, but it didn't make enough sense to the simulator to put the calib. bits in OSCCAL, even when I'd changed top location back to 3448h after "Load" had caused a reset to 3FFFh.
I'll study the Oshonsoft simulator manual more thoroughly, as you advise. Half my trouble is having to learn and understand all the terminology before I can understand the rest of the text. I've searched my local colleges for PIC programming courses, but they all "scratch the surface" as part of much more extensive courses. Still, it gives the grey cells exercise.
Off to bed.
Frank

User avatar
phalanx
Non-SFE Guru
Posts: 1947
Joined: Sun Nov 30, 2003 8:57 am
Location: Candia, NH

Re: PIC12F675 Oscillator Calibration

Post by phalanx » Wed Sep 02, 2015 2:20 pm

Definitely not a pain. The purpose of this forum is to help people out after all!
Old Frank wrote:I also want to be able to do this sort of thing "from the ground up" and not rely on others' hidden software such as the Microchip Pickit stuff. I feel I'd understand it better.
I think you may have a misunderstanding of what a PICkit is. It's nothing more than a programmer/debugger. It doesn't do anything to obfuscate the internal workings of a PIC. It simply provides the hardware interface necessary to load code onto a device. The preservation of the calibration value during programming/erasing isn't a hidden feature that Microchip provides. It's clearly defined in the programming spec for all the PICs that have a calibration value and all 3rd party programmers are supposed to handle it accordingly. The PICkit-3 integrates seamlessly with MPLAB and are constantly upgraded to support new devices as they become available.

In an ideal world you will never have to overwrite the calibration value in program memory and it will always be available. There is no requirement though that you have to use it however. You can arbitrarily write any value OSCCAL and it will function. After a reset, OSCCAL defaults to 0x80 which is the center of the adjustment range.

For your purposes, the calibration value most likely isn't necessary. If you would, post your source code here so I can take a look at what you are trying to do.

-Bill

User avatar
phalanx
Non-SFE Guru
Posts: 1947
Joined: Sun Nov 30, 2003 8:57 am
Location: Candia, NH

Re: PIC12F675 Oscillator Calibration

Post by phalanx » Wed Sep 02, 2015 2:28 pm

Old Frank wrote:I found this that I'd tried about a week ago.
org 03FFh
movwf OSCCAL
org 0000h
What you told the assembler/linker to do here is to overwrite the calibration value with an instruction that moves the contents of an uninitialized W register into the OSCCAL register. Since you would be calling this location from your program code and the location now contains something other than a RETURN or RETLW instruction, your program counter will roll over to 0x00 and continue running like the device had just been reset. You would then "CALL 0x03FF" again and get stuck in an infinite loop.

Definitely post your code when you have a chance.

-Bill

Old Frank
Posts: 13
Joined: Tue Sep 01, 2015 12:46 pm

Re: PIC12F675 Oscillator Calibration

Post by Old Frank » Thu Sep 03, 2015 8:02 am

You'll regret that last remark, Bill.
I thought "org 03FF" meant "start execution at 03FF" (containing e.g. 3448), which should move 48h into W, followed by "put W's contents into OSCCAL". I seem to be barking up the wrong creek without a paddle.
Anyway, although I still haven't got a simple LED flash to work yet, here's a first draft of the strobe idea.

Code: Select all

;Test to flash LED on GP1 with input to AN0
;to select flash freq.

	list p=pic12f675

	movlw	0048h		;Calibration nibble read from mem.top
	movwf	OSCCAL		;& put into OSCCAL

CNTR1	EQU	0021h		;Counter for FLASH
CNTR2	EQU	0022h		;Counter for nr  of 255s
CNTR3	EQU	0023h		;Counter for nr  of units
HINIB	EQU	0024h		;High nibble of ADC result (nr of 255s)
LONIB	EQU	0025h		;Low nibble of ADC result (nr of units)

;Initialise GPIO and ADC

	clrf	GPIO		;Init. GPIO
	movlw	07h		;Set <GP2:0> to dig. I/O
	movwf	CMCON		;& comparator off

	movlw	0081h		;Left justify, VDD ref, Channel 0 &
	movwf	ADCON0		;turn on A/D module.
	movlw	0051h		;A/D clock is Fosc/16 &
	movwf	ANSEL		;AN0 is A/D input.
	
	bsf	STATUS,5	;Bank1
	movlw	09h		;Set GP0/AN0 & GP3 as inputs
	movwf	TRISIO		;& all others outputs

;Enable interrupts
	bsf	PIE1,6		;Enable A/D interrupts
	bsf	INTCON,PEIE	;Enable peripheral interrupts
	bsf	INTCON,GIE	;Enable all interrupts
	bcf	STATUS,5	;Bank0

;A/D conversion
CONVRT	bcf	PIR1,ADIF	;Clear A/D interrupt flag
	bsf	ADCON0,1	;Start conversion
	nop			;Delay to allow time
	nop			;for conversion to complete
	btfsc	ADCON0,1	;Check for conversion
	goto	$-1		;to finish
	movlw	F0h		;Mask off high nibble
	andwf	ADRESL,0	;& put in W then
	movwf	LONIB		;store it in HINIB
	movlw	0Fh		;Mask off low nibble
	andwf	ADRESL,0	;& put in W then
	movwf	HINIB		;store it in LONIB


;Flash LEDs on GP1
FLASH	bsf	GPIO,1		;Light l.e.d. on GP1
	movlw	0044h		;Put 44h into CNTR1 for
	movwf	CNTR1		;200? microsecond flash
ONT	decfsz	CNTR1,1		;Decrement CNTR1
	goto	ONT		;until it is zero
	
OFF	bcf	GPIO,1		;Turn off l.e.d.
	call	HITABLE		;Put nr of 255s
	movwf	CNTR2		;in CNTR2
OFT2	decfsz	CNTR2,1		;Decrement CNTR2
	goto	OFT2		;until it is zero
	
	call	LOTABLE		;Put nr of units
	movwf	CNTR3		;in CNTR3	
OFT3	decfsz	CNTR3,1		;Decrement CNTR3
	goto	OFT3		;until it is zero
	
	goto	CONVRT


HITABLE	addwf	PCL,1		;Add W (ADRESH) to PCL which then
	retlw	00C3h		;points to number of 255s in delay
	retlw	0082h		;starting at 20Hz, in 10Hz steps
	retlw	0061h
	retlw	004Eh		;N.B. these will need
	retlw	0041h		;adjusting
	   .
           .
        retlw	000Dh
	retlw	000Dh
	retlw	000Ch

LOTABLE	addwf	PCL,1		;Add W (ADRESH) to PCL which then
	retlw	00C7h		;points to number of units in delay
	retlw	006Bh		;starting at ??Hz, in 1Hz steps
	retlw	00BDh
	retlw	0022h		;N.B. these will need 
	retlw	0010h		;to be adjusted
	retlw	00B9h
	   .
           .
	retlw	00B4h
	retlw	0039h
	retlw	00C5h

	end

Old Frank
Posts: 13
Joined: Tue Sep 01, 2015 12:46 pm

Re: PIC12F675 Oscillator Calibration

Post by Old Frank » Mon Sep 07, 2015 6:19 pm

Here's a LED flash trial, which I thought was guaranteed to work. It simulates correctly, the programmer seems to install it in the PIC, as it reads back correctly after clearing, but still no LED flashes on a board tested with a PICAXE chip programmed in BASIC.
I must be doing something really fundamentally wrong, but can't see it.

Code: Select all

;Test to flash LED on GP1

	list p=pic12f675

	movlw	0014h		;Calibration nibble read from mem.top
	movwf	OSCCAL		;& put into OSCCAL

CNTR1	EQU	0021h		;Counter for FLASH
CNTR2	EQU	0022h		;Counter for off time
ON	EQU	44h		;LED on time
OFF	EQU	88h		;LED off time

;Initialise GPIO

	bcf	STATUS,RP0	;Bank0
	clrf	GPIO		;Init. GPIO
	movlw	07h		;Set <GP2:0> to dig. I/O
	movwf	CMCON		;& comparator off

	bsf	STATUS,RP0	;Bank1
	movlw	09h		;Set GP0/AN0 & GP3 as inputs
	movwf	TRISIO		;& all others outputs
	bcf	STATUS,RP0	;Bank0

;Flash LEDs on GP1

FLASH	bsf	GPIO,1		;Light l.e.d. on GP1
	movlw	ON		;Put on time into CNTR1
	movwf	CNTR1		;
ONT1	decfsz	CNTR1,1		;Decrement CNTR1
	goto	ONT1		;until it is zero
	bcf	GPIO,1		;Turn off l.e.d.
	movlw	OFF		;Put off time into CNTR1
	movwf	CNTR1		;
OFT1	decfsz	CNTR1,1		;Decrement CNTR1
	goto	OFT1		;until it is zero
	
	goto	FLASH
	
	end
Relax over the weekend, Bill. Forget things like old men in the UK. Some years ago I realised that the closer I get to death, the less time seems to matter, .... and if I should die in the meantime, it won't matter at all.
I'm off to bed. Cheers.
Frank

User avatar
phalanx
Non-SFE Guru
Posts: 1947
Joined: Sun Nov 30, 2003 8:57 am
Location: Candia, NH

Re: PIC12F675 Oscillator Calibration

Post by phalanx » Mon Sep 07, 2015 7:41 pm

Hi Frank,

I looked over your code and now there is a little work to do. I'm not familiar with the development environment you are using (I use MPLAB-X), but it appears to take the same formatting that Microchip's assembler MPASM uses so I will assume that's in fact what it is using. Microchip has assembly template files for a large number of PIC devices and and 12F675 is one of them. I used the template file to illustrate the formatting that MPASM expects when you make a project. I took your code and applied it to the template making corrections in spots which I'll detail further down.

The updated code which builds and runs properly:

Code: Select all

;**********************************************************************
;   This file is a basic code template for assembly code generation   *
;   on the PIC12F675. This file contains the basic code               *
;   building blocks to build upon.                                    *
;                                                                     *
;   Refer to the MPASM User's Guide for additional information on     *
;   features of the assembler (Document DS33014).                     *
;                                                                     *
;   Refer to the respective PIC data sheet for additional             *
;   information on the instruction set.                               *
;                                                                     *
;**********************************************************************
;                                                                     *
;    Filename:	    xxx.asm                                           *
;    Date:                                                            *
;    File Version:                                                    *
;                                                                     *
;    Author:                                                          *
;    Company:                                                         *
;                                                                     *
;                                                                     *
;**********************************************************************
;                                                                     *
;    Files Required: P12F675.INC                                      *
;                                                                     *
;**********************************************************************
;                                                                     *
;    Notes:                                                           *
;                                                                     *
;**********************************************************************

	list      p=12f675           ; list directive to define processor
	#include <p12f675.inc>        ; processor specific variable definitions

	__CONFIG   _CP_OFF & _CPD_OFF & _BODEN_OFF & _MCLRE_ON & _WDT_OFF & _PWRTE_ON & _INTRC_OSC_NOCLKOUT 

; '__CONFIG' directive is used to embed configuration word within .asm file.
; The lables following the directive are located in the respective .inc file.
; See data sheet for additional information on configuration word settings.
	
	
;***** VARIABLE/CONSTANT DEFINITIONS

w_temp        EQU     0x20        ; variable used for context saving 
status_temp   EQU     0x21        ; variable used for context saving

CNTR1	EQU	22h ;Counter for FLASH
CNTR2	EQU	23h ;Counter for off time
ON	EQU	44h ;LED on time
OFF	EQU	88h ;LED off time


;**********************************************************************
    ORG     0x000             ; processor reset vector
    goto    main              ; go to beginning of program


    ORG     0x004             ; interrupt vector location
    movwf   w_temp            ; save off current W register contents
    movf    STATUS,w          ; move status register into W register
    movwf   status_temp       ; save off contents of STATUS register


; isr code can go here or be located as a call subroutine elsewhere


    movf    status_temp,w     ; retrieve copy of STATUS register
    movwf   STATUS            ; restore pre-isr STATUS register contents
    swapf   w_temp,f
    swapf   w_temp,w          ; restore pre-isr W register contents
    retfie                    ; return from interrupt


; these first 4 instructions are not required if the internal oscillator is not used
main
    call    0x3FF             ; retrieve factory calibration value
    bsf     STATUS,RP0        ; set file register bank to 1 
    movwf   OSCCAL            ; update register with factory cal value 
    bcf     STATUS,RP0        ; set file register bank to 0


; remaining code goes here
		
   bcf	    STATUS,RP0  ;Bank0
   clrf	    GPIO	;Init. GPIO
   movlw    07h		;Set <GP2:0> to dig. I/O
   movwf    CMCON	;& comparator off

   bsf	    STATUS,RP0  ;Bank1
   clrf	    ANSEL	;Turn all analog pins into digital pins
   movlw    09h		;Set GP0/AN0 & GP3 as inputs
   movwf    TRISIO	;& all others outputs
   bcf	    STATUS,RP0  ;Bank0

 ;Flash LEDs on GP1

FLASH	
    bsf	    GPIO,GP1	;Light l.e.d. on GP1
    movlw   ON		;Put on time into CNTR1
    movwf   CNTR1	;
    
ONT1	
    decfsz  CNTR1,1	;Decrement CNTR1
    goto    ONT1	;until it is zero
    bcf	    GPIO,GP1	;Turn off l.e.d.
    movlw   OFF		;Put off time into CNTR1
    movwf   CNTR1	;
	
OFT1	
    decfsz  CNTR1,1	;Decrement CNTR1
    goto    OFT1	;until it is zero

    goto    FLASH  


    END                     ; directive 'end of program'
Fixes:
1. Right under the "list" directive, I added a #include<p12f675.inc> which brings in the processor specific variable definitions

2. The __CONFIG directive allows you to embed your configuration bits into your .asm file.

3. Variable/Constant declaration should occur before any code is written so I removed your section that updated OSCCAL

4. I updated your variable locations so they don't conflict with the template variables for interrupt service routines. It's good practice to make your constants ALL_CAPS so they stand out but I did not change them here.

5. Note how the template has an ORG 0x000 for the reset vector and an ORG 0x004 for the ISR. After a reset, the code jumps immediately to the "main" label. The template ISR preserves some important registers and restores them prior to exiting. In the future you can add ISR routines to that section.

6. For readability, I put your section labels on different lines than the code following it.

7. You did a good job initializing your pins but you missed the ANSEL register which controls the analog capabilities of pins. By default, all pins are analog inputs so you have to "CLRF ANSEL" to set all pins to digital. I put this right before you set the TRISIO register since it's in the same bank.

8. Instead of saying "bsf GPIO,1" I changed it to "bsf GPIO,GP1" to make it more readable. These bit names can be found in the p12675.inc file.

9. With the base instruction rate of 1MHz, your ON and OFF times are 206us and 412us respectively for a flash rate of about 1,618Hz which is way too fast for your eye to perceive as flashing. Increasing your ON and OFF times to 0xFF will get you down to about 651Hz which is till too fast to perceive as blinking. You will have to adjust how you create your delays if you need to slow down the flash rate.

I hope this gets you moving in the right direction!

-Bill

Old Frank
Posts: 13
Joined: Tue Sep 01, 2015 12:46 pm

Re: PIC12F675 Oscillator Calibration

Post by Old Frank » Wed Sep 09, 2015 1:34 pm

My word, Bill, you've done some work on this. I'm sorry it's taken so much time.
I originally had "include<p12f675.inc>", but the assembler highlighted it as an error, with or without the #.
All your other points show why I've been trying to find a college running a PIC programming course. I'm just ignorant. I've been asking anyone with computer experience if they program PICs or know someone who does, but North Wales seems like a PIC programming desert. Courses and books are advertised on the web, but from previous experience I'm rather sceptical about them. My basic knowledge is from two Babani (UK) books from the 1990s, but their coverage is limited.
I'll study your corrections in the morning, as my thinking is even worse after 9p.m., and try to understand them.
Many thanks for the work you've put in.
Frank

Old Frank
Posts: 13
Joined: Tue Sep 01, 2015 12:46 pm

Re: PIC12F675 Oscillator Calibration

Post by Old Frank » Sun Sep 13, 2015 1:47 pm

Hi, Bill.
To let you know I've not forgotten. Still trying to get at this while brain is capable, but SWMBO has other ideas during daylight hours and it's hopeless at this time of night. I had a quick try a few days ago, but nothing lit on the board even with long ON time and short OFF time. Tomorrow's booked all day with SWMBO's outing and then dentist - what joy! Maybe Tuesday morning.
Cheers for now,
Frank

User avatar
phalanx
Non-SFE Guru
Posts: 1947
Joined: Sun Nov 30, 2003 8:57 am
Location: Candia, NH

Re: PIC12F675 Oscillator Calibration

Post by phalanx » Mon Sep 14, 2015 8:35 am

I too have a SWMBO so I can understand the lack of time to work on your own projects!

-Bill

Old Frank
Posts: 13
Joined: Tue Sep 01, 2015 12:46 pm

Re: PIC12F675 Oscillator Calibration

Post by Old Frank » Sat Nov 14, 2015 2:56 pm

Sorry to have been away for so long, Bill. I was busy with prep. for a conference workshop session, then while I was at the conference I had a health scare and ended in hospital all wired up. More hospital investigation next week. Told to take things easy - as if an old retiree like me wasn't trying to do just that. Anyway, I've been catching up (slowly) on jobs I'd promised my local high school and should finish them in a week or so. Then I hope to get back to PIC-progging. I've been lent a PICkit 2, so I might find that less trouble. I'll let you know. Thanks for your patience with me. All the best, Frank.

Post Reply