1

我正在我的 ATTINY 85 上编写一个简单的程序。该程序应该在芯片唤醒时点亮 LED 引脚,并在其休眠时将其关闭。但是,当我将看门狗定时器设置为在 0.5 秒后复位时,它会在第一次复位时这样做,然后在大约 100 毫秒后复位。我使用示波器检查了它,prinstcreen 在此链接下: https ://i.snag.gy/WovBsf.jpg

这是代码:

/*
 * Sketch for testing sleep mode with wake up on WDT.
 * Donal Morrissey - 2011.
 * ATTINY85
 */

#include <TinyWireM.h>                  // I2C Master lib for ATTinys which use USI - comment this out to use with standard arduinos
#include <LiquidCrystal_attiny.h>          // for LCD w/ GPIO MODIFIED for the ATtiny85


#include <avr/sleep.h> 
#include <avr/power.h>
#include <avr/wdt.h>
#include <avr/interrupt.h>

//uwaga na numer pinu! nie używać tego z resetem
#define OUT_PIN 3

#define GPIO_ADDR     0x27
LiquidCrystal_I2C lcd(GPIO_ADDR, 16, 2); // set address & 16 chars / 2 lines

volatile int f_wdt=1;


/***************************************************
 *  Name:        ISR(WDT_vect)
 *
 *  Returns:     Nothing.
 *
 *  Parameters:  None.
 *
 *  Description: Watchdog Interrupt Service. This
 *               is executed when watchdog timed out.
 *
 ***************************************************/
ISR(WDT_vect){
  if(f_wdt == 0){
    f_wdt=1;

  }
  else{
//      lcd.clear();
//      lcd.print("WDT overrun");
//      delay(500);
  }
}


/***************************************************
 *  Name:        enterSleep
 *
 *  Returns:     Nothing.
 *
 *  Parameters:  None.
 *
 *  Description: Enters the arduino into sleep mode.
 *
 ***************************************************/
void enterSleep(void)
{
//  lcd.clear();
//  lcd.print("Asleep...");

  set_sleep_mode( SLEEP_MODE_PWR_DOWN );   /* EDIT: could also use SLEEP_MODE_PWR_DOWN for lowest power consumption. */
  sleep_enable();

  /* Now enter sleep mode. */
  sleep_mode();

  /* The program will continue from here after the WDT timeout*/
  sleep_disable(); /* First thing to do is disable sleep. */

  /* Re-enable the peripherals. */
  power_all_enable();

}



/***************************************************
 *  Name:        setup
 *
 *  Returns:     Nothing.
 *
 *  Parameters:  None.
 *
 *  Description: Setup for the serial comms and the
 *                Watch dog timeout. 
 *
 ***************************************************/
void setup()
{
  /*  Setup the LCD */
  lcd.init();                           // initialize the lcd
  lcd.backlight();                      // Print a message to the LCD.
  lcd.clear();
  lcd.setCursor(0,0);
  lcd.print("Initializing...");
  delay(500);

  /*** Setup the WDT ***/

  /* Clear the reset flag of watchdog interrupts, so that they are available again. */
  MCUSR &= ~(1<<WDRF);

  /* Enable configuration changes
   */
  WDTCR |= (1<<WDCE) | (1<<WDE);

/*
WDP3 WDP2 WDP1 WDP0         Number of WDT     Typical Time-out at
                                             Oscillator Cycles     VCC = 5.0V

  0         0      0        0             2K (2048) cycles       16 ms
  0         0      0        1             4K (4096) cycles       32 ms
  0         0      1        0             8K (8192) cycles       64 ms
  0         0      1        1            16K (16384) cycles    0.125 s
  0         1      0        0            32K (32768) cycles    0.25 s
  0         1      0        1            64K (65536) cycles    0.5 s
  0         1      1        0            128K (131072) cycles 1.0 s
  0         1      1        1            256K (262144) cycles 2.0 s
  1         0      0        0            512K (524288) cycles 4.0 s
  1         0      0        1            1024K (1048576) cycles 8.0 s
*/
  /* set new watchdog timeout prescaler value */
  WDTCR =  0<<WDP3 | 1<<WDP2 | 0<<WDP1 |  1<<WDP0 ;

  /* Enable the WD interrupt (note no reset). */
  WDTCR |= (1<<WDIE); 

  lcd.clear();
  lcd.print("Initialisation complete.");
  delay(100); 
}



/***************************************************
 *  Name:        enterSleep
 *
 *  Returns:     Nothing.
 *
 *  Parameters:  None.
 *
 *  Description: Main application loop.
 *
 ***************************************************/
void loop()
{
  if(f_wdt == 1)
  {
//    lcd.clear();
//    lcd.print("Awake!");
    digitalWrite( OUT_PIN, HIGH );
    delay(1000);
    /* Don't forget to clear the flag. */
    f_wdt = 0;
    digitalWrite( OUT_PIN, LOW );
    /* Re-enter sleep mode. */
    enterSleep();
  }
  else
  {
    /* Do nothing. */
  }
}

有人知道如何解决这个问题吗?

编辑:好的,我设法修复它。我唯一需要改变的是在进入睡眠之前启用 WDT 中断,然后在睡眠后禁用它。所以enetSleep 函数看起来像这样:

void enterSleep(void)
{
  lcd.clear();
  lcd.print("Asleep...");

  /* Enable the WD interrupt (note no reset). */
  WDTCR |= (1<<WDIE); 

  set_sleep_mode( SLEEP_MODE_PWR_DOWN );   /* EDIT: could also use SLEEP_MODE_PWR_DOWN for lowest power consumption. */
  sleep_enable();

  /* Now enter sleep mode. */
  sleep_mode();

  /* The program will continue from here after the WDT timeout*/
  sleep_disable(); /* First thing to do is disable sleep. */

  /* Re-enable the peripherals. */
  power_all_enable();

  /* Disable the WD interrupt */
  WDTCR &= ~_BV(WDIE);
}

当然,我删除了

WDTCR |= (1<<WDIE);

从设置线。

4

0 回答 0