RTC32 mit XMEGA

Gast #2954724
Lesenswert?

Hallo,

ich habe leider im Netz nur ASF Beispiele für den RTC32 aus den Xmegas 
gefunden. Ich wollte aber auf das Framework verzichten und habe mich 
selber drangesetzt.

Es wird ein externer 32kHz Quarz zwischen dem Pin TOSC1 und TOSC2 
benötigt.

Das Programm aktivier die notwendigen Komponenten und versetzt den 
Prozessor dann in den Schlafmodus. Hier verweilt er solange bis der 
RTC32 den Wert im PER-Register überspringt.

Achtung: ich habe lange gedacht, dass ich den RTC32 falsch konfiguriert 
hätte und er überhaupt nicht zählt! Das Atmel Studio zeigt nur den 
richtigen CNT-Wert an, wenn das CNT-Register vorher synchronisiert 
worden ist - hängt mit den Clock-Domänen zusammen.

Getestet habe ich das ganze mit einem ATxmega256A3BU, sollte aber 
natürlich mit jedem anderen Xmega laufen der einen RTC32 besitzt.
1
#include <avr/io.h>
2
#include <util/atomic.h>
3
#include <util/delay.h>
4
#include <avr/interrupt.h>
5
#include "avr_compiler.h"
6

7

8
/*! \brief CCP write helper function written in assembly.
9
 *
10
 *  This function is written in assembly because of the timecritial
11
 *  operation of writing to the registers.
12
 *
13
 *  \param address A pointer to the address to write to.
14
 *  \param value   The value to put in to the register.
15
 */
16
void CCPWrite( volatile uint8_t * address, uint8_t value )
17
{
18
  volatile uint8_t * tmpAddr = address;
19

20
    ATOMIC_BLOCK(ATOMIC_RESTORESTATE)
21
    {
22
#ifdef RAMPZ 
23
        RAMPZ = 0; 
24
#endif
25
        asm volatile(
26
        "movw r30,  %0"        "\n\t"
27
        "ldi  r16,  %2"        "\n\t"
28
        "out   %3, r16"        "\n\t"
29
        "st     Z,  %1"       "\n\t"
30
        :
31
        : "r" (tmpAddr), "r" (value), "M" (CCP_IOREG_gc), "i" (&CCP)
32
        : "r16", "r30", "r31"
33
        );
34
    }
35
}
36

37
/**
38
 * \internal
39
 * \brief Check if RTC32 is busy synchronizing
40
 *
41
 * \retval true  Is busy
42
 * \retval false Is ready
43
 */
44
uint8_t rtc32_is_busy(void)
45
{
46
  return RTC32.SYNCCTRL & RTC32_SYNCBUSY_bm;
47
}
48

49
ISR(RTC32_OVF_vect)
50
{
51
    /* Toggle status led */
52
    PORTR.DIRTGL = PIN0_bm;
53
}
54

55

56
int main(void)
57
{
58
    /* Apply a resetr of the VBAT */
59
    VBAT.CTRL |= VBAT_ACCEN_bm;
60

61
    /* Set access enable bit */
62
    CCPWrite((void *)&VBAT.CTRL, VBAT_RESET_bm);
63

64
    /* Enable 32.768kHz crystal oscillator */
65
    VBAT.CTRL |= VBAT_XOSCEN_bm | VBAT_XOSCSEL_bm;
66

67
    /* Wait until oscillator is stable */
68
    while(!(VBAT.STATUS & VBAT_XOSCRDY_bm));
69

70
    /* Enable low power mode for external oscillator */
71
    OSC.XOSCCTRL = OSC_X32KLPM_bm;
72

73
    /* Reset RTC32 module */
74
    RTC32.CTRL = 0;
75

76
    /* Wait until sync done */
77
    while(rtc32_is_busy());
78

79
    /* Set PER to 1024. CLK source of the RTC32 is 1024 ticks / second = 1 Hz */
80
    RTC32.PER = 1024;
81

82
    /* Reset CNT register */
83
    RTC32.CNT = 0;
84

85
    /* Wait until sync done */
86
    while(rtc32_is_busy());
87

88
    /* Enable overflow interrupts */
89
    RTC32.INTCTRL = RTC32_OVFINTLVL_MED_gc;
90

91
    /* Enable real time module */
92
    RTC32.CTRL = RTC32_ENABLE_bm;
93

94
    /* Wait until sync done */
95
    while(rtc32_is_busy());
96

97
    /* Set port C pin 7 as output */
98
    PORTC.DIRSET = PIN7_bm;
99

100
    /* Enable medium priority interrupts */
101
    PMIC.CTRL = PMIC_MEDLVLEN_bm;
102

103
    /* Set sleep mode and enable sleep */
104
    SLEEP.CTRL = SLEEP_SMODE_PSAVE_gc | SLEEP_SEN_bm;    
105

106
    /* Enable global interrupts */
107
    sei();
108

109
    while(1)
110
    {
111
        /* Go sleeping */
112
        asm("sleep");
113
    }
114
}

Freue mich über Anregungen und Fragen.

Viele Grüße
Stefan

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