Hi zusammen,
sorry für ungenaue Überschrift, wusste aber nichts besseres.
Ich habe ein STK500 Board mit ATMega8 drauf. Dieser erzeugt mir ein
40kHz Signal, 20 Perioden lang, welches ich am PB0 abgreife. Als
Taktgeber dient zZt der interne Oszilator auf 8MHz.
Wenn ich mir nun das Signal mit nem Oscar ansehe, fällt mir auf, dass es
nicht immer "gleich" ist.
"Gestartet wird der Ping über einen Schalter am STK500, welcher auf den
EXT_INT0 geht."
Die 40kHz stimmen und meistens ist es ok, manchmal sieht es allerdings
wie wie hier:
http://www2.picfront.org/picture/kO9L3gsYUKs/img/ATM8_Takt01m.JPGhttp://www2.picfront.org/picture/BN9hqzzrXd/img/ATM8_Takt02m.JPGhttp://www2.picfront.org/picture/HxMQLPb6/img/ATM8_Takt03m.JPG
Das tritt absolut willkürlich auf (jedes mal, jedes 3mal, 10mal
garnicht, dann 3mal hintereinander,....) und auch die Periode ist nicht
immer die selbe (1,3,4,8,....)
Und mit diesem Signal kann ich dann so ziemlich gar nichts anfangen :(
mein Code dazu sieht (verkürzt) so aus:
1
WAIT:
2
rjmp WAIT
3
EXT_INT0: ; bei Switch0
4
ldi temp, 1
5
out TCCR0, temp ; starte Timer0 mit prescale=1
6
cbi PORTB, PB0
7
reti
8
TMR0_Int: ; TIMER0 Overflow
9
out TCNT0, timer0 ; setze Startwert für Timer0
10
dec count1 ; dekrementiere count
11
breq COUNTOF
12
13
sbis PORTB, 0 ; pruefe ob PB0 high
14
15
rjmp SetHigh ; wenn PB0 = 0, setze PB0
16
rjmp SetLow ; wenn PB0 !=0, loesche PB0
17
18
SetLow:
19
cbi PORTB, PB0 ; loesche PB0
20
reti
21
22
SetHigh:
23
sbi PORTB, PB0 ; setze PB0
24
reti
Ach ja: Es ist auch egal ob ich den Ausgang offen oder belastet habe.
Ich bekomme das selbe Problem
Kann sich jemand erklären, woran das liegen könnte?
Bin irgendwie am verzweifeln...
Danke
Stefan
Muss es unbedingt PB0 sein? Nimm Timer 2 (der hat ne Compare-Einheit)
und OC2 als Ausgang und generier das Signal in Hardware (Timer im
CTC-Betrieb, Portpin toggeln). Oder nimm einen ATMega88, der hat auch an
Timer 0 eine Compare-Einheit.
Abgesehen davon ist es sehr ungeschickt, nur so ein Codeschnipselchen zu
schicken. Traditionell ist die Wahrscheinlichkeit, dass der eigentliche
Fehler im nicht gezeigten Teil liegt, sehr groß.
hans wrote:
> Der Fehler ist sichtbar: Der Taster prellt, EXT_INT0 und damit> das Timer setzen/starten wiederholt sich.
Wäre auch meine Vermutung. Eine Entprellung sehe ich da nirgends.
Außerdem ist das Auswerten von mechanischen Kontakten mit externen
Interrupts sowieso meist unsinnig.
Findest Du leicht raus, indem Du das ganze oszillografierte Signal
anzeigst. Wenn's nach dem Fehler noch 20 Perioden sind, ist's klar, der
int0 hat nochmal zugeschlagen.
Hallo,
zum Codeschnipsel wurde ja schon was gesagt.
Trotzdem: wie entprellst Du den Taster bzw. verhinderst, daß ein 2. oder
3. auftretender Externer IRQ den Port nicht beliebig wieder auf L setzt?
Danach sieht es mir nämlichn aus. Ext INT wird erkannt, Impulse gehen
los, irgenwo dazwischen prellt der Taster und erzeugt einen weiteren
Impuls, der PB 0 auf L setzt.
Wenn schon auf diese Art, dann den Ext INT in seiner IRQ sofort
ausschalten, am Ende der Impulsfolge evtl. dort noch anstehende IRQs
löschen und dann erst wieder freigeben.
Gruß aus Berlin
Michael
Ok, vielen Dank für die vielen und schnellen Antworten!
Lag wohl wirklich am "nicht entprellen"! Hatte da auch schon mal dran
gedacht, aber warum auch immer, die Spur nicht weiter verfolgt.
....eine Entsprellung hätte die natürlich auch gleich aufm STK500
mitliefern können....
Ich deaktiviere jetzt in "EXT_INT0:" die externen interrupts und setze
sie erst nach Durchlauf des kompletten Programms auf enable.
>am Ende der Impulsfolge evtl. dort noch anstehende IRQs löschen>und dann erst wieder freigeben.
Das ist wohl nicht nötig, da der Interrupt durch eine Flanke ausgelößt
wird.
Den Taster benutze ich auch nur zu Versuchszwecken. Später wird dort
dieser durch ein externes Signal ersetzt.
Bin momentan eh dabei, das Ganze auf Timer2 mit compare mode umzubauen.
Da ich blutiger Anfänger bin, hatte ich mich etwas vor dem doch relativ
komplexen Timer2 etwas gescheut.
Wie gesagt: Danke euch allen!
Stefan
Stefan wrote:
>>am Ende der Impulsfolge evtl. dort noch anstehende IRQs löschen>>und dann erst wieder freigeben.> Das ist wohl nicht nötig, da der Interrupt durch eine Flanke ausgelößt> wird.
Doch, genau das ist nötig! Wenn Du das Interrupt Flag nicht löschst,
bevor Du den Interrupt wieder freigibst, dann wird der Handler sofort
wieder aufgerufen. Das Flag ist dann schließlich noch von der ersten
Prellflanke gesetzt!
Ok, mir war zwar nicht klar, dass das Interrupt Flag gesetzt werden
kann, wenn der externe Int. deaktiviert ist, aber ich werds zu Vorsicht
mal tun...
Danke euch. Mit Timer2 und compare Funktion läufts nun auch problemlos.
Spart ja einiges an Code....
Stefan wrote:
> Ok, mir war zwar nicht klar, dass das Interrupt Flag gesetzt werden> kann, wenn der externe Int. deaktiviert ist,
Wie soll man denn sonst bitteschön Polling machen können? Die Flags
werden immer gesetzt, wenn das betreffende Hardware-Ereignis auftritt.