Forum: Mikrocontroller und Digitale Elektronik AVR ATTINY RTC PIT OSCULP32K


von Georg M. (g_m)


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?

von WF88 (Gast)


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.

von Jan V. (janv)


Lesenswert?

WF88 schrieb:
> Interessant wäre die Abweichung über

variierende Temperaturen!

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.