Hallo liebes Forum :-)
Ich hoffe ihr könnt mir mal etwas erklären.
Ich habe ein Programm auf einem Attiny24 laufen, welches den PT2272
Funkdecoder immitiert. Allerdings mit Lernfunktion und zusätzlichem
Ein-/Austaster.
Nun habe ich während des Programmablaufs mehrere Zustände, die ich
erfassen und Festhalten muss. Dazu habe ich ein Register, indem ich alle
Zustände mit Bit Operationen speichere und wieder abrufe. Also ähnlich
dem Statusregister.
Da ist auch der manuelle Ein-/Austaster mit drin, der bei gedrückter
Taste eine 1 in Registerposition "Bit 1" schreibt.
Das Programm klappt auch wunderbar, nur konnte ich jetzt ein Komisches
Phänomen feststellen.
Beim Einschalten des Mikrocontrollers, also Spannung anlegen, ging die
zu schaltende LED sporadisch mit an.
Habe die Zustände, die das Programm durchläuft mit LEDs erfasst und
komme nun zu dem Schluss, das alles so ist, wie es soll.
Beim Startvorgang lösche ich nun immer dieses Register mit den
Schaltzuständen, bevor das eigentliche Programm startet.
Der Fehler trat bisher nicht mehr auf, nur kann mir jemand das Verhalten
erklären?
Wird der Controller evtl. durch die angelegte Spannung kurz nervös und
rattert wild durch die Register?
Danke schonmal :-) Ist auch keine große Frage :-)
Gruß Daniel
Daniel schrieb:> Wird der Controller evtl. durch die angelegte Spannung kurz nervös und> rattert wild durch die Register?
Das ist durchaus nicht unmöglich. Zwei potentielle Ursachen dafür kommen
in Frage:
1) Zu langsames Ansteigen der Versorgungsspannung (z.B. durch zu groß
gewählte Bypass-Kondensatoren).
2) Der Systemtakt benötigt zu lange, um stabil zu werden. Das kann durch
1) bedingt sein, aber auch andere Ursachen haben (z.B. bei Verwendung
eines Quarzes: grenzwertige Bürdekapazitäten für den Quarz).
Nagut, ich benutze das interne Quarz. Das könnte eine Ursache sein.
Oder eben der momentane Aufbau auf einem Steckbrett. Ich schalte
momentan über Stecker ziehen ein und aus. Hätte ich oben mit
reinschreiben sollen. Ist ja nicht ganz unwichtig :-(
Fand es halt nur komisch das immer das Bit 1 in meinem Schaltregister
gesetzt wird. (Das mache ich so, weil die Tasten für "An/Aus" und die
"Lerntaste" entprellt werden.) Das Bit kann eigentlich nur in der
Entprellroutine gesetzt werden, wird es aber nicht, wie ich mit
Testweise eingefügtem Code, der bei dem "sbr"-Befehl eine weitere LED
anschaltet geprüft habe.
Hast du Reset vernünftig beschaltet, oder fest auf +Ub gelegt? 10K gegen
+ und 100n gegen Masse ist ganz gängig. Das macht über den Daumen
gepeilt eine Millisekunde Reset nach dem Einschalten, bis er losläuft.
Bootloader können auch schon mal seltsame Nebenwirkungen haben, wie sie
auf Evaluationboards zum seriellen Flashen verwendet werden.
Ich vermute, dass dein Taster beim Stromanlegen erstmal eine "1"
liefert.
Wie sieht denn die Schaltung aus?
Ist da ein Kondensator am Taster, der eine kurze Zeit zum Aufladen
benötigt?
Meist werden beim Reset der Speicher (RAM) und die Mehrzweckregister
(R1, R2, R3...) nicht auf einen festgelegten Wert gesetzt. Beim
Programmcounter ist es klar, der muss an einer bekannten meist gleichen
Adresse stehen, wenn es los gehen soll. Aber selbst der Stackpointer
wird nicht von allen Mikrokontrollern quasi selbsttätig initialisiert.
Special Function Register haben dagegen meist dokumentierte Startwerte,
wobei einzelne Bits davon die Ausnahme zur Regel sein können.
Wenn Du in C programmierst, trifft Dein Code auf geordnetere
Verhältnisse. Das aber nur, weil vor Deinem Code der sogenannte Startup
Code, den der Compiler mit anschleppt, abläuft.
Daniel schrieb:> Nagut, ich benutze das interne Quarz.
Das würde mich nun doch sehr wundern. Ich kenne nämlich keinen µC, der
einen internen Quarz besitzen würde...
Habe den Reset mit einem Widerstand gegen Plus. Masse mit 100nF
Kondensator.
Die Taster sind direkt mit dem Mikrocontroller verbunden und schalten
Masse.
Interner Pullup-Widerstand ist ebenfalls aktiviert.
Daran sollte es eigentlich nicht liegen, denke ich mal.
Komischerweise macht das Programm jetzt auch nach mehrmaligem An und
Ausschalten keine mucken mehr. Lässt sich wunderbar über Funk an und
ausschalten. Gehe also davon aus, das er die Register beim starten mit
irgendwas beschreibt.
Ist da etwas drüber bekannt, das die das machen? Hmm... Ist im übrigen
Register 20.
Danke, das ihr euch Zeit für mich genommen habt :-)
Daniel schrieb:> Ist da etwas drüber bekannt, das die das machen?
Keine Ahnung. Und wenn schon.
Nach dem Reset sind alle Register in einem eindeutigen Zustand. Und das
auch fantastischerweise immer im selben. Die Inhalte sind im Datenblatt
angegeben.
Schalt den Brown Out Detect ein!
Gerald B. schrieb:> Hast du Reset vernünftig beschaltet, oder fest auf +Ub gelegt? 10K gegen> + und 100n gegen Masse ist ganz gängig. Das macht über den Daumen> gepeilt eine Millisekunde Reset nach dem Einschalten, bis er losläuft.
Das mag zwar sein, aber dafür ist die externe, nicht unbedingt
notwendige Resetbeschaltung nicht da. Damit das Startverhalten
verbessern zu wollen, ist schlichtweg Unsinn.
Thomas E. schrieb:> Nach dem Reset sind alle Register in einem eindeutigen Zustand.
NEEIIN!
Es sind dann nur die Peripherie-Register in einem eindeutigen Zustand.
Nicht aber die Register der MCU (also R0..R31). Deren Inhalt ist genauso
zufällig wie der des SRAM insgesamt (tatsächlich handelt es sich bei
diesen Registern am Ende auch bloß um SRAM, nur ihre Adresse macht diese
paar SRAM-Zellen zu MCU-Registern).
Leider suggeriert hier z.B. der Atmel-Simulator ein definiertes
Verhalten dieser paar SRAM-Zellen (da bin auch ich auch mal drauf
reingefallen), aber ein solches ist weder dokumentiert noch besteht es
in der Realität.
Aber wirklich blöd ist in diesem Zshg. vor allem die Mehrdeutigkeit des
Begriffs "Register". Das sorgt für Missverständnisse, die nicht nötig
wären.
> Begriffs "Register". Das sorgt für Missverständnisse
Es gibt doch die Unterscheidung 'Special Function Registers' und
'Working Registers', und Letztere starten eben undefiniert.
c-hater schrieb:> NEEIIN!
Immer ruhig bleiben.
Wen interessiert der RAM-Inhalt. Daß man den selbst auf einen
definierten Zustand setzt oder dies dem freundlichen Compiler überlässt,
ist doch wohl selbstverständlich.
Ich kann das Problem das TO ohnehin nicht nachvollziehen.
Wahrscheinlich fehlen sowieso nur wieder die Stützkondensatoren.
c-hater schrieb:> da bin auch ich auch mal drauf> reingefallen
Na, das ist aber genau die Dämlichkeit, die gerade du anderen immer
vorhälst.
S. Landolt schrieb:> Es gibt doch die Unterscheidung 'Special Function Registers' und> 'Working Registers'
Klar. Bloß entfällt diese Möglichkeit zur Unterscheidung halt, sobald
irgendjemand nur noch von Registern spricht. Capisce?
> ... ohnehin nicht nachvollziehen ...
Nun ja, er programmiert offenbar in Assembler und spricht von Register
20 - vielleicht hat er wirklich versäumt, dieses zu Beginn auf einen
definierten Zustand zu setzen.
Thomas E. schrieb:> Na, das ist aber genau die Dämlichkeit, die gerade du anderen immer> vorhälst.
Nein. Der Unterschied ist: Ich LERNE. Und ich KANN lernen. Und ich
WILL lernen. Und ich verwende seit 30 Jahren jedes Jahr sehr viel Zeit
darauf, genau das zu tun.
Und natürlich und völlig selbstverständlich lernt man am nachhaltigsten
aus selbst gemachten Fehlern...
Sofern man denn überhaupt lernen WILL. Und sich selber Fehler
eingestehen kann.
Also so ziemlich genau das Gegenteil von deiner verkorksten
Persönlichkeit ist...
Ohoh... was ist denn hier los? :-(
Trau mich schon garnicht mehr zu antworten :-(
Stützkondensatoren hab ich ehrlich gesagt nicht drin, nur den an Masse
halt.
S. Landolt schrieb:> er programmiert offenbar in Assembler und spricht von Register> 20 - vielleicht hat er wirklich versäumt, dieses zu Beginn auf einen> definierten Zustand zu setzen.
Ja, ich benutze Assembler. Soll zum Kennenlernen der CPU gut sein.
Verstehe die ganzen Klammern bei C sowieso nicht :-D
Mittlerweile hab ich Assembler auch lieb gewonnen. Wer weiß wie lange
:-D
Und ja, ich hab vergessen Register 20 auf einen deninierten Zustand zu
setzen.
Ich würde das Register einfach löschen mit "clr". Dann ist alles 0 und
definiert, oder etwa nicht? 0 schon, aber auch definiert? Andererseits
was soll man anders definieren als 0? Glaub ich hab meine Frage selbst
beantwortet :-D
Und der Rest von euch hat sich wieder lieb.
Daniel schrieb:> Ich würde das Register einfach löschen mit "clr". Dann ist alles 0 und> definiert, oder etwa nicht?
Jepp, damit ist es definiert.
> Andererseits> was soll man anders definieren als 0?
Das kann in bestimmten Fällen durchaus schonmal Sinn ergeben. Hängt
einfach von der Anwendung ab.
Bei R20 aber kein Problem. "ldi R20,immediate_value" tut den Job und ist
in keiner Hinsicht teurer als ein "clr R20".
Blöder kommt es schon bei R <16. Da steht "ldi" leider nicht zur
Verfügung...
Aber bei Registern unter R16 könnte man ja:
ldi R20,immediate_value
mov R15,R20
machen? Oder auch gleich clr R15.
Und immediate_Value muss ich vorher als
.def immediate_Value = 0x00 meinetwegen definieren, ja? Oder meinetwegen
0x20 bei speziellen Sachen?
Wieder was gelernt :-)
Na dann mach' noch 2 Stütz-C's auf kürzestem Wege zwischen Masse und +5V
am µC. Einen KerKo 100n und einen Elko 47µ. Ob ein Stützkondensator
wirklich fehlt, merkt man nicht so ohne weiteres. Nur mit aufwendigen
Messungen. Und wenn es "kippelt" muß das auch nicht zwangsläufig
regelmäßig auftreten.
Ein "zu viel" gibt es dabei nicht, aber sehr wohl ein "zu wenig". Bei
den Centbeträgen verbaue ich die lieber großzügig.
Das ist noch eine Angewohnheit aus der Zeit der TTL-Gräber ;-)
Daniel schrieb:> Aber bei Registern unter R16 könnte man ja:> ldi R20,immediate_value> mov R15,R20> machen?
Natürlich.
> Und immediate_Value muss ich vorher als> .def immediate_Value = 0x00 meinetwegen definieren, ja?
Nein, das ist nicht zwingend.
Oweh, bin ich ein SEHR altmodischer AVR-ASM-Fummler?
Ich habe (gewollt) noch nie eines der "General Purpose"-
Register R0...31 ohne eine klare Wert-Zuweisung benutzt.
Also nie so ein Problem gehabt...
VERGESSEN hab ich es natürlich schon mal - da sollte es aber
meist ein Wert != NULL sein...
Dass der Stackpointer (Lo/Hi) gleich zu Anfang auf
RAMEND (Lo/Hi) gesetzt werden muss, ist bei AVR wirklich doof,
aber in jedem Code-Beispiel vermerkt. Merkt man aber, da
zuverlässig GARNIX funktioniert...
Habe mir auch nie Gedanken über die ultimativ-optimale
NULL-Zuweisung gemacht:
CLR Rx ist jedenfalls IMMER OK, da eine LDI-Zuweisung erst
ab R16 möglich ist...
Ansonsten fällt mir kein I/O-Register ein, dass keinen
Standard-Wert hat. Gibt es eigentlich welche != NULL?
Jacko schrieb:> Ansonsten fällt mir kein I/O-Register ein, dass keinen> Standard-Wert hat. Gibt es eigentlich welche != NULL?
Ja, die Register für den z.B. Uart, sind default-mäßig auf 8N1 bei den
AVRs eingestellt ;)
EEPROM Kontrollregister hat auch das ein und andere Bit, dass beim Start
nicht definiert ist.
> Dass der Stackpointer (Lo/Hi) gleich zu Anfang auf> RAMEND (Lo/Hi) gesetzt werden muss, ist bei AVR> wirklich doof,> Gibt es eigentlich welche != NULL?
Zum Beispiel eben genau der Stackpointer, der bei allen neueren Typen
auf RAMEND gesetzt ist.