Hallo, vielleicht kann mir einer von euch mit meinem Problem weiterhelfen. Kurz zum Aufbau meiner Schaltung. Der uC soll en PB0 eine PWM eines RC-Empfängers auswerten. Dazu wird ein Interrupt bei PB0=high ausgelöst. Dieser startet den Counter0. Ist PB0=low wird der Counter gestoppt und das Register ausgewertet. Das Programm läuft soweit durch. Jedoch wird der Ausgang zwischenzeizlich auf low gesetzt, obwohl dieses nicht sein dürfte. Was mache ich da falsch? Es scheint egal zu sein, ob ich den Timer starte und stopppe oder einfach das Register auf Null setze, wenn der Interrupt ausgelöst wird. Ich habe erst an den Stack gedacht, aber das Programm sollte diesen nicht überfordern. Gruß Carsten
Möglicherweise ne Race-Condition? Du greifst nicht-atomar auf 16-Bit Variablen zu, die in der ISR geändert werden. AVR kann einen int nicht in einer Instruktion lesen/schreiben. Wenn eine ISR innerhalb des Zugriffs reinhaut, gibt's Phantasiewerte. Johann
Du verwendest PB2 statt PB0! Das hier hält definitiv keinen Timer an :-) TCCR0B |= (0<<CS00) | (0<<CS01) | (0<<CS02); Außerdem sollte der Timer beim initialisieren noch nicht gestartet werden, sondern erst bei der ersten flanke. Ob der Rest deines Progs so stimmt, weiß ich nicht, vorallem die Timereinstellung, Auflösung etc. Ich hätt es wahrscheinlich anders gelöst: INT0 als "on change" verwenden. je nach Zustand von PB2 Timer starten oder {stopen, auslesen, rücksetzen}. Den gemessenen Timerwert einfach in ne globale volatile Variable stecken und gemütlich in der Main auswerten. Eventuell noch eine Plausibilitätsprüfung (zu kurze Pulse sind ungültig oder so). Wenn dus paranoid Wasserdicht machen willst musst du noch Funktionen gegen eine Interruptüberlast einbauen. (z.B. Taubschalten des Interrupts für eine Gewisse zeit nach der letzten fallenden Flanke). Wenn du nämlich durch irgend einen dämlichen Zufall 10k Pulse pro Sekunde auf deiner Int-Leitung hast, kommt deine Main nicht mehr dran! Außerdem nimm statt "int" "uint8_t", dann hast du auch keine Probs mit "atomar". Dein Timer ist eh nur 8 Bit breit.
Hallo, danke für die schnellen Antworten. Laut Datenblatt soll der Timer mit "TCCR0B |= (0<<CS00) | (0<<CS01) | (0<<CS02)" gestoppt werden. zb. TCCR0B |= (1<<CS00) | (0<<CS01) | (0<<CS02) startet den Timer sofort. Ich werde das mit "uint8_t" mal testen. Des weiteren bin ich der Meinung das der Counter0 doch ein 8-bit Timer ist. Zumindest habe ich das Datenblatt so verstanden. Gruß Carsten
Hallo, Du hast zwar das Datenblatt verstanden, die Bitmanipulation in C aber nicht... Eine 0 konnst Du hinschieben wie Du willst, es bleibt 0. Ein Register mit 0 ver-odert ändert sich also garnicht. TCCR0B &= ~((1<<CS00) | (1<<CS01) | (1<<CS02)); passt da eher. Gruß aus Berlin Michael
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.