... dabei wollen wir mal festhalten, dass ich im Prinzip immer noch Anfänger bin - ich beschäftige mich grad ein knappes Jahr mit µC´s und mit der Sprache C erst seit letztem Dezember. Beschäftigen heißt ja auch nicht "können".Zitat:
Zitat von BlackDevil
Du loos, ih wohn im beirischn Schwobn, des isch bei iis des Allgei - obwol i a Auslenda bi. Do wiatz scho a bizzle a drAnpassung liaga. (Kann ich bei Bedarf in die eine oder andere europäische Sprache übersetzen).Zitat:
Zitat von BlackDevil
Zuerst muss man mal einen Timer initialisieren. Ich mach das mit dem Timer2, das ist der Timer mit der höchsten Interrupt-Priorität - also der, der als erster bedient wird! Der Timer2 wird bei mir wie folgt initialisiert - denk dran, ich arbeite mit dem mega168 und einem 20MHz-Takt, bei anderen Takten und Zeitschnippsel muss entsprechend angepasst werden. Hier kann ich übrigens nix für die Variablen - die sind im doc vorgeschrieben.
Da ich gerade beim Initialisieren bin, initialisiere ich auch gleich die beidenCode:/* ============================================================================== */
/* === 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 157
TCCR2B |= (1<<CS21); // Prescaler 1/8 / Clock <- CPU doc S 158
OCR2A = 124; // Preset 125 für 50µs bei 20Mhz
TIMSK2 |= (1<<OCIE2A); // Tmr/Cntr2 CompareA interrupt enabled
}
/* ============================================================================== */
externen Interrupts:
Damit meine Zeiteinheit = 50 µs-Zeitscheiben ausgewertet wird, gibts ne ISR, die diese 50µs-Zeitschnippsel hochzählt:Code:/* ============================================================================== */
/* === Initialisierung fuer EXT_INT0/1 auf Pin 4+5/PD2,3 bei m168 ================
$002 jmp SIG_INTERRUPT0 ; IRQ0 Handler _VECTOR(1)
$004 jmp SIG_INTERRUPT1 ; IRQ1 Handler _VECTOR(2) ================ */
void XTI_0_1_init( void )
{ //Initialisiere beide Interrupts auf rising edge
// d.h. EICRA ISC00,01,10+11 auf 1 (doc,S68)
EICRA |= (1<<ISC11)|(1<<ISC10)|(1<<ISC01)|(1<<ISC00);
EIMSK |= (1<<INT1)|(1<<INT0); // und erlaube diese I´s in EIMSK
// Initialisierung der Zeiten: // Der Kürze wegen hier nur für Kanal 0
Iz_diff0 = 0; // Differenz zwischen dem aktuellen und dem
// vorhergehenden Interrupt auf Kanal 0
Iz_xseci0 = 0; // Aktueller Zeitwert (Stand des 50µsec-Zählers)
// Lies die Variable mal so: Integer Zeit "X" (regelungstechnisch
// wird mit "X" der Ist-Wert bezeichnet sec => in Zeiteinheiten,
// aber eben nicht sec sondern 50 µsec, i => istwert 0 .. Kanal
Iz_xsecv0 = 0; // Vorhergehender Zeitwert auf Null initialisieren
}
/* ============================================================================== */
Das Auslesen der Zeitdauer erfolgt in einer ISR die bei fallender Flanke am Pin (siehe Routine) ausgelöst wird:Code:/* ============================================================================== */
/* === Nicht unterbrechbare ISR für timer2 ===================================== */
/* Routine zählt hoch im Takt 20 kHz = 50 µs.
==> Eine Zeiteinheit ist also 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 < 60000) //Timer bis 60 000 ==> 3 sec Datenerfassung möglich
Izeit_1 ++; // und Izeit_1 bleibt in der uint16-Grenze
else
{
Izeit_1 = 0; // ansonsten: Rückstellen auf Null
}
}
/* ============================================================================== */
So, das ist die ganze Sache. Wie bereits erwähnt, bei mir läufts - und die Coladose läuft mit zwei getrennten Motoren prächtig geradeaus. Achtung: es gibt sicher mehrere und auch bessere Möglichkeiten und verständlichere Variablen *gggg*.Code:/* ============================================================================== */
/* === Nicht unterbrechbare ISR für EXT_INT0 auf Pin 46/PD2/mega168 =========== */
/* Routine rechnet den Zeitbedarf vom vorhergehenden zum jetzigen Interrupt aus,
dieser Wert wird z.B. von der Regelung ausgelesen (nur dumm, wenn das erst nach
dem nächsten Interrupt passiert - das ist bei mir aber nicht der Fall! Nennt sich
Softwareengineering *ggggggg*
Der zugehörige Motor auf PD7/PB0 = re,li und PB1 Geschwind./PWM */
ISR(INT0_vect) // hiess mal: ISR(SIG_INTERRUPT0)
{ //
Iz_xseci0 = Izeit_1; //Weise Iz_xsec1 dem akt. Timerwert zu
Iz_diff0 = Iz_xseci0-Iz_xsecv0; //Neue Zeit-Differenz0 ausrechnen
Iz_xsecv0 = Iz_xseci0; //der aktuelle Zeitwert wird "Alter"
}
/* ============================================================================== */
Jetzt hoffe ich nur, dass ich nichts vergessen habe und nicht irgendeine Zeile entfernt habe, die für Deine Zwecke eher verwirrend wäre.
Viel Erfolg
Viel Glück.