XMEGA-A1-USB Mikrocontrollermodul: XmegaA und RTC

Dirk

Administrator
Teammitglied
28. Jan. 2007
4.328
166
63
Mittelhessen, Giessen
Sprachen
  1. ANSI C
  2. C++
  3. C#
  4. Java
  5. Kotlin
  6. Pascal
  7. Assembler
  8. PHP
Hallo zusammen,

da mich des öfteren Forenmitglieder fragen, wie man bei dem Xmega den RTC mit einem externen Uhrenquarz nutzt, stelle ich hierzu einmal ein Beispiel in das Forum.

Zielsystem ist der Xmega128A1 auf dem Mikrocontrollermodul XMEGA-A1-USB.

An dem Oszillatoreingang TOSC1/2 ist ein 32,768kHz Uhrenquarz angeschlossen. Die an PQ3 angeschlossenen LED soll einmal die Sekunde getoggled werden. Der Systemtakt ist nicht wichtig, ich nutze im Beispiel den internen RC-Oszillator mit 2MHz.

Im Beispiel gehe ich folgendermaßen vor:

A. Zuerst wird der 32kHz Oszillator im low power mode konfiguriert und aktiviert, die Taktquelle des RTC wird auf den Oszillator eingestellt (1024Hz).

B. Danach wird der RTC konfiguriert.

C. Nun wird der Overflow Interrupt des RTC freigegeben, der einmal in der Sekunde auftritt.

In der Interrupt-Serviceroutine setze ich das Bit IF_RTC_OVERFLOW in der Variable IntFlags, welches in der Hauptschleife des Hauptprogramms ausgewertet wird. Hier toggle ich dann die LED an PQ3.

Das Beispielprogramm habe ich noch einmal angehängt.

Dirk



CodeBox C

#include <stdlib.h>
#include <stddef.h>
#include "avr_compiler.h"



volatile uint8_t IntFlags;
#define IF_RTC_OVERFLOW 0

ISR(RTC_OVF_vect)
{

IntFlags |= 1<<IF_RTC_OVERFLOW; // Message an das Hauptprogramm

}

int main (void)
{

IntFlags = 0;

// Systemclock: 2MHz (internal RC Oscillator)

PORTQ.DIRSET = 1<<PIN3; // LED an PQ3
PORTQ.OUTCLR = 1<<PIN3; // LED an

// **************************************************************
// A. Zuerst konfigurieren wir Oscillator und Clock-Distribution
// **************************************************************

/*****************************************************************
* OSC
* XOSCCTRL - XOSC Control Register
*
* Bit 5 = X32KLPM: Crystal Oscillator 32.768 kHz Low Power Mode
*
* Bit 3:0 = XOSCSEL[3:0]: Crystal Oscillator Selection
* = 0010 = OSC_XOSCSEL_32KHz_gc (GROUP: 32kHz, SOURCE: 32.768 kHz TOSC)
*
*****************************************************************/

OSC.XOSCCTRL = OSC_X32KLPM_bm | OSC_XOSCSEL_32KHz_gc;


/*****************************************************************
* OSC
* CTRL - Oscillator Control Register
*
* Bit 3 = XOSCEN: External Oscillator Enable
*
*****************************************************************/

OSC.CTRL = OSC_XOSCEN_bm;

// Warten bis External Clock Source stabil und bereit ist
while ((OSC.STATUS & (OSC_XOSCRDY_bm)) != OSC_XOSCRDY_bm) ;


/*****************************************************************
* CLK
* RTCCTRL - RTC Control Register
*
* Bit 2:0 = RTCSRC[2:0]: RTC Clock ource
* = 001 = CLK_RTCSRC_TOSC_gc
* (1.024 kHz from 32.768 kHz Crystal Oscillator on TOSC)
*
* Bit 0 = RTCEN: RTC Enable
*****************************************************************/

CLK.RTCCTRL = ( CLK.RTCCTRL & ~CLK_RTCSRC_gm ) |
CLK_RTCSRC_TOSC_gc | CLK_RTCEN_bm;


// Nun läuft der 32kHz Oszillator im low power mode und das RTC Modul
// erhält einen Clock von 1024Hz


// **************************************************************
// B. Jetzt konfigurieren wir den RTC
// **************************************************************

// Der RTC Counter soll nach exakt 1s überlaufen

RTC.PER = 1023;
RTC.CNT = 0;
RTC.COMP = 0xFFFF;
RTC.CTRL = RTC_PRESCALER_DIV1_gc; // Prescaler 1

// Der RTC Counter erhält nun seinen Takt (1024Hz)


// Da der RTC Counter asynchron zum System seinen Takt erhält, müssen
// wir warten, bis die Register des RTC synchronisiert sind
do {

} while(( RTC.STATUS & RTC_SYNCBUSY_bm ) == RTC_SYNCBUSY_bm);


// **************************************************************
// C. Nun aktivieren wir den Overflow-Interrupt des RTC
// **************************************************************

// Low Level Overflow Interurpt aktivieren
RTC.INTCTRL = ( RTC.INTCTRL & ~( RTC_COMPINTLVL_gm | RTC_OVFINTLVL_gm ) ) |
RTC_OVFINTLVL_LO_gc;

// Low Level Interrupts freigeben
PMIC.CTRL |= PMIC_LOLVLEN_bm;

sei(); // Interrupts global freigeben


// Main Loop

while (1)
{

// Haben wir eine Message von unserer RTC Counter Overflow ISR?
if ((IntFlags & (1<<IF_RTC_OVERFLOW)) == (1<<IF_RTC_OVERFLOW))
{
cli();
IntFlags &= ~(1<<IF_RTC_OVERFLOW); // Ja, Message erhalten, Flag wieder löschen
sei();

PORTQ.OUTTGL = 1<<PIN3; // LED toggle (Periodendauer 1 Sekunde)

}


};


return 0x00;
}
 

Anhänge

  • XMEGA-A1-USB RTC Example.zip
    1,5 KB · Aufrufe: 28

Über uns

  • Makerconnect ist ein Forum, welches wir ausschließlich für einen Gedankenaustausch und als Diskussionsplattform für Interessierte bereitstellen, welche sich privat, durch das Studium oder beruflich mit Mikrocontroller- und Kleinstrechnersystemen beschäftigen wollen oder müssen ;-)
  • Dirk
  • Du bist noch kein Mitglied in unserer freundlichen Community? Werde Teil von uns und registriere dich in unserem Forum.
  •  Registriere dich

User Menu

 Kaffeezeit

  • Wir arbeiten hart daran sicherzustellen, dass unser Forum permanent online und schnell erreichbar ist, unsere Forensoftware auf dem aktuellsten Stand ist und der Server regelmäßig gewartet wird. Auch die Themen Datensicherheit und Datenschutz sind uns wichtig und hier sind wir auch ständig aktiv. Alles in allem, sorgen wir uns darum, dass alles Drumherum stimmt :-)

    Dir gefällt das Forum und unsere Arbeit und du möchtest uns unterstützen? Unterstütze uns durch deine Premium-Mitgliedschaft!
    Wir freuen uns auch über eine Spende für unsere Kaffeekasse :-)
    Vielen Dank! :ciao:


     Spende uns! (Paypal)