Hallo zusammen,
ich stehe vor einem Rätsel. Ein einfaches Programm, was einen Pin
toggelt erzeugt komische hochfrequente Toggles (rot im Bild), dazwischen
die 4ms-Zeitabstände, wie es laut Programm sein sollte:
1
#include<avr/io.h> // importiert im Wesentlichen iom328p.h
Die Skalierung der Zeitleiste unten im Bild ist etwas verwirrend. :)
Ist dies das originale Programm?
Also ich kann da erstmal nicht ungewöhnliches dran sehen.
Detlef Kunz schrieb:> Ist dies das originale Programm?
Ja.
> Also ich kann da erstmal nicht ungewöhnliches dran sehen.
Und woher kommen die rot eingekringelten Toggles? Eigentlich soll der
Timer genau alle 4ms von 64000 auf 0 springen und dann nur einmal
toggeln.
Detlef Kunz schrieb:> Die Skalierung der Zeitleiste unten im Bild ist etwas verwirrend. :)
Die untere ist vergrößert, die Skala macht das Programm so, aber das
dürfte nun kein Problem sein.
Das Programm ist in Ordnung. Du verwendest einen Mega328?
Hmm. Hast du schon mal kontrolliert, ob du unabsichtliche Resets hast
oder ob sonst hardwaremässig alles in Ordnung ist?
tommy schrieb:> gehört in die while(1) Schleife nicht mindestens> ein Semikolon?
Das macht keinen Unterschied. Ich hatte alles rausgelöscht, um den Code
für die Frage so kurz wie möglich zu halten, dann compiliert und dann
gemessen.
Karl Heinz schrieb:> Das Programm ist in Ordnung. Du verwendest einen Mega328?
Ja, ein ATMega328p auf einem Arduino Pro Mini Derivat aus China.
> Hmm. Hast du schon mal kontrolliert, ob du unabsichtliche Resets hast> oder ob sonst hardwaremässig alles in Ordnung ist?
Also ich habe nun die Verbindung zum AVR Dragon Board getrennt, RESET an
VCC gepinnt und die Stromversorgung auf eine Batterie umgestellt. Selbst
das kleine Voltmeter im Bild habe ich noch entfernt. Es bleibt wie im
ersten Bild.
Ich habe auch noch:
1
TCCR1A=_BV(WGM11);
2
ICR1=64000;
ausprobiert (Mode 14), das gleiche in Grün.
Das kann doch nicht sein. ?!
Markus, ich hab's auch mit dem Oszilloskop genau so beobachtet. Bei 6400
und 64000 ist der Effekt ähnlich. Nur wewnn ich z.B. in der ISR den
Timer-Wert auf 63000 setze, dann gibt's gleichmäßige Impulse. Von 63000
bis 64000 gibt's also keine Probleme.
Ich hab' nochmal den Watchdog kontrolliert: Ausgeschaltet und trotzdem
in der while-Schleife resettet. Auch kein Unterschied.
Ich kann mir nicht vorstellen, dass der Prozessor defekt ist, aber ich
probiere nach dem Frühstück mal einen zweiten aus, muss nur noch die
PIN-Leisten anlöten.
Hi,
also am Programm kann ich auch keinen Fehler sehen, es sollte doch
eigentlich ein Rechteck rauskommen.
Es scheint aber so, als ob das Programm jedesmal nachdem in der ISR die
Pins gesetzt wurden irgendein Murks passiert (scheinbar wird die ISR
gleich nochmal aufgerufen... und das mehrmals, komisch ist aber, dass
die beiden Pins (C0/C2) anscheinend immer symmetrisch verändert werden,
d.h. das geschieht wirklich durch die ISR. Würde ein anderer Zustand
z.B. durch einen Reset auftreten, wären beide Pins gleichzeitig
kurzzeitig auf "1".
Außerdem ist die Anzahl der Togglevorgänge immer gerade, sonst wäre in
den 4ms Intervallen auch mal der Zustand von C0/C2 andersrum.
Auch ein Problem mit dem LA (Bitkipper o.ä.) scheidet eigentlich aus, da
der Zustand von C0/C2 immer genau andersrum ist.
Bin auf die Lösung gespannt...
Markus
Markus M. schrieb:> Außerdem ist die Anzahl der Togglevorgänge immer gerade
Bei kleinen Modifikationen (6400 usw., s.o.) ist die Anzahl auch mal
ungerade.
Zumindest scheint das Problem nicht trivial zu sein, daher schon mal
danke für die Antworten.
> Bin auf die Lösung gespannt...
Und ich erst ...
PS: Der hochfrequente Teil entspricht einem Timer-Wert von 62937 =
0xF5D9 vor einem RETI. Aber das hilft wohl auch nicht ...
Ich habe ein sehr ähnliches Problem mit
>ein ATMega328p auf einem Arduino Pro Mini Derivat aus China.
INT0 Interrupt eingestellt auf steigende Flanke.
ldi temp, (1<<ISC00)|(1<<ISC01) ; INT0 steigende Flanke
sts EICRA,temp
ldi temp, (1<<INT0) ; INT0 erlauben
out EIMSK,temp
In der IR Routine wird zum Test nur kurz PortC4 an und aus geschaltet.
;------------------------------------------------------------------
INT0_IR:
in R0,sreg
sbi portc,4
nop
nop
nop
nop
nop
nop
nop
nop
nop
cbi portc,4
out sreg,R0
reti
;------------------------------------------------------------------
Beim 2313 funktioniert das mit meinem Eingangssignal einwandfrei, bei
dem Ard. Pro mini löst er oft bei steigender und fallender Flanke - und
oft 2* kurz hintereinander aus.
Das kann natürlich am Rechteck-Eingangssignal liegen, aber beim 2313
klappts und der Logic Analyzer ist auch damit zufrieden.
Vielleicht haben die Billig Prozessoren irgendein Problem. Ich habe es
aber mit 2 Platinen probiert.
Torsten C. schrieb:> Markus M. schrieb:>> Bin auf die Lösung gespannt...>> Und ich erst ...
Interessiert mich auch.
Kannst du mal den vom Compiler generierten Asm-Code posten? Ich habe
einen Verdacht, was da passieren könnte, dieser Verdacht läßt sich aber
nur anhand des Asm-Code überprüfen.
Notfalls reicht auch die erzeugte *.hex-Datei.
c-hater schrieb:> dieser Verdacht läßt sich aber> nur anhand des Asm-Code überprüfen.>> Notfalls reicht auch die erzeugte *.hex-Datei.
Ich ziehe immer wieder meinen Hut vor Leuten die Asm beherrschen :o
Danke, Helmut! :-) Du warst schneller.
c-hater schrieb:> Kannst du mal den vom Compiler generierten Asm-Code posten? Ich habe> einen Verdacht, was da passieren könnte, dieser Verdacht läßt sich aber> nur anhand des Asm-Code überprüfen.
Sie vollständige Datei ist in der Anlage. Am Interrupt kann ich nichts
falsches erkennen:
1
__vector_13:
2
push r1
3
push r0
4
lds r0,95
5
push r0
6
clr __zero_reg__
7
push r18
8
push r24
9
push r25
10
push r30
11
push r31
12
push r28
13
push r29
14
in r28,__SP_L__
15
in r29,__SP_H__
16
lds r24,toggle
17
tst r24
18
breq .L4
19
ldi r24,lo8(40)
20
ldi r25,0
21
ldi r18,lo8(4)
22
movw r30,r24
23
st Z,r18
24
sts toggle,__zero_reg__
25
rjmp .L3
26
.L4:
27
ldi r24,lo8(40)
28
ldi r25,0
29
ldi r18,lo8(1)
30
movw r30,r24
31
st Z,r18
32
ldi r24,lo8(1)
33
sts toggle,r24
34
.L3:
35
pop r29
36
pop r28
37
pop r31
38
pop r30
39
pop r25
40
pop r24
41
pop r18
42
pop r0
43
sts 95,r0
44
pop r0
45
pop r1
46
reti
Also bei meinem zweiten "Pro Mini Derivat" habe ich auch die "roten
Kringel". :(
Heute hat mir der Postbote ein "Arduino Uno" und ein "Arduino Mega"
gebracht. Ich probier's damit mal ...
Was ich machen würde:
Eine blaue (grüne, gelbe...) LED an irgendeinen noch unbenutzten Pin
eines noch unbenutzten Ports hängen und ganz an den Anfang des Codes ein
paar geeignete Instruktionen einfügen, die diese LED bei jedem
Programmstart kurz aufblitzen lassen. Es ist unendlich wertvoll, sehen
zu können, ob und wann der µC resettet (übrigens bei jedem Projekt).
Weiße (orangene, violette...) LED an einen weiteren unbenutzen Pin eines
noch unbenutzen Ports hängen. Alle unbenutzten Interruptvektoren
definieren und auf eine Extra-ISR zeigen lassen. Diese ISR mit Code
bestücken, der die weiße LED kurz aufblitzen lässt.
Eine kleine, simple Delayroutine schreiben. Verzögerungszeit sinnvoll
wählen - so, dass Du sie auf dem Oszi/Logikanalyzer gut erkennen kannst.
Dann die Delayroutine an allen möglichen "interessanten" Stellen im Code
einfügen. Programm laufen lassen und anhand der auf dem Oszi sichtbaren
Wirkung die Ursache herauszufinden versuchen.
Torsten C. schrieb:> Danke, Helmut! :-) Du warst schneller.> Sie vollständige Datei ist in der Anlage. Am Interrupt kann ich nichts> falsches erkennen
Ich habe mir beide Varianten angeschaut und kann auch nix wirklich
falsches am Code erkennen.
Aufgefallen ist mir nur eins in der Version von Helmut (was allerdings
in diesem Zusammenhang sicher keine Rolle spielt): Warum wird eigentlich
der Stackpointer nicht auf's RAM-Ende initialisiert? Eventuell für
Mega168(P)A übersetzt?
Bei deiner Version ist mir aufgefallen, daß es scheinbar gar keinen Code
zur Initialisierung des Stackpointers gibt. Nun gibt es zwar AVRs, bei
denen das tatsächlich nicht nötig ist, aber der M328P gehört laut
Datenblatt nicht zu diesen, dort steht:
> The Stack in the data SRAM must be defined by the program before any> subroutine calls are executed or interrupts are enabled.
Hi
>dort steht:>> The Stack in the data SRAM must be defined by the program before any>> subroutine calls are executed or interrupts are enabled.
Das mag zwar dort stehen. Aber Initial Value ist für den Stackpointer
RAMEND. Also keine Initialisierung im Programm notwendig.
MfG Spess
spess53 schrieb:> Das mag zwar dort stehen. Aber Initial Value ist für den Stackpointer> RAMEND.
Stimmt, das hatte ich übersehen.
Also kann's auch am Stack nicht liegen. Also Programmfehler
ausgeschlossen, Compilerfehler ausgeschlossen, es bleibt nur die
Hardware.
Hallo Torsten,
ich bin auch gespannt was sich als Grund für dieses komische Verhalten
herausstellt.
Torsten C. schrieb:> PS: Der hochfrequente Teil entspricht einem Timer-Wert von 62937 => 0xF5D9 vor einem RETI. Aber das hilft wohl auch nicht ...
a) Die Periode im hochfrequenten Teil von einem Toggle zum nächsten
scheint ja so um die 100μs lang zu sein, aber wie lang ist sie genau?
Vielleicht führt uns der genaue Wert auf eine Spur.
b) Was für einen Pro Mini hast du? 3.3V oder 5V? 8MHz oder 16MHz? 3.3V
mit 16MHz könnte zu so lustigen Effekten führen.
c) Kannst du mal mit avrdude die Fuses auslesen?
d) Kannst du mal in der ISR
PORTC = _BV(0);
ersetzen durch
PORTC = PORTC & ~_BV(2) | _BV(0);
und
PORTC = _BV(2);
ersetzen durch
PORTC = PORTC & ~_BV(0) | _BV(2);
Sollte keinen Effekt haben wiel ja nur zwei Pins auf Ausgang stehen,
aber vielleicht übersehen wir ja was ...
e) Kannst du mal im Anschluss an
DDRC |= _BV(0); // Port C0: Debugging Port
(Toggle)
DDRC |= _BV(2); // Port C2: Debugging Port
(Toggle)
einfügen:
PORTC |= _BV(2) | _BV(0);
PORTC &= ~(_BV(2) | _BV(0));
Dies, um sicher zu gehen, das tatsächlich kein Reset ststtfinden.
LG, Sebastian
Ich habe alles ausprobiert, es gibt keine Resets, es werden keine
unbenutzten ISRs angesprungen usw. Danke für die vielen Vorschläge.
Ich habe das gleiche Problem mit 'nem "Arduino Uno" und 'nem "Arduino
Mega". Für meinen Teil: Ich vertage das Problem, gehe nun schlafen und
fange morgen auf einem STM32F4Discovery neu an.
Ich will mit meinem Projekt weiter kommen und mich nicht mit diesem
"Mist" herum schlagen. Ich hoffe, Ihr habt Verständnis.
Wenn die Peripherie-Hardware läuft, die Platine vom Platinensammler da
ist und alles funktioniert, versuche ich es nochmal mit 'nem AVR. Dann
mache ich ein SW-Update meiner Toolkette und wenn das nicht hilft, lege
ich den Timer als 16-Bit-Wert parallel auf einen Port.
Hallo zusammen,
nachdem sich mein Frust wieder gelegt hat, bin ich Euch noch eine
Antwort schuldig. Ich bin nochmal alle Eure Hinweise durchgegangen, und
nun gehts. :-)
Ich wurde misstrauisch, als es nach einem POR manchmal ging, obwohl der
LA weiter falsche Pulse anzeigte. Es war eine Kombination aus zwei
Dingen:
1. Der Watchdog
Bei neueren AVR-Typen bleibt der Watchdog auch nach einem Reset durch
den Watchdog aktiviert, siehe AVR-GCC-Tutorial/Der Watchdog.
2. Der LA
Da der LA aber (durch kapazitives Übersprechen?) weiter falsche Pulse
anzeigte, habe ich das erst nicht gemerkt.
Fazit:
Nach dem einfügen der void get_mcusr(void) in der section(".init3") sah
auf dem Oszilloskop alles OK aus. Der LA geht im 250ns-Sample-Mode nun
auch, bei schlelleren Samples kommt halt Müll raus, der so ählich
aussieht, wie das, was ich bei falsch initialisertem WD auf dem Oszi
sah.
Danke nochmal Euch allen. ! :-)
Hi
>1. Der Watchdog>Bei neueren AVR-Typen bleibt der Watchdog auch nach einem Reset durch>den Watchdog aktiviert, siehe AVR-GCC-Tutorial/Der Watchdog.
Warum fummelst du auch am Watchdog rum?
Den aktiviert man, wenn überhaupt, erst dann, wenn ein Programm stabil
läuft.
MfG Spess
spess53 schrieb:> Warum fummelst du auch am Watchdog rum?
Ohne "Fummeln" war der bei mir an. Ist das nicht bei jedem µC so? Gut,
mache arbeiten mit 'nem Bootloader. Der muss den WD aber m.E. auch
erstmal ausschalten.
spess53 schrieb:> AVRs werden mit abgeschaltetem WD ausgeliefert.
An welcher Stelle "abgeschaltet"? Meinst Du die WDTON Fuse? Die war bei
mir auch "inaktiv", der WDT lief m.E. aber trotzdem ohne "Fummeln". Die
Fuse verhindert ja nur das ausschalten. An ist der WD nach einem POR
m.E. trotzdem immer.
Hi
>An welcher Stelle "abgeschaltet"? Meinst Du die WDTON Fuse?
Ja. WDTON ist gelöscht (1)
> Die Fuse verhindert ja nur das ausschalten.
Nein, die bewirkt erst mal, das der WD ohne weitere Aktionen
eingeschaltet ist. Bei gelöschter WDTON-Fuse muss der WD durch dein
Programm eingeschaltet werden.
>Die war bei mir auch "inaktiv", der WDT lief m.E. aber trotzdem ohne>"Fummeln".
Da dein Programm keine Einschaltsequenz enthält kann es nur die
WDTON-Fuse sein. Es sei denn du glaubst an unbefleckte Empfängnis.
>Fazit:>Nach dem einfügen der void get_mcusr(void) in der section(".init3")
Und was macht das genau?
MfG Spess
...diese get_mcusr() Funktion merkt sich den aktuellen Inhalt von MCUSR
in mcusr_mirror und deaktiviert danach den WDT.
Anhand vom mcusr_mirror kann man dann auswerten was der Grund des
letzten Resets war...
Aber trotzdem kann das natürlich nicht "richtig" sein, da der WDT auf
jeden Fall deaktiviert bleiben sollte, wenn die Fuse in dem
entsprechenden Zustand ist. Ich musste mich noch nie um den WDT kümmern.
Evtl. wird der WDT ja durch einen Fehler an einer anderen Stelle aus
versehen aktiviert?
Grüße
Markus
Hmmm, dann ist da das nächste Rätsel: Wie ging der an?
> If the Watchdog is accidentally enabled, for> example by a runaway pointer or brown-out> condition, the device will be reset and the> Watchdog Timer will stay enabled. If the code> is not set up to handle the Watchdog, this might> lead to an eternal loop of time-out resets. To> avoid this situation, the application software> should always clear the Watchdog System Reset Flag> (WDRF) and the WDE control bit in the initialisation> routine, even if the Watchdog is not in use.
Aber eigentlich ist das m.E. nun nicht mehr so wichtig.
Den BOD habe ich nun auch aus.
Frohes neues Jahr!
zu deinem Problem mit der Kapazitiven Einkopplung von Nachbarkanälen des
LA's: Versuche mal die Kanäle leicht zu belasten z.B. mit 50kOhm ob dann
immer noch so ein Übersprechen auftaucht, kannst ja den Wert auf
P5robeweise immer weiter verringern, bis es weg ist.