News:

PROTON pic BASIC Compilers for PIC, PIC24, dsPIC33

Main Menu

Sleep n seconds on 12F1822

Started by charliecoutas, Jun 21, 2026, 08:51 AM

Previous topic - Next topic

charliecoutas

I am trying to make a 12F1822 Sleep for a number of seconds. The config is:

Device = 12F1822                                                       

Config1 FOSC_INTOSC, WDTE_ON, PWRTE_ON, MCLRE_OFF, CP_OFF, BOREN_OFF, CLKOUTEN_OFF, IESO_OFF, FCMEN_OFF
Config2 WRT_OFF, PLLEN_ON, STVREN_OFF, LVP_OFF

When I write "Sleep 20" the compiler warns: "The Watchdog fuse is disabled, so the microcontroller may never wake up on its own"

Can somebody point me in the right direction please?

Charles

See_Mos

#1
Sleep uses the watchdog timer.  Have a look at register WDTCON and the bit WDTEN

trastikata

Hi Charlie,

this is an old but relevant post:

https://protoncompiler.com/index.php?msg=12828

If you still have questions, let us know.

Regards

charliecoutas

Thanks See_MOS, Trastikata. Can't try it now, will report back Tuesday.

Charlie

top204

#4
The more recent PIC devices have advanced quite a bit in their sleep mechanisms, and the compiler's Sleep command is a relic from the past to keep some backward compatibility when possible, and I will be going through its code functions and giving the "not suitable" error on the devices that do not have a fuse config setting for specific Watchdog Timer Prescaler values, such as the PIC12F1822 device, and others.

However, now that the compiler has true, and efficient, procedures, it is very straightforward to create a mechanism to place the device into "full" sleep mode for a certain length of time on suitable devices, or a mechanism to sleep/wake for a certain amount of times for a more flexible sleep time (but not as efficient).

For example, the code listing below has a procedure for a full sleep mode on a PIC12F1822 device:

'
'   /\\\\\\\\\
'  /\\\///////\\\
'  \/\\\     \/\\\                                                 /\\\          /\\\
'   \/\\\\\\\\\\\/        /\\\\\     /\\\\\\\\\\     /\\\\\\\\   /\\\\\\\\\\\  /\\\\\\\\\\\  /\\\\\\\\\
'    \/\\\//////\\\      /\\\///\\\  \/\\\//////    /\\\/////\\\ \////\\\////  \////\\\////  \////////\\\
'     \/\\\    \//\\\    /\\\  \//\\\ \/\\\\\\\\\\  /\\\\\\\\\\\     \/\\\         \/\\\        /\\\\\\\\\\
'      \/\\\     \//\\\  \//\\\  /\\\  \////////\\\ \//\\///////      \/\\\ /\\     \/\\\ /\\   /\\\/////\\\
'       \/\\\      \//\\\  \///\\\\\/    /\\\\\\\\\\  \//\\\\\\\\\\    \//\\\\\      \//\\\\\   \//\\\\\\\\/\\
'        \///        \///     \/////     \//////////    \//////////      \/////        \/////     \////////\//
'                                  Let's find out together what makes a PIC Tick!
'
' Demonstrate a set of preprocessor meta-macros to control the Watchdog Timer Prescaler for a more efficient sleep mechanism.
' Written for PIC12F1822, PIC12LF1822, PIC16F1823, and PIC16LF1823 devices.
'
' Written for the Positron8 compiler by Les Johnson.
' https://sites.google.com/view/rosetta-tech/positron-compilers-experimenters-notebook
'
    Device = 12F1822                                                            ' Tell the compiler what device to compile for
    Declare Xtal = 32                                                           ' Tell the compiler what frequency the device is operating at (in MHz)
    Declare Watchdog = On                                                       ' Tell the compiler to use Clrwdt mnemonics in its library routiones, so the watchdog is tamed in them
    Declare Auto_Heap_Arrays = On                                               ' Tell the compiler to create arrays above standard variables, so assembler code is more efficient
    Declare Auto_Heap_Strings = On                                              ' Tell the compiler to create Strings above standard variables, so assembler code is more efficient
    Declare Auto_Variable_Bank_Cross = On                                       ' Tell the compiler to create any multi-byte variables in the same RAM bank. For more efficiency
'
' Setup USART1
'
    Declare Hserial_Baud = 9600                                                 ' Set the Baud rate for USART1
    Declare HSerout1_Pin = PORTA.0                                              ' Set the TX pin for USART1
    Declare HSerin1_Pin  = PORTA.1                                              ' Set the RX pin for USART1
    Declare Hserial1_Clear = On                                                 ' Enable Error clearing on received bytes
'
' Create any global variables, constants and aliases here
'
    Dim wWakeCounter As Word = 0                                                ' Increments on every wake-up of the device

'------------------------------------------------------------------------------------
' Watchdog meta-macros for a PIC12F1822, PIC12LF1822, PIC16F1823, or PIC16LF1823 device.
'
$define WDT_1Ms()   WDTCON = WDTCON & 11000001: WDTCON = WDTCON | %00000000     ' The Watchdog Prescale is 1:32 (Interval is approx 1 millisecond)
$define WDT_2Ms()   WDTCON = WDTCON & 11000001: WDTCON = WDTCON | %00000010     ' The Watchdog Prescale is 1:64 (Interval is approx 2 milliseconds)
$define WDT_4Ms()   WDTCON = WDTCON & 11000001: WDTCON = WDTCON | %00000100     ' The Watchdog Prescale is 1:128 (Interval is approx 4 milliseconds)
$define WDT_8Ms()   WDTCON = WDTCON & 11000001: WDTCON = WDTCON | %00000110     ' The Watchdog Prescale is 1:256 (Interval is approx 8 milliseconds)
$define WDT_16Ms()  WDTCON = WDTCON & 11000001: WDTCON = WDTCON | %00001000     ' The Watchdog Prescale is 1:512 (Interval is approx 16 milliseconds)
$define WDT_32Ms()  WDTCON = WDTCON & 11000001: WDTCON = WDTCON | %00001010     ' The Watchdog Prescale is 1:1024 (Interval is approx 32 milliseconds)
$define WDT_64Ms()  WDTCON = WDTCON & 11000001: WDTCON = WDTCON | %00001100     ' The Watchdog Prescale is 1:2048 (Interval is approx 64 milliseconds)
$define WDT_128Ms() WDTCON = WDTCON & 11000001: WDTCON = WDTCON | %00001110     ' The Watchdog Prescale is 1:4096 (Interval is approx 128 milliseconds)
$define WDT_256Ms() WDTCON = WDTCON & 11000001: WDTCON = WDTCON | %00010000     ' The Watchdog Prescale is 1:8192 (Interval is approx 256 milliseconds)
$define WDT_512Ms() WDTCON = WDTCON & 11000001: WDTCON = WDTCON | %00010010     ' The Watchdog Prescale is 1:16384 (Interval is approx 512 milliseconds)
$define WDT_1S()    WDTCON = WDTCON & 11000001: WDTCON = WDTCON | %00010100     ' The Watchdog Prescale is 1:32768 (Interval is approx 1 second)
$define WDT_2S()    WDTCON = WDTCON & 11000001: WDTCON = WDTCON | %00010110     ' The Watchdog Prescale is 1:65536 (Interval is approx 2 seconds)
$define WDT_4S()    WDTCON = WDTCON & 11000001: WDTCON = WDTCON | %00011000     ' The Watchdog Prescale is 1:131072 (Interval is approx 4 seconds)
$define WDT_8S()    WDTCON = WDTCON & 11000001: WDTCON = WDTCON | %00011010     ' The Watchdog Prescale is 1:262144 (Interval is approx 8 seconds)
$define WDT_16S()   WDTCON = WDTCON & 11000001: WDTCON = WDTCON | %00011100     ' The Watchdog Prescale is 1:524288 (Interval is approx 16 seconds)
$define WDT_32S()   WDTCON = WDTCON & 11000001: WDTCON = WDTCON | %00011110     ' The Watchdog Prescale is 1:1048576 (Interval is approx 32 seconds)
$define WDT_64S()   WDTCON = WDTCON & 11000001: WDTCON = WDTCON | %00100000     ' The Watchdog Prescale is 1:2097152 (Interval is approx 64 seconds)
$define WDT_128S()  WDTCON = WDTCON & 11000001: WDTCON = WDTCON | %00100010     ' The Watchdog Prescale is 1:4194304 (Interval is approx 128 seconds)
$define WDT_256S()  WDTCON = WDTCON & 11000001: WDTCON = WDTCON | %00100100     ' The Watchdog Prescale is 1:8388608 (Interval is approx 256 seconds)

$define WDT_Enable() WDTCONbits_SWDTEN = 1                                      ' Enable the Watchdog Timer
$define WDT_Disable() WDTCONbits_SWDTEN = 0                                     ' Disable the Watchdog Timer

'------------------------------------------------------------------------------------
' The main program starts here
' Place the device into sleep mode using the Watchdog Timer Prescaler for the time length of the sleep
'
Main:
    Setup()                                                                     ' Setup the program and peripherals

    Do                                                                          ' Create a loop
        HRsout1Ln "Going to Sleep"                                              ' Transmit what is going to happen
        DelayMs 1                                                               ' A short wait, so it fully transmits before sleep
        GotoSleep()                                                             ' Place the device into full sleep mode
        Inc wWakeCounter                                                        ' Increment the wWakeCounter variable, when the device wakes up
        HRsout1Ln "Awake. wWakeCounter is ", Dec wWakeCounter                   ' Transmit when the device is awake, and show the value in wWakeCounter
        DelayMs 500                                                             ' Wait for a bit of drama before the device goes back to sleep again
    Loop                                                                        ' Do it forever

'------------------------------------------------------------------------------------
' Place the device into full sleep mode for approx 1 second
' Input     : None
' Output    : None
' Notes     : Sleeps for the length of time set by the WDTPS bits in the WDTCON SFR. i.e. WDT_1S()
'
Proc GotoSleep()
    ClrWdt                                                                      ' Clear the Watchdog Timer before putting the device in sleep mode
    WDT_1S()                                                                    ' Set the Watchdog Prescaler to approx 1 second (actually 1.0486)
    WDT_Enable()                                                                ' Enable the Watchdog Timer
    Sleep                                                                       ' Place the device into sleep mode
    WDT_Disable()                                                               ' Disable the Watchdog Timer, before exiting the procedure
EndProc

'------------------------------------------------------------------------------------
' Setup the program and peripherals
' Input     : None
' Output    : None
' Notes     : None
'
Proc Setup()
    Osc_Init()                                                                  ' Setup the Internal Oscillator
    WDT_Disable()                                                               ' Disable the Watchdog Timer
    WDT_1S()                                                                    ' Set the Watchdog Prescaler to approx 1 second as a default
EndProc

'------------------------------------------------------------------------------------
' Setup the internal oscillator
' Input     : None
' Output    : None
' Notes     : For a PIC12F1822, PIC12LF1822, PIC16F1823, or PIC16LF1823 device.
'
Proc Osc_Init()
    OSCCON  = %01110000                                                         ' 8MHz HF
    OSCTUNE = %00000000
    BORCON  = %00000000
    DelayMs 100                                                                 ' A small delay to wait for the PLL to stabilise
EndProc

'------------------------------------------------------------------------------------
' Setup the config fuses for an internal oscillator on a PIC12F1822, PIC12LF1822, PIC16F1823, or PIC16LF1823 device.
' OSC pins are general purpose I/O lines.
' 4xPLL is enabled.
' Watchdog is controlled by the SWDTEN bit in the WDTCON SFR.
'
    Config1 FOSC_INTOSC,_                                                       ' INTOSC oscillator. I/O function on CLKIN pin
            WDTE_SWDTEN,_                                                       ' Watchdog Timer is controlled by the SWDTEN bit in the WDTCON SFR
            PWRTE_OFF,_                                                         ' PWRT disabled
            MCLRE_OFF,_                                                         ' MCLR/VPP pin function is digital input
            CP_OFF,_                                                            ' Program memory code protection is disabled
            CPD_OFF,_                                                           ' Data memory code protection is disabled
            BOREN_OFF,_                                                         ' Brown-out Reset disabled
            CLKOUTEN_OFF,_                                                      ' CLKOUT function is disabled
            IESO_OFF,_                                                          ' Internal/External Switchover mode is disabled
            FCMEN_OFF                                                           ' Fail-Safe Clock Monitor is disabled

    Config2 WRT_OFF,_                                                           ' Write protection off
            PLLEN_ON,_                                                          ' Oscillator 4xPLL enabled
            STVREN_ON,_                                                         ' Stack Overflow or Underflow will cause a reset
            BORV_19,_                                                           ' Brown-out Reset Voltage (VBOR) set to 1.9V
            LVP_ON                                                              ' Low-voltage programming enabled

The "GotoSleep()" procedure is for a 1 second 'full' sleep, but that can be be made into 20 seconds by looping 20 times within the procedure, or altering the "WDTPS" bits of the WDTCON SFR for a time close enough. i.e 16 seconds or 32 seconds etc... (Powers of 2). See the WDT_xxx() meta-macros in the listing above, and view the 'Watchdog Timer' section in the device's datasheet (Section 10.0).

Regards
Les

charliecoutas

Thanks Les, that makes it clear.

Charlie