Let's find out together what makes a PIC Tick!

Main Menu

Strange error with new 12F675 IC's

Started by See_Mos, May 18, 2023, 05:11 PM

Previous topic - Next topic


I am down to the last two of my 12F675 dated 2002 and I needed some low peripheral count devices for a new project so I ordered some more from Farnell, these are dated 2022. 

The code that works on the old chips does not work on the new ones!

RSOUT : CLS : DelayMS 100

no longer works and writing to the LCD gives all kinds of strange characters.

There is a count down timer based on TIMER1 and a delay of one second in the main loop which toggles an LED. The timer appears to run as expected but as soon as the count down times out and  TIMER1 is disabled then the the LED starts to flash at a much higher rate than the loop delay of DelayMS 1000, the ON time being much shorter than the OFF time

I reprogrammed one of the old devices and everything works as expected.

I should have gone for 12F1840 and just ignored all of the peripherals that I do not need

OK, now to read the revision G data sheet to see if I can spot the changes!


Quote from: See_Mos on May 18, 2023, 05:11 PMThere is a count down timer based on TIMER1 and a delay of ....

There seems to be a TIMER1 errata, check this Timer1 Module Data Sheet Errata


I removed the TIMER1 code but the clear screen and subsequent write is still not working.  I am now looking at the registers to see if there have been any changes which are not being picked up by the compiler.


Your syntax for the Cls modifier with the RSOut command is not correct. It has always been "RSOut Cls"

I have just created a sample code listing to test the RSOut command and the Cls modifer with it, and Timer1, on a PIC12F675 device.

The test program's code listing is below:

'   /\\\\\\\\\
'  /\\\///////\\\
'  \/\\\     \/\\\                                                 /\\\          /\\\
'   \/\\\\\\\\\\\/        /\\\\\     /\\\\\\\\\\     /\\\\\\\\   /\\\\\\\\\\\  /\\\\\\\\\\\  /\\\\\\\\\
'    \/\\\//////\\\      /\\\///\\\  \/\\\//////    /\\\/////\\\ \////\\\////  \////\\\////  \////////\\\
'     \/\\\    \//\\\    /\\\  \//\\\ \/\\\\\\\\\\  /\\\\\\\\\\\     \/\\\         \/\\\        /\\\\\\\\\\
'      \/\\\     \//\\\  \//\\\  /\\\  \////////\\\ \//\\///////      \/\\\ /\\     \/\\\ /\\   /\\\/////\\\
'       \/\\\      \//\\\  \///\\\\\/    /\\\\\\\\\\  \//\\\\\\\\\\    \//\\\\\      \//\\\\\   \//\\\\\\\\/\\
'        \///        \///     \/////     \//////////    \//////////      \/////        \/////     \////////\//
'                                  Let's find out together what makes a PIC Tick!
' Test a serial LCD with an 8-pin standard 14-bit core device displaying the contents of Timer1
    Device = 12F675                             ' Tell the compiler what device is being compiled for
    Declare Xtal = 4                            ' Tell the compiler what speed the device will be operating at (in MHz)
' Setup RSout
    Declare RSOut_Pin = GPIO.0
    Declare Serial_Baud = 9600
    Declare RSOut_Mode = 0
' Create any global variables for the program here:
    Dim wTimer1 As TMR1L.Word                   ' Create a 16-bit SFR from SFRs TMR1L and TMR1H

' The main program starts here
' Transmit the contents of Timer1 to a serial LCD, clearing the LCD between transmissions.
    Set_OSCCAL                                  ' Load the OSCCAL SFR with the calibration value held in the device
    DelayMs 500                                 ' Wait for the serial LCD to stabilise
    T1CON = %00110001                           ' Setup Timer1 to use its internal oscillator with maximum prescaler

    Do                                          ' Create a loop
        RSOut Cls                               ' Clear the serial LCD's display
        RSOut "Timer1 ", Dec wTimer1            ' Transmit the Timer1 value to the serial LCD
        DelayMs 100                             ' A small delay
    Loop                                        ' Do it forever

' Setup the config fuses to use the internal oscillator with GPIO.4 and GPIO.5 as I/O pins, on a PIC12F675 device

The program displays the contents of the 16-bit Timer1 on the serial LCD after clearing the display first.

The RSOut line can also be written as:

RSOut Cls, "Timer1 ", Dec wTimer1  ' Clear the serial LCD, then transmit the Timer1 value to it


RSOut Cls : RSOut "Timer1 ", Dec wTimer1  ' Clear the serial LCD, then transmit the Timer1 value to it

If you are getting strange characters on the serial LCD, make sure the PIC device is operating at the correct speed and that the Baud rate is correct for the serial LCD, and the serial mode used to communicate to it is correct.

Below is a screenshot of the Proteus simulation of the above program working:

PIC12F675 Serial LCD Test.jpg


Sorry Les, the extra colon was a typing error.

It looks like there is a problem with OSCCAL.  All five new devices tested so far are out by +15% to +19%

Reprogramming OSCCAL only works once, GP4 becomes close to 1000KHz and the display works as expected.

After cycling VDD GP4 returns to the original higher frequency even though reading the device shows the new OSCCAL value at location $3FF 


Unfortunately, if a programmer has erased or over-written the calibration value at the top of the code memory, (address $03FF with a 1K device), the Set_OSCCAL command has nothing to read to place in the OSCCAL SFR.

The Set_OSCCAL command creates the assembler code:

    bcf STATUS,PP_RP0
    bcf STATUS,PP_RP1
    call 0X03FF
    bsf STATUS,PP_RP0
    movwf OSCCAL
    bcf STATUS,PP_RP0

For a PIC12F675 device, you can see the Call to the address 0X03FF, and upon its return, WREG holds the calibration value to place in the OSCCAL SFR, but if it has been erased, it will cause problems because the Retlw mnemonic will also have been erased, so it cannot return and will start the device over, but use a call stack position as well.


With Pickit+ I can read the device and see a sensible value like $343C at location $3FF

I have working code that I wrote 20 years ago. With potentiometer input I can vary OSCCAL directly and show the value on the serial display when the oscillator is running near the correct frequency and this can also be confirmed with a frequency counter on GP4.

Say the value on the LCD display is $44 and GP4 is close to 1000KHz, I can then use Pickit+ to manually put $3444 into location $3FF.  This erases the device so I reprogramme it with the same code as before but with the OSCCAL setting disabled.  After cycling the power I can then verify or read the device with PicKit+ and it shows $3444 as before but this is being ignored by the device and the frequency at GP4 has gone up from around 1000KHz to 1154KHz.

I tried setting a much different value at $3FF like $3415 but after reprogramming GP4 is still 1154KHz

At the top of the code I added a direct update of OSCCAL as per the data sheet but this is also ignored

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

so the puzzle now it why I can set OSCCAL directly but the device does not do so at power on

Colin G3YHV

Could they be pirate chips  ?
I am sure we had a load of dud  DS3231  so called precision rtc's
They were all over the place and even jumped about!
Scraped them and changed to GPS timing
Colin G3YHV


Because it is so long since I have used a standard 14-bit device with an internal oscillator, I forgot to use the Set_OSCCAL command in the above code listing, but I remember when they were the most used devices, not all PICs set the internal oscillator up accurately by default, so the Set_OSCCAL command was a must in all programs. Set_OSCCAL now added to the previous code listing.

That is the problem with simulation, the oscillator will always be accurate, but in the real world it will not be, because it is based upon R/C and the old devices did not contain a good PLL, or in most cases with standard 14-bit core types, they contained no PLL.

The Set_OSCCAL command adds code to read the calibration value placed at the top of code (flash) memory and load it into the OSCCAL SFR before the user's program starts, so it sets up the internal oscillator to be more accurate. However, sometimes, the OSCCAL SFR itself needs to be loaded because the calibration value is not quite right, and the oscillator can be made more accurate. Rememeber, the standard 14-bit core devices are now very old and very much legacy, so their technology was not nearly as good as the more recent devices.

So... Whenever using the internal oscillator on a standard 14-bit core device, add the Set_OSCCAL command to the program's listing.


Thanks again Les. Good thing your memory is better than mine.

Set_OSCCAL worked and when I looked at the assembler code I saw two lines of code that were not shown in the data sheet.

I posted elsewhere about the problem of typing Set OSCCAL instead of Set_OSCCAL

Something else I had forgotten about the 12F629-675 is that enabling the weak.pull-up switch sets pull-up on all pins and any pins where pull-up is not needed have to be turned off.