
Zitat von
BlackDevil
Code ist immer interessant ...
... 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 von
BlackDevil
... obgleich deine Variablen etwas schwierig zu entziffern sind (teilweise) ...
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).
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.
Code:
/* ============================================================================== */
/* === 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
}
/* ============================================================================== */
Da ich gerade beim Initialisieren bin, initialisiere ich auch gleich die beiden
externen Interrupts:
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
}
/* ============================================================================== */
Damit meine Zeiteinheit = 50 µs-Zeitscheiben ausgewertet wird, gibts ne ISR, die diese 50µs-Zeitschnippsel hochzählt:
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
}
}
/* ============================================================================== */
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 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"
}
/* ============================================================================== */
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*.
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.
Lesezeichen