reset.c - Demonstrates software reset, idle, sleep, watchdog timer operation.

Program that tests some of the ways that a PIC24 can be reset, as well as sleep mode, idle mode, and the watchdog timer. Intended to be used in a laboratory exercise in which the current draw of the processor is monitored before/after the power down modes.

 
#include "pic24_all.h"
 
 
This function puts the PIC24 in low-power mode, following the directions given in DS70615C section 9.2.2.1 by:
  • Configuring all digital I/O pins as inputs and enabling pullups on them.
  • Configuring all analog I/O pins shared with digital I/O pins to be digital only.
  • Disabling the internal voltage regulators when in sleep mode.
  • Disabling all peripherals, except UART 1.

WARNING: if pullups are enabled on pins used by the oscillator, the clock typically stops running. Therefore, this code only works with the FRC oscillator.

Note: this function is processor specific.

#if (defined(__dsPIC33EP128GP502__))
void configPinsForLowPower(void) {

Configure all digital I/O pins for input.

  TRISB = 0xFFFF;
  TRISA = 0xFFFF;
  ANSELA = 0x0000;
  ANSELB = 0x0000;

The primary oscillator is not used, so turn on all the pull-ups.

  CNPUA = 0xFFFF;
  CNPUB = 0xFFFF;

Turn off the internal voltage regulators when in sleep.

  _VREGS = 0;
  _VREGSF = 0;

Power off all peripherals except UART 1.

  PMD1 = 0xFFDF;
  PMD2 = 0xFFFF;
  PMD3 = 0xFFFF;
  PMD4 = 0xFFFF;
  PMD6 = 0xFFFF;
  PMD7 = 0xFFFF;
}
#else
# warning "Using dummy function for configPinsForLowPower()."
void configPinsForLowPower(void) {
}
#endif


uint8_t printMenuGetChoice() {
  uint8_t u8_c;
  outString("'1' enable watchdog timer\n");
  outString("'2' enter sleep mode\n");
  outString("'3' enter idle mode\n");
  outString("'4' enable watchdog timer and enter sleep mode\n");
  outString("'5' doze = divide by 2\n");
  outString("'6' doze = divide by 128\n");
  outString("'7' execute reset instruction\n");
  outString("Choice: ");
  u8_c = inChar();
  outChar(u8_c);      //echo character
  outString("\n");      //newline
  return(u8_c);
}

//persistent variables are not touched at reset
_PERSISTENT uint8_t u8_resetCount;


int main(void) {
  configClock();                //clock configuration
  configPinsForLowPower();      //config pins for low power since we are measuring current
  configHeartbeat();            //heartbeat LED
  configDefaultUART(DEFAULT_BAUDRATE); //serial port config
  outString(HELLO_MSG);         //say Hello!

  if (_POR) {
    u8_resetCount = 0;      // if power on reset, init the reset count variable
  } else {
    u8_resetCount++;        //keep track of the number of non-power on resets
  }
  if (_WDTO) {
    _SWDTEN = 0;            //If Watchdog timeout, disable WDT.
  }
  printResetCause();        //print statement about what caused reset
  //print the reset count
  outString("The reset count is ");
  outUint8(u8_resetCount);
  outString("\n");

  while (1) {
    uint8_t u8_c;
    u8_c = printMenuGetChoice();
    DELAY_MS(1);  //let characters clear the UART before executing choice
    switch (u8_c) {
      case '1':         //enable watchdog timer
        _SWDTEN = 1;    //WDT ENable bit = 1
        break;
      case '2':         //sleep mode
        asm("pwrsav #0");  //sleep
        outString("after sleep\n");   //never executed.
        break;
      case '3':         //idle mode
        asm("pwrsav #1"); //idle
        outString("after idle\n");   //never executed.
        break;
      case '4':
        _SWDTEN = 1;     //WDT ENable bit = 1
        asm("pwrsav #0"); //sleep
        outString("after WDT enable, sleep.\n"); //executed on wakeup
        break;
      case '5':
        _DOZE = 1; //chose divide by 2
        _DOZEN = 1; //enable doze mode
        break;
      case '6':
        _DOZE = 7; //chose divide by 128
        _DOZEN = 1; //enable doze mode
        break;
      case '7':
        asm("reset"); //reset myself
        break;

      default:
        break;  //ignore
    }

  } // end while (1)
  return 0;
}