Code:
/* >> Stand ..\C5_Ronny-5_etc\ALCo\ALCo_tmrij.c
=============================================================================== =
Target MCU : ATmega1284p
Target Hardware : siehe main
Target cpu-frequ. : siehe main 20 MHz Quarz, vgl. Current Conf. Options
=============================================================================== =
*** Versionsgeschichte:
x03 19Sep22 1730 alle Quellfiles : Filenummern aktualisieren auf ~03~
====================
x40 6Aug16 1204 Versionsupdate nach erfolgter Uebernahme ins Studio7 x
x00 14Jul15 1730 Übernahme des Originals ARCo_x23.c x23 14Jun15 1500
=============================================================================== =
*** Aufgabenstellung : Software RJjr, ArmLiController/Servobetrieb, ATmega1284p
Original: ...\C5_Ronny-5_etc\ARCo\ARCo_x.. siehe main
============================================================================== */
// FP FP FP FP FP FP FP FP FP FP FP FP FP FP FP FP FP FP FP FP FP FP FP FP FP FP =
/* == Funktionsprototypen
// - - - - - - - - - - - - - - - -
void TC0PWM_init(void) ; // Tmr/Ctr0 initialisieren für PWM-Signal 36+ kHz
void IRLEDset (u8 speed1) ; // Relative Pulslänge auf OC0B/PB4 setzen
void TC1TMR_init(void) ; // Init Timer/Counter 1 für 2 ms Servoperiode
void TC1TMR_on(void) ; // Init Timer/Counter enable
void TC1TMR_off(void) ; // Init Timer/Counter disable
ISR (TIMER1_COMPA_vect) ; // Servo Svpt aktuell wählen + Servorampe starten
ISR (TIMER1_COMPB_vect) ; // VECTOR 9 S 65
void TC2TMR_init (void) ; // Init Tmr/Cntr2, 8-Bit bei 20 kHz => 50 µs
void TC2_stop (void) ; // Stoppe Tmr/Cntr 2
ISR (TIMER2_COMPA_vect) ; // Routine zählt hoch, bei 20 kHz => 50 µs
void wms (uint16_t ms) ; // Programm pausieren lassen
void wmus (uint16_t us) ; // Wait in MikrosekundenD
// FP FP FP FP FP FP FP FP FP FP FP FP FP ******************************* */
// FP FP FP FP FP FP FP FP FP FP FP FP FP
/* **************************************************************************** **
** **************************************************************************** */
// ============================================================================= =
// ============================================================================= =
// Routine initialisiert Timer0/PINB4 auf mega1284 für die IR-LED
// siehe KoCo .. Timerroutinen_zum_IR-LED_schalten.txt
// ===============================================================================
// == Initialisierung von Timer0/PINB4 auf mega1284 für die IR-LED
void TC0PWM_init(void) // Tmr/Ctr0 initialisieren für PWM-Signal 36+ kHz
{ //
TCCR0A |= (1<<WGM00); // Phase Correct PWM mode 106
TCCR0B |= (1<<WGM02); // ###>>> mit TOP = OCR0A 106
TCCR0B |= (1<<CS01); // => clk/8 => 35,7 kHz mit OCR0A=35 108
TCCR0A |= (1<<COM0B1); // Clr OC0B on Compare Match when up-counting 106
// Set OC0B on Compare Match when down-counting
OCR0A = 35; // Phase Correct PWM mode 5 => OCR0A ist TOP 106
OCR0B = 17; // =>PWM-Startwert => ca. 50 % duty cycle
// Anmerkg: OCR0A=35 und Vorteiler clk/8 => 20*10e6 / 8 / 35 / 2 = 35 714 Hz
// Die letzte Division (durch 2) macht die Frequenztheorie selbst *ggg*
// Steuern der IR-Modulationsfrequenz durch OCR0B als "zweiter" Vorteiler
// ###>>> Die ISR (TIMER2_COMPA.. enthält einen kleinen IR-LED-Wobbel !!
TIMSK0 &= ~(1<<OCIE0A); // Tmr/Cntr0 Oput CompA Mtch intrpt disabld
TIMSK0 &= ~(1<<OCIE0B); // Tmr/Cntr0 Oput CompB Mtch intrpt disabld
//TIMSK0 |= (1<<TOIE0); // Tmr/Cntr0 Overflow interrupt enabled
return; // Ende
} // Ende void TC0PWM_init(void)
// ============================================================================= =
// ============================================================================= =
void IRLEDset (u8 speed1) // Relative Pulslänge auf OC0B/PB4 setzen
{OCR0B = 60;} // z.B. für SFH5110
// ============================================================================= =
// ============================================================================= =
// == Timer Aufgabe: Servo mit Soft-PWM ansteuern auf wählbarem Port
// Beispiel: Set TCNT1 to 0x01FF : TCNT1 = 0x1FF;
// Read TCNT1 into i : i = TCNT1;
// - - - - - - - - - - - - - - - -
void TC1TMR_init(void) // Init Timer/Counter 1 für 2 ms Servoperiode
{ //
TCCR1B |= (1<<WGM12); // WGM12 => CTC, TOP = OCR1A S135
TCCR1B |= (1<<CS11); // CS11+10 <=> clk/8 => 2,500 MHz S136
OCR1A = OCR1AV; // 10x OCR1AV = 63990=> alle 25,60 ms 1 Interrupt
// Interrupt zählt bis 6400 !
OCR1B = OCR1BV; // OCR1B = {???} => 1-2 ms Rampe
// TIMSK1 |= (1<<OCIE1A); // Tmr/Cntr1 Oput CompA Mtch intrrpt enabled
// - - - - - - - - - - - - - - - -
SetBit (PORTC, L1r); // rtLED ein, Kontrolle für Servotimer-init
}
// ============================================================================= =
// ============================================================================= =
// == Timer1
// - - - - - - - - - - - - - - - -
void TC1TMR_on(void) // Init Timer/Counter enable
{ //
TIMSK1 |= (1<<OCIE1A); // Tmr/Cntr1 Oput CompA Mtch intrrpt enabled
Svpt = 1; // Zeiger auf den aktuellen Servo
}
// ============================================================================= =
// ============================================================================= =
// == Timer1
// - - - - - - - - - - - - - - - -
void TC1TMR_off(void) // Init Timer/Counter disable
{ //
TIMSK1 &= ~(1<<OCIE1A); // Tmr/Cntr1 Oput CompA Mtch intrrpt disabled
OCR1B = 0; // Servorampe auf Null setzen
Svpt = 1; // Zeiger auf den aktuellen Servo
}
// ============================================================================= =
// ============================================================================= =
// === ISR für TIMER1_COMPA_vect, VECTOR 16 (vgl. S 65) ==================== =
// Zehn Servos umlaufend ansteuern. Es gibt 2 Fälle:
// 1. SerPos1 _ODER_ SerPos2 ist =|= 0, dann ist dies Srv_tm
// 2. SerPos1 und SerPos2 sind belegt, dann MUSS SDelta auch belegt sein,
// sonst gilt SerPos1
// Es wird SerMal von Posa nach Posb oder zurück gefahren, je nach SDelta
/* **************************************************************************** **
** **************************************************************************** */
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
ISR (TIMER1_COMPA_vect) // Servo[Svpt] wählen + dessen Rampe starten
{ //
u8 xt; // Kurzschreibweise für Servopointer
// xt = NxtSvpt; //
// - - - - - - - - - - - - - - -
Svpt ++; // Pointer für diesen, aktuellen Servo eins rauf
if ((Svpt < 1) || (Svpt > Svmx)) Svpt = 1; // und eingrenzen auf {1-10}
xt = Svpt + 1; // Pointer auf nächsten Servo berechnen
if ( xt >= 11) xt = 1; // .. Überlauf abfangen
// - - - - - - - - - - - - - - -
// Für den aktuellen Servopointer liegt ein korrekter Wert Srv_tm[nr] vor
// Den aktuellen Srv_tm-Wert auf zulässige Schranken begegrenzen, vgl. kal_0
// und vor dem Setzen Offset draufrechnen. ##########################
if ( SrvCHK ) // Prüfung nur, wenn ServoCHECK aktiv !!
{ //
if ( Srv_tm[Svpt] < SrvMin [Svpt] ) Srv_tm[Svpt] = SrvMin [Svpt];
if ( Srv_tm[Svpt] > SrvMax [Svpt] ) Srv_tm[Svpt] = SrvMax [Svpt];
} //
// - - - - - - - - - - - - - - - -
switch (Svpt) //
{ //
case 1: SetBit ( PC, Servo1 ); break;
case 2: SetBit ( PC, Servo2 ); break;
case 3: SetBit ( PC, Servo3 ); break;
case 4: SetBit ( PC, Servo4 ); break;
case 5: SetBit ( PC, Servo5 ); break;
case 6: SetBit ( PC, Servo6 ); break;
case 7: SetBit ( PA, Servo7 ); break;
case 8: SetBit ( PA, Servo8 ); break;
case 9: SetBit ( PA, Servo9 ); break;
case 10: SetBit ( PA, Servo10); break;
default: break; // hierher würde noch n Fehlerflag passen
} // Ende switch (Svpt)
// - - - - - - - - - - - - - - -
// OCR1B = Srv_tm[Svpt]; // Stellwert ist durch Rampenwert Srv_tm definiert
OCR1B = Srv_tm[Svpt] + Seroff [Svpt]; // Rampenwert ist mit Srv_tm definiert
TIFR1 |= (1<<OCF1B); // ??? Klappt immer wenn dies gesetzt wird
TIMSK1 |= (1<<OCIE1B); // Tmr/Cntr1 CompB Match interrupt enabled
// d.h. Timer1B starten <=> nächster Servo...
// - - - - - - - - - - - - - - -
// - - - - - - - - - - - - - - -
// ########>>>>>>>> Und nun wird der Interupt erlaubt, damit
// ########>>>>>>>> die ISR nicht zuuuu lange dauert.
sei(); // ########>>>>>>>> Erlaube nested Interrupts
//======
// - - - - - - - - - - - - - - -
// rtLED blinken => Servotimer-Funktionskontrolle etwa im Sekundentakt
if ( IsBitSet ( FlgLED, 2 )) Tglpt ++; // Togglepointer rauf wenn Flag
if (Tglpt == 368) Tglpt = 1; // Ca. Sekundentakt als Funktionskontrolle
if (Tglpt == 1) SetBit (PrtLED, L1r); //
if (Tglpt == 2) ClrBit (PrtLED, L1r); // EIN kurzer Blinkie pro Sekunde
// - - - - - - - - - - - - - - -
// - - Wert für nächsten Servo holen wenn möglich
// Servowert >>holen<< von SrvZa1 oder so derzeit nicht installiert
// es wird >>nur<< mit den Daten in SrvZa0 ff gefahren, solange
// SrvFg0 nicht Null ist.
if ( SrvFu0[xt] ) // Flag ist !0 wenn Daten existieren ! WENN nicht
{ // Null, dann Daten so lange auswerten, bis
// das letzte Teilstück gefahren wurde
switch (SrvFu0[xt]) //
{ //
// - - - - - - - - - - - - - - -
case 1: // Standardfahrt von akt. Pos. nach ~Za~
Srv_tm[xt] = SrvZa0[xt]; // Direktfahrt
SrvFu0[xt] = 0; // quittiere Datenübernahme
SrvFg0[xt] = 0; // und hier
break;
// - - - - - - - - - - - - - - - -
case 6: // Fahre erste Servoperiode Richtung "Anfang" = ~Za0~
// Aufgabenstellung:
// Fahre von ~tm~ nach ~Za~ mit reduzierter Geschwindigkeit
// ==> bestimme das vorzeichenrichtige SrvIc0
// prüfe ob das nächste Teilstück das Ziel erreicht
// dann Ende des ERSTEN Teilstücks,
// Rest wird in case 61 gefahren
// ansonsten fahre das erste Teilstück,
// Rest wird in case 61 gefahren
// Evtl. zweites Teilstück nach ~Zb0~ in case 62
// TeilstreckenAnzahl für Fahrt mit SrvZx0[]-Tupel
if ( Srv_tm[xt] == SrvZa0[xt] )
{ //
SrvFu0[xt] = 61; // ... Flag 61 für Weiterfahrt setzen
break;
}
// Prüfe ob vom aktuellen ~tm~ nach ~Za~ In- oder Decrement notwendig ist
if (Srv_tm [xt] > SrvZa0[xt] ) SrvIc0[xt] = - 1 * abs (SrvIc0[xt]);
if ( Srv_tm[xt] > SrvZa0[xt] ) // DEcrementieren wenn ~tm~ > Za0 =>
// Ab hier ist ~tm~ > ~Za0~ ! ! !
{ // => Negatives Vorzeichen sicherstellen
if ( (Srv_tm[xt] + SrvIc0[xt]) < SrvZa0[xt] )
// gehts schon beim ersten Teilstück zu WEIT ?!?!
{ //
Srv_tm[xt] = SrvZa0[xt]; // => dann fahre nur bis zum Teil-Ende
SrvFg0[xt] --; // Teilstreckenende = erreicht => dekrem.
if ( SrvFg0[xt] <= 0 ) // WENN letztes Teilstück
{ //
SrvFu0[xt] = 0; // quittiere sofort die Datenübernahme
SrvFg0[xt] = 0; // und TeilstreckenAnzahl auf Null setzen
// ###>>> Ein anschließendes break ist erstmal unsinnig, weil noch
// der zweite Punkt, ~Zb0~, angesteuert werden muss.
// ###>>> Ein anschließendes break ist erstmal unsinnig, weil noch
// KANN sinnvoll sein, WENN nur ein Teilstück möglich ist
} // Ende if ( SrvFg0[xt] <= 0 )
} // NOCH if ( (Srv_tm[xt] + SrvIc0[xt]) < SrvZa0[xt] )
else // andernfalls ist das erste Teilstück hier nicht zu WEIT
{ // .. d.h. ~tm~ < ~Za0~ ! ! !
Srv_tm[xt] = Srv_tm[xt] + SrvIc0[xt]; // nächster Zielpunkt
SrvFu0[xt] = 61; // ... Flag 61 für Weiterfahrt setzenOK
} // Ende if ( (Srv_tm[xt] + SrvIc0[xt]) < SrvZa0[xt] )
} // NOCH if ( Srv_tm[xt] > SrvZa0[xt] ) ...
else // Ab hier ist ~tm~ < ~Za0 <=> also INcrementieren
{ //
SrvIc0[xt] = abs (SrvIc0[xt]); // Positives Increm. sicherstellen
if ( (Srv_tm[xt] + SrvIc0[xt]) > SrvZa0[xt] ) // ?? zu WEIT ??
{ //
Srv_tm[xt] = SrvZa0[xt]; // => dann fahre nur bis zum Teil-Ende
SrvFg0[xt] --; // dekrementieren
if ( SrvFg0[xt] <= 0 ) // WENN letztes Teilstück
{ //
SrvFu0[xt] = 0; // und quittiere sofort die Datenübernahme
SrvFg0[xt] = 0; // und TeilstreckenAnzahl auf Null setzen
// ###>>> Ein anschließendes break ist erstmal unsinnig, weil noch
// der zweite Punkt, ~Zb0~, angesteuert werden muss.
// KANN sinnvoll sein WENN nur ein Teilstück möglichnötig ist
} // Ende if ( SrvFg0[xt] <= 0 )
} // NOCH if ( (Srv_tm[xt] + SrvIc0[xt]) > SrvZa0
else // andernfalls
{ //
Srv_tm[xt] = Srv_tm[xt] + SrvIc0[xt]; // nächster Zielpunkt
SrvFu0[xt] = 61; // ... Flag 61 für Weiterfahrt setzenOK
} // Ende if ( (Srv_tm[xt] + SrvIc0[xt]) < SrvZa0
} //
break; // Ende case 6: ... ERSTE Servoperiode Richtung ~Za0~
// - - - - - - - - - - - - - - - -
case 61: // Ausführung Hin-Herfahrt nach ~Za/Zb~ mit reduz Geschwindigkeit
// ###>>> HIER Fahrt nach ~Za0~ nach Abarbeiten von case 6
if (Srv_tm[xt] > SrvZa0[xt]) SrvIc0[xt] = - 1 * abs (SrvIc0[xt]);
if ( SrvIc0[xt] < 0 ) // Decrementieren oder ??
{ // ==> ab hier DE-crementieren
if ( (Srv_tm[xt] + SrvIc0[xt]) < SrvZa0[xt] ) // dann zu WEIT !!
{ //
Srv_tm[xt] = SrvZa0[xt]; // => Fahre nur bis zum Ziel ~Za0~
SrvFg0[xt] --; // Teilstrecke runtertickern
if ( SrvFg0[xt] == 0 ) // Alle Teilstrecken abgefahren ?
{ //
SrvIc0[xt] = 0; // Daten übernehmen
SrvFu0[xt] = 0; // Daten übernehmen
break; // und Ende der Fahrt
} //
SrvFu0[xt] = 62; // Umschalten auf Fahrt nach ~Zb0~
SrvIc0[xt] = -1 * SrvIc0[xt]; // Vorzeichenwechsel
} // NOCH if ( (Srv_tm[xt] + SrvIc0[xt]) < SrvZa0
else // else if ( (Srv_tm[xt] + SrvIc0[xt]) < SrvZa0
{ //
Srv_tm[xt] = Srv_tm[xt] + SrvIc0[xt]; // NUR nächster Zielpunkt
} // Ende if ( (Srv_tm[xt] + SrvIc0[xt]) < SrvZa0
} // Ende if ( SrvIc0[xt] < 0 )
else // Ab hier wird IN-crementiert
{ //
if ( (Srv_tm[xt] + SrvIc0[xt]) > SrvZa0[xt] ) // dann zu WEIT !!
{ //
Srv_tm[xt] = SrvZa0[xt]; // => Fahre nur bis zum Ziel
SrvFu0[xt] = 62; // Umschalten auf Fahrt nach ~Zb0~
SrvFg0[xt] --; // Teilstrecke runtertickern
if ( SrvFg0[xt] == 0 ) // Alle Teilstrecken abgefahren ?
{ //
SrvIc0[xt] = 0; // Daten übernehmen
SrvFu0[xt] = 0; // Daten übernehmen
break; // und Ende der Fahrt
} //
} // NOCH if ( (Srv_tm[xt] + SrvIc0[xt]) > SrvZa0
else // andernfalls
{ //
Srv_tm[xt] = Srv_tm[xt] + SrvIc0[xt]; // NUR nächster Zielpunkt
} // Ende if ( (Srv_tm[xt] + SrvIc0[xt]) > SrvZa0
} //
break; // Ende case 61: ... Fahrt nach ~Za0~
// - - - - - - - - - - - - - - - -
case 62: // Ausführung Hin-Herfahrt nach ~Za/Zb~ mit reduz Geschwindigkeit
// HIER Fahrt nach ~Zb0~ nach Abarbeiten von case 6
if (Srv_tm[xt] > SrvZb0[xt]) SrvIc0[xt] = - 1 * abs (SrvIc0[xt]);
if ( SrvIc0[xt] < 0 ) // Decrementieren oder ??
{ // ==> ab hier also decrementieren
if ( (Srv_tm[xt] + SrvIc0[xt]) < SrvZb0[xt] ) // dann zu WEIT !!
{ //
Srv_tm[xt] = SrvZb0[xt]; // => Fahre nur bis zum Ziel ~Zb0~
SrvFg0[xt] --; // Teilstrecke runtertickern
if ( SrvFg0[xt] == 0 ) // Alle Teilstrecken abgefahren ?
{ //
SrvIc0[xt] = 0; // Daten übernehmen
SrvFu0[xt] = 0; // Daten übernehmen
break; // und Ende der Fahrt
} //
SrvFu0[xt] = 61; // Umschalten auf Fahrt nach ~Zb0~
SrvIc0[xt] = -1 * SrvIc0[xt]; // Vorzeichenwechsel
} // NOCH if ( (Srv_tm[xt] + SrvIc0[xt]) < SrvZb0
else // andernfalls
{ //
Srv_tm[xt] = Srv_tm[xt] + SrvIc0[xt]; // NUR nächster Zielpunkt
} // Ende if ( (Srv_tm[xt] + SrvIc0[xt]) < SrvZb0
} // Ende if ( SrvIc0[xt] < 0 )
else // Ab hier wird incrementiert
{ //
if ( (Srv_tm[xt] + SrvIc0[xt]) > SrvZb0[xt] ) // dann zu WEIT !!
{ //
Srv_tm[xt] = SrvZb0[xt]; // => Fahre nur bis zum Ziel
SrvFg0[xt] --; // Teilstrecke runtertickern
if ( SrvFg0[xt] == 0 ) // Alle Teilstrecken abgefahren ?
{ //
SrvIc0[xt] = 0; // Daten übernehmen
SrvFu0[xt] = 0; // Daten übernehmen
break; // und Ende der Fahrt
} //
SrvFu0[xt] = 61; // Umschalten auf Fahrt nach ~Zb0~
SrvIc0[xt] = -1 * SrvIc0[xt]; // Vorzeichenwechsel
} // NOCH if ( (Srv_tm[xt] + SrvIc0[xt]) > SrvZb0
else // andernfalls
{ //
Srv_tm[xt] = Srv_tm[xt] + SrvIc0[xt]; // NUR nächster Zielpunkt
} // Ende if ( (Srv_tm[xt] + SrvIc0[xt]) > SrvZb0
} //
break; // Ende case 62: ... Fahrt nach ~Zb0~
// - - - - - - - - - - - - - - -
case 9: // Standardfahrt von akt. Pos. nach ~a~
Srv_tm[xt] = SrvZa0[xt]; // Direktfahrt
SrvFu0[xt] = 0; // quittiere Datenübernahme
break; // Ende case 9: ... Standardfahrt von akt. Pos. nach ~a~
// - - - - - - - - - - - - - - -
default:
break;
} // Ende switch (SrvFu0[xt])
} // Ende if ( !( SrvFg0[xt] ) ) // Flag is..
return; //
// - - - - - - - - - - - - - - -
} // Ende ISR (TIMER1_COMPA_vect)
// ============================================================================= =
// ============================================================================= =
// === Nicht unterbrechbare ISR für TIMER1_COMPB_vect ===================== =
ISR (TIMER1_COMPB_vect) // VECTOR 18 S 65
{ //
TIMSK1 &= ~(1<<OCIE1B); // Tmr/Cntr1 CompB Match interrupt disabled
// - - - - - - - - - - - - - - -
switch (Svpt)
{ //
case 1: ClrBit ( PC, Servo1 ); ClrBit ( PA, Servo10); break;
case 2: ClrBit ( PC, Servo2 ); ClrBit ( PC, Servo1 ); break;
case 3: ClrBit ( PC, Servo3 ); ClrBit ( PC, Servo2 ); break;
case 4: ClrBit ( PC, Servo4 ); ClrBit ( PC, Servo3 ); break;
case 5: ClrBit ( PC, Servo5 ); ClrBit ( PC, Servo4 ); break;
case 6: ClrBit ( PC, Servo6 ); ClrBit ( PC, Servo5 ); break;
case 7: ClrBit ( PA, Servo7 ); ClrBit ( PC, Servo6 ); break;
case 8: ClrBit ( PA, Servo8 ); ClrBit ( PA, Servo7 ); break;
case 9: ClrBit ( PA, Servo9 ); ClrBit ( PA, Servo8 ); break;
case 10: ClrBit ( PA, Servo10); ClrBit ( PA, Servo9 ); break;
default: break; // hierher würde noch n Fehlerflag passen
}
// - - - - - - - - - - - - - - -
} // Ende ISR (TIMER1_COMPB_vect)
// ============================================================================= =
// ============================================================================= =
// === Initialisierung fuer Timer2 mega168 ==================================== =
void TC2TMR_init (void) // Init Tmr/Cntr 2, 8-Bit auf 20 kHz = 50 µs
{ //
TCCR2A |= (1<<WGM21); // Timer im CTC-Mode, Top=OCR2A doc S 156
TCCR2B |= (1<<CS21); // Prescaler 1/8 / Clock <- CPU doc S 157
OCR2A = 124; // Preset 124 für 50µs bei 20Mhz
TIMSK2 |= (1<<OCIE2A); // Tmr/Cntr2 CompareA interrupt enabled
// Izeit_1 = 20000; // Laufzeit nullen - unabhängig von Isecndn !!
ClrBit (PrtLED, L1g); // gnLED/PD4 ausschalten
tmr1 = tmrAN = 0; // Timer nullen
} //
// ============================================================================= =
// ============================================================================= =
// === Stoppen Timer2 mega168
void TC2_stop(void) // Stoppe Tmr/Cntr 2
{ //
TCCR2A &= ~(1<<WGM21); // Timer WGM21 resetten
TIMSK2 &= ~(1<<OCIE2A); // Tmr/Cntr2 CompA interrupt DIS abled
} //
// ============================================================================= =
// ============================================================================= =
// === Nicht unterbrechbare ISR für timer2 ==================================== =
// Routine zählt hoch im Takt 20 kHz = 50 µs. Der Zählerwert wird von den ISR für
// EXT_INT0 und -INT1 ausgelesen und den Werten Iz_yseci zugewiesen
ISR (TIMER2_COMPA_vect) // Vektor 7
{ //
// - - - - - - - - - - - - - - - -
if ( Izeit_1 ) //Interrupt-Timer = 1 ... 20 000 ... (1 sec blink)
// WENN Izeit_1 =|= Null => Ausdruck ist wahr => Anweisung wird ausgeführt
{ //
Izeit_1 --; // ###>>> Izeit_1 ist aktuell int16_t ==>>
// Izeit_1 bleibt bis 32000 in der int16-Grenze
} // siehe if ( Izeit_1 )
else // Eine Sekunde ist voll =>
{ //
Izeit_1 = 20000; // Rückstellen auf 20000
Isec_alt = Isecundn; // Die aktuelle Sekunde (Überlauf!!) sichern
Isecundn ++; // Boardzeit-Sekunden hochzählen, max 9 Std
Isec_lok ++; // Lokale Sekunden hochzählen, kann überlaufen,
// ... der wird IRGENDWO im Programm gebraucht
ToggleBit (PORTD, L1g); // LED/PC4 toggeln, HEARTBEAT
// Allzwecktimer tmr1 - siehe ~com~
if ( tmr1 ) tmr1 --; // einfach tickern bis Null
if ( tmrAN ) tmrAN --; // Downcounter 0,1 sec für ~AN1~
// - - - - - - - - - - - - - - - -
} // Ende if ( Izeit_1 )
if ( Izeit01 ) //Interrupt-Timer 01, Zehntelsekundentimer
{ //
Izeit01 --; // ###>>> Izeit01 für 0,1 sec - Timer
} // siehe if ( Izeit_1 )
else // Eine 1/10tel Sekunde ist voll =>
{ //
Izeit01 = 2000; // Rückstellen auf 20000
// Allzwecktimer - siehe ~com~
if ( tmrAN01 ) tmrAN01 --; // einfach tickern bis Null
// - - - - - - - - - - - - - - - -
} // Ende if ( Izeit01 )
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
return; //
} //
// ============================================================================= =
// ============================================================================= =
// ============================================================================= =
//### Programm 1 ms pausieren lassen !! Der Pausenwert ist nur experimentell !
void wms(uint16_t ms)
{
for(; ms>0; ms--)
{
uint16_t __c = 4000;
__asm__ volatile (
"1: sbiw %0,1" "\n\t"
"brne 1b"
: "=w" (__c)
: "0" (__c)
);
}
}
// ============================================================================= =
// ============================================================================= =
// ============================================================================= =
//### Programm 1 µs MIKROsekunde pausieren lassen !! Pausenwert EXerimentell !
void wmus (uint16_t us) // Wait in Mikrosekunden
{
for(; us>0; us--)
{
uint16_t __c = 4;
__asm__ volatile (
"1: sbiw %0,1" "\n\t"
"brne 1b"
: "=w" (__c)
: "0" (__c)
);
}
}
// ============================================================================= =
// ============================================================================= =
// ===== ENDE Subroutinen ================================================= =
// ============================================================================= =
Lesezeichen