// Information zur Software
#define VERSIONLANG ("Projekt " __FILE__ " erstellt am " __DATE__ " um " __TIME__ " Uhr")
// GPIO-Pin für externe LED
#define LED_PIN 9
// Ein- und Ausschaltzeit der LED in Vielfachen des Rahmentakts von 62,5 ms (1/16 Sekunde)
#define LED_EIN 2000
#define LED_AUS 500
#define SYS_TCMP 15624 // TCMP = T*F/P-1 = 62,5 ms mit F = 16 MHz und P = 64
#define SYS_SLOTS 64 // 16 Zeitschlitze im Sekundentakt verfügbar
#define SYS_IDLEMAX 0xFFFF // Zähler zur Überwachung der Systemlast
// Abgeleitete System-Konstanten
#define SYS_CLKSEM 8 // Systemtakte pro halbe Sekunde (entspricht SYS_TASKSLOTS/2)
#define SYS_CLKSEC 16 // Systemtakte pro Sekunde (entspricht SYS_TASKSLOTS)
#define SYS_CLKMIN 960 // Systemtakte pro Minute (entspricht 60*SYS_CLKMIN)
// Signalisierung-LED (On-Board_LED Pin D13)
#define LEDPIN 13
// Direkter Registerzugriff auf Pin D13 (speziel für Uno / ATmega328P)
// Pin D13 <-> PB5 (On-Board LED) [Bit 5 in den Registern DDRB und PORTB]
#define iniLED PORTB&=0xDF;DDRB|=0x20;PORTB&=0xDF;
#define setLED PORTB|=0x20;
#define clrLED PORTB&=0xDF;
// Definitionen zur Schleifensynchronisation
#define SYNCINIT initTimer1();iniLED;
#define SYNCLOOP if ( syncloop() ) return;
// Prototypen
void initTimer1(void);
boolean syncloop(void);
// Signalisierung des Overflow Interrupts von Timer 1
volatile boolean sysint = false;
// Überwachung der Systemlast
uint16_t idlecnt = 0;
uint16_t overloadcnt = 0;
// Interrupt Service Routine
ISR(TIMER1_COMPA_vect)
{
sysint = true;
}
// Initialisierung von Timer 1 (62.5 ms System-Interrupt)
void initTimer1(void)
{
__asm("CLI"); // Interrupts sperren
TCCR1A = 0; // Timer Control Register zurücksetzen
TCCR1B = 0; // Timer Control Register zurücksetzen
TCCR1C = 0; // Timer Control Register zurücksetzen
TCNT1 = 0; // Zählregister zurücksetzen
OCR1A = SYS_TCMP; // Vergleichsregister setzen
TCCR1B |= (1 << WGM12); // Vergleichsmodus aktivieren
TCCR1B |= (1 << CS10); // Prescaler 64 (Bit 10 und ...)
TCCR1B |= (1 << CS11); // Prescaler 64 (... Bit 11 setzen)
TIMSK1 |= (1 << OCIE1A); // Timer Compare Interrupt aktivieren
__asm("SEI"); // Interrupts freigeben
}
// Synchronisierungsfunktion
boolean syncloop(void)
{
static uint8_t cnt = 0;
// Schleifensynchronisierung
if ( !sysint )
{
if ( idlecnt < SYS_IDLEMAX ) idlecnt++;
return true;
}
sysint = false;
// Systemtakt (62.5 ms)
if ( !idlecnt ) overloadcnt++; // Systemüberlast!
idlecnt = 0;
// Takt-Zähler
if ( cnt == SYS_CLKSEM ) clrLED;
if ( ++cnt >= SYS_CLKSEC ) {cnt = 0; setLED;}
return false;
}
// Initialisierung
void setup()
{
SYNCINIT; // Initialisierung der Interrupt-Synchronisation
Serial.begin(9600); // Serielles Interface initialisieren
Serial.println(VERSIONLANG); // Information zur Software ausgeben
pinMode(LED_PIN,OUTPUT); // GPIO-Ausgang konfigurieren
digitalWrite(LED_PIN,LOW); // LED ausschalten
}
// Hauptschleife
void loop()
{
// Zähler
static uint16_t cnt = 0;
// Dieser Teil der Hauptscheife läuft unsynchronisiert
SYNCLOOP; // Interrupt-Synchronisation der Hauptschleife
// Dieser Teil der Hauptschleife startet alle 62,5 ms
// LED ansteuern
if ( ++cnt >= LED_EIN+LED_AUS )
{
// Zähler zurücksetzen und LED ausschalten
cnt = 0;
digitalWrite(LED_PIN, LOW);
// Serial.println(cnt);
}
Serial.println(cnt);
// LED einschalten (Ende der Ausschaltzeit)
if ( cnt == LED_AUS ) {
digitalWrite(LED_PIN, HIGH);
}
}