AVR ATTINY RTC PIT OSCULP32K

OP #7265056
Lesenswert?

Dank dem RTC (Real Time Counter) kann der ATtiny lange Zeit im Standby 
Sleep Modus bleiben, und dank dem Ultra Low-Power Oscillator OSCULP32K 
beträgt die Stromaufnahme nur ca. 0.7µA (VDD=3V).

Ich habe gestern diesen Code getestet
(Time-out period: 60 min)
1
/*------------------------------------------------------------
2
                        ATtiny402
3

4
           +3V --- VDD 1|‾‾‾‾‾‾‾|8 GND 
5
                   PA6 2|       |7 PA3 --- LED 
6
                   PA7 3|       |6 UPDI 
7
  piezo buzzer --- PA1 4|_______|5 PA2 --- piezo buzzer
8

9
---------------------------------------------------------------*/
10

11
#include <avr/io.h>
12
#include <avr/interrupt.h>
13
#include <avr/sleep.h>
14

15
volatile uint8_t pit;            // SW PIT interrupt flag
16
uint8_t count;                   // SW counter
17
uint8_t cmpv = 180;              // TCA CMP Value
18

19
ISR(RTC_CNT_vect) 
20
{
21
  RTC.PITINTCTRL = RTC_PI_bm;    // enable PIT interrupt
22
  RTC.INTFLAGS = RTC_OVF_bm;     // clear RTC OVF interrupt flag
23
}
24

25
ISR(RTC_PIT_vect)
26
{
27
  pit = 1;                       // set SW PIT interrupt flag
28
  RTC.PITINTFLAGS = RTC_PI_bm;   // clear PIT interrupt flag
29
}
30

31
int main(void)
32
{
33
  PORTA.PIN1CTRL = PORT_ISC_INPUT_DISABLE_gc;   // disable digital input buffer
34
  PORTA.PIN2CTRL = PORT_ISC_INPUT_DISABLE_gc;   // disable digital input buffer
35
  PORTA.PIN3CTRL = PORT_ISC_INPUT_DISABLE_gc;   // disable digital input buffer
36
  PORTA.PIN6CTRL = PORT_ISC_INPUT_DISABLE_gc;   // disable digital input buffer
37
  PORTA.PIN7CTRL = PORT_ISC_INPUT_DISABLE_gc;   // disable digital input buffer
38

39
  PORTA.DIRSET = PIN3_bm;                       // PA3 output (LED)
40
  PORTA.DIRSET = PIN1_bm;                       // PA1 output (TCA WO1)
41
  PORTA.DIRSET = PIN2_bm;                       // PA2 output (TCA WO2)
42
  PORTA.PIN2CTRL = PORT_INVEN_bm;               // invert PA2 (TCA WO2, antiphase for piezo buzzer)
43

44
  RTC.CLKSEL = RTC_CLKSEL_INT1K_gc;             // 1024 Hz from OSCULP32K
45
  while (RTC.STATUS > 0) {}                     // wait for all register to be synchronized
46
  RTC.PER = 0x0E0F;                             // RTC period (60 min @ 1Hz)
47
  RTC.INTCTRL = RTC_OVF_bm;                     // enable RTC OVF interrupt
48
  RTC.CTRLA = RTC_RUNSTDBY_bm | RTC_PRESCALER_DIV1024_gc | RTC_RTCEN_bm;     // Run In Standby, 1Hz clock, enable RTC
49

50
  TCA0.SINGLE.CTRLB = TCA_SINGLE_CMP1EN_bm | TCA_SINGLE_CMP2EN_bm | TCA_SINGLE_WGMODE_SINGLESLOPE_gc;   // enable compare channel 1 and 2, single-slope PWM
51
  TCA0.SINGLE.CTRLA = TCA_SINGLE_CLKSEL_DIV2_gc | TCA_SINGLE_ENABLE_bm;                                 // set clock source (1.666MHz), start TCA
52

53
  while (RTC.PITSTATUS > 0) {}                          // wait for RTC.PITCTRLA synchronization
54
  RTC.PITCTRLA = RTC_PERIOD_CYC64_gc | RTC_PITEN_bm;    // 62.5ms PIT time-out period, enable PIT
55
  RTC.PITINTCTRL = RTC_PI_bm;                           // enable PIT interrupt
56

57
  SLPCTRL.CTRLA = SLPCTRL_SMODE_STDBY_gc;               // select STANDBY sleep mode
58
  sei();                                                // enable interrupts
59

60
  while(1)
61
  {
62
    PORTA.OUTSET = PIN3_bm;                      // PA3 on (LED on)
63
    if(pit)                                      // if PIT interrupt occurred
64
    {
65
      pit = 0;                                   // clear SW PIT interrupt flag
66
      TCA0.SINGLE.PERBUF = (cmpv << 2) - 1;      // set period
67
      TCA0.SINGLE.CMP1BUF = cmpv;                // set compare match
68
      TCA0.SINGLE.CMP2BUF = cmpv;                // set compare match
69
      cmpv = cmpv == 180 ? 190 : 180;            // toggle between 180 and 190
70
      count++;
71
      if(count == 16)
72
      {
73
        count = 0;                      // clear SW counter
74
        RTC.PITINTCTRL = 0;             // disable PIT interrupt
75
        PORTA.OUTCLR = PIN3_bm;         // PA3 off (LED off)
76
        sleep_mode();
77
      }
78
    }
79
  }
80
}


und bin mit dem Ergebnis sehr zufrieden:

 17:00:00
 17:59:58
 18:59:56
 19:59:54
 20:59:52
 21:59:50


Was meint ihr?
Gast #7265095
Lesenswert?

Georg M. schrieb:
> Was meint ihr?
2 Sekunden Abweichung pro Stunde, macht 48s/Tag = 1440s = 24min 
Abweichung pro Monat.

Für 0.7µA und programmierbar (nicht nur eine Zeitschaltuhr) finde ich 
das sehr gut.

Die Abweichung lässt sich ja auch noch rauskalibrieren. Interessant wäre 
die Abweichung über 1 Monat, nachdem man die 2 Sekunden raus kalibriert 
hat.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren