Erstmal vorbeugen: ATmega103 compatibility mode ist _ausgeschaltet_!
Mein Problem: Ueber einen 40106 Schmitt-Trigger habe ich 5 Tasten entprellt und die ST-Ausgaenge an Port G4..0 angeschlossen.
Pull-Ups im µC eingeschaltet: PG1 und PG4 funktionieren normal. Erkennung funktioniert. Taster losgelassen: 5V an PG1, PG4 Taster gedrueckt: 0V an PG1, PG4
PG0, PG2 und PG3 verhalten sich komisch. Taster losgelassen: 5V an PG0, PG2, PG3 Taster gedrueckt: 4,85V an PG0, PG2, PG3 Wenn ich die Pull-Ups abschalte, aendert sich der Pegel von 150mV auf 0V.
Wenn ich die Pins PG0, PG2 und PG3 direkt auf Masse lege, fliessen 90mA Strom aus dem Controller heraus (pro Pin!).
DDRG = 0x00; PORTG = 0xff;
Laut Datenblatt ist nach Abschalten des ATm103-CMode PortG ein bidirektionaler I/O-Port, wie alle anderen auch. Mit Ausnahme, dass er nicht im I/O-Adressbereich liegt sondern ueber Memory adressiert wird. Kennt jemand dieses Phaenomen und hat es loesen koennen? Ich habe inzwischen 2 Chips ausprobiert, beide das gleiche Verhalten. Wenn ich die Tasten an PORTC anschliesse, ist alles in Ordnung.
Da hab ich auch dran gedacht, das Datenblatt sagt aber, dass JTAG beim Mega64 auf Port F liegt. Die Port-G-Pins kann man verwenden, um externen Speicher an den Controller anzubinden.
JTAG liegt auf PORTF und ist auch abgeschaltet. Es gibt noch das AS0-Bit in ASSR und das SRE-Bit in MCURC. Beide koennen, auf 1 gesetzt, eine alternative Port-Funktion aktivieren. Es werden aber beide standardmaessig mit 0 initialisiert.
Ich hatte auch ueberlegt, ob es daran liegen koennte, dass die Ports F und G nicht im I/O-Adressbereich liegen. Dagegen spricht aber, dass zwei Tasten funktionieren und dass Port F erwartungsgemaess funktioniert. Dort habe ich zwei Pins am ADC und vier I/O-Pins fuer ein Display. ADC und Display funktionieren.
Nein, JTAG liegt da nicht drauf. Die "alternate functions" (RTC Oszillator und RAM interface) koennen es eigentlich auch nicht sein, weil man so keinen Fall konstruieren kann wo nur PG0, PG2 und PG3 getrieben werden, nicht aber PG1 und PG4.
Bist du sicher, dass wirklich DDRG=0 ist? Mach doch an den Reset-Vektor mal eine Endlosschleife hin, dann muss Port G hochohmig sein (DDRG wird ja vom Reset auf Null initialisiert).
Ich habe jetzt vor der Tastenabfrage im Timer explizit nochmal PORTG=0xff gesetzt und DDRG=0x00.
Das Ergebnis ist, dass ich jetzt zwar die Tasten alle lesen kann, aber sobald ich mit dem Messgerät die Spannung am Pin messen moechte, bekomme ich einen Tastendruck angezeigt und die Spannung schwankt hin und her.
Es scheint so, als ob DDRG staendig auf 1 zurueckgesetzt wird. Gibt es dafuer eine Erklaerung? Das permanente Setzen von jeweils nur DDRG oder PORTG fuehrt zu keinem Ergebnis. Es muessen wirklich beide Werte gesetzt werden. Das klingt schon fast nach einem weiteren Problem.
Also sieht das doch sehr nach Softwareproblem aus.
Gib uns mal mehr Infos. Ist das Programm in C oder Assembler geschrieben, mit was fuer Tools, etc. Oder zeig am Besten mal die paar Source-Zeilen wie du den Port initialisierst und darauf zugreifst.
Ok, es ist wohl doch ein Software Problem. Das macht es jetzt zwar nicht einfacher fuer mich, aber ich weiss, wo ich ansetzen muss. Ich habe auf Bernhards Rat hin ein kleines Testprogramm geschrieben, was nur initialisiert, dabei den Timer startet und dann mit 25Hz die Tasten abfragt.
Jetzt funktioniert alles normal. Die Schaltung ist die gleiche, alle anderen Ports sind genauso belegt, werden aber nicht abgefragt. Ich werde mal nach und nach die anderen Interrupts dazu schalten und sehen was passiert.
Da der Port im Memory liegt, können keine Bit-Befehle angewendet werden. Bei den IO-Adressen sind ja die Bits einzeln manipulierbar. Kann es sein, dass Du read-modify-write-Probleme hast?
Grüße, Kurt
--
KHTronik - Kurt Harders
Elektronik, Softwareentwicklung, Opensource-Beratung
Leimbacher Str. 36
42281 Wuppertal
T +49 202 2 50 11 64
F +49 202 2 50 11 65
M +49 171 8 36 82 33
Ja, das Problem kennt in den lustigsten Varianten wohl jeder, der ernsthaft programmiert.
Solche Fehler (und auch Tippfehler) sind überaus schwer zu finden. Wenn man nicht schon einen Fingerzeig in die richtige Richtung hat, kann man sich da echt zu Tode suchen und die fehlerhafte Stelle locker ein dutzend Mal lesen, ohne daß einem der Fehler auffällt.
Es gibt ein Mittel: man benenne alle Namen per Refactor-Befehl in "DiesIstBlödsinn" um, und schaue sich dann den Code an. Das ist kein Scherz, erfordert aber einen halbwegs brauchbaren Editor.
Grüße, Kurt
--
KHTronik - Kurt Harders
Elektronik, Softwareentwicklung, Opensource-Beratung
Leimbacher Str. 36
42281 Wuppertal
T +49 202 2 50 11 64
F +49 202 2 50 11 65
M +49 171 8 36 82 33
PORTG wäre doch völlig legal, es wird nur (neben den richtigen) auch an an mindestens einer falschen Stelle darauf zugegriffen.
Sowas kannst du mit deinem Ansatz nicht wirklich detektieren. Dein Ansatz nützt nur was für "nichtstrikte" Programmiersprachen, um fälschlich erzeugte, quasi "parasitäre" Symbole zu detektieren. Aber wer programmiert schon freiwillig in so einer Sprache und das auch noch im µC-Bereich?
Und wenn es nur darum geht, jedes Vorkommen _eines_ Symbols aufzufinden, dann braucht man dafür auch kein Refactoring, dafür genügt schon die normale Suchen-Funktion jedes beliebigen primitiven Texteditors.
Refactoring ist eigentlich nur was für Leute, die hauptsächlich zusammengeklau(b)ten fremden Code zu einem "eigenen" Werk verwursten und nicht wollen, daß das schon auf den ersten Blick sofort jedem auffällt...
Der Effekt, den Du durch umbenennen erreichst ist, dass Du den falschen Namen nicht mehr überliest. Genau das passiert ja beim Suchen des Fehlers: Du nimmst an, dass da PORTB stehen sollte, und siehst garnicht, dass dort PORTG steht. Wir haben dieses Verfahren in Assembler, Pascal und C eingesetzt, um genau solche Fehler, Nutzung ähnlicher oder vertippter, aber existierender Namen, zu finden.
Das gilt aber nicht mehr, wenn Du viele Quelldateien hast, oder sogar Namespaces, bei denen der selbe Name in verschiedenem Kontext auftauchen kann.
Sorry, das ist der blanke Unsinn. Gerade bei Sprachen mit Namerspaces, und dazu zählt, mit dem Schlüsselwort static, sogar C, ist Refactoring in größeren Projekten ein Mittel, z.B. Umbennenungen zur besseren Dokumentation vorzunehmen. Es ist ja gerade das besondere Merkmal des Refactoring, die Änderungen auf der Eebene der semantischen Korrektheit vorzunehmen.
Grüße, Kurt
--
KHTronik - Kurt Harders
Elektronik, Softwareentwicklung, Opensource-Beratung
Leimbacher Str. 36
42281 Wuppertal
T +49 202 2 50 11 64
F +49 202 2 50 11 65
M +49 171 8 36 82 33
Bevor Du öffentlich über ein Thema schreibst, von dem Du nichts weißt, solltest Du Dich darüber informieren, damit Du Dich nicht -- wie hier -- öffentlich zum Volldeppen machst.
Das projektweite Umbenennen ist nur eine von mehreren Funktionen, die das Refactoring bietet. Falls Du jemals _ernsthaft_ programmiert haben solltest (was ich aufgrund Deiner oben zitierten Absonderung nicht annehme), mit Augenmerk nicht nur darauf, dass der Code gerade mal funktioniert, sondern auch wartbar und erweiterbar ist (d.h. von Dir selbst nach mehr als zwei Wochen, sowie auch von anderen möglichst leicht verstehbar ist), dann hättest Du die Erfahrung gemacht, dass öfters mal ein Symbol (Variable, Funktion, Prozedur, Klasse, etc.) ungünstig benannt ist und einen sinnvolleren Namen bekommen muss, der den Sinn und Zweck des Symbols gut verstehbar repräsentiert. Es gibt Leute, die dann den ungünstigen Namen bestehen lassen. Mag sein, dass sie einfach faul sind, oder glauben, sie könnten sich dadurch unabkömmlich machen (weil ja niemand anders den unleserlichen Kram versteht). Letztlich ist das aber eine dumme Verhaltensweise, die ihnen selbst und dem Unternehmen schadet, da durch schlechte Benennungen Änderungen am Code unnötig aufwendig und damit unnötig teuer werden. Es gibt andere Leute, die benennen, sobald sie erkennen, dass ein Symbol einen ungünstigen Namen hat, dieses um und sorgen damit für bessere Verständlichkeit. Für diese Leute ist dieser Teil des Refactoring ein Segen, der ihnen mühsame und fehlerträchtige Handarbeit abnimmt.
Eine weitere Komponente des Refactoring ist, ein Stück Code als Funktion oder Methode zu extrahieren. Wenn man feststellt, dass man an mehreren Stellen immer wieder fast identischen Code schreibt, lohnt es sich, diesen als Funktion/Methode zu extrahieren und durch einen Aufruf der Funktion/Methode zu ersetzen. Auch das führt zu besser wartbarem Code, da nur noch an einer Stelle -- in der Funktion/Methode -- und nicht an allen möglichen Stellen, wo sie verwendet wird, geändert werden muss. Außerdem werden die betreffenden Programmteile besser verständlich, da dort jeweils anstatt eines Codeblocks, dessen Funtionsweise man erst erkennen müsste, der Aufruf einer (hoffentlich sinnvoll benannten) Funktion/Methode steht. Das Refactoring erleichtert einem hierbei wiederum die Arbeit, indem es ermittelt, welche Variablen der zu extrahierende Programmteil benötigt, und diese als Argumente mit in die Funktions-/Methodendefinition schreibt.
Und dann sind da noch einige andere ebenso nützliche Aufgaben, bei denen einem das Refactoring helfen kann. Die beiden oben genannten sind nur als Beispiele gedacht, weitere Informationen sind mit wenig Aufwand im WWW zu finden.
Falls Du irgendwann mal ernsthaft programmieren wollen solltest, solltest Du dich über Refactoring informieren und es dann auch einsetzen.
Dass es immer wieder Menschen gibt, die Werkzeuge zu üblen Zwecken missbrauchen (z.B. zu der Verschleierung, die Dir offenbar als einziger Anwendungszweck für Refactoring einfällt -- gehörst Du etwa zu dieser Gruppe von Menschen?), ist traurig. Es macht aber die Werkzeuge für ihren eigentlichen Zweck nicht weniger wertvoll.
Grüße,
Günther
PS: Um Korinthenkackern zuvor zu kommen: Ich meine im Kontext dieses Threads mit dem Begriff Refactoring nicht die abstrakte Methode Refactoring, sondern die Hilfsmittel, die in diversen Entwicklungsumgebungen eingebaut sind, um einem die Durchführung des Refactoring zu erleichtern.
PPS: Ich musste mal ein Programm durchstöbern, dessen Schöpfer drei globale Variablen namens 'A', 'AA' und 'AAA' für praktisch alles verwendete. Da wurden beim Aufruf von Funktionen zusätzliche Parameter und/oder bei der Rückkehr zusätzliche Rückgabewerte hineingeschrieben. Sie wurden als Laufvariable verwendet (anstatt des allseits bekannten 'i'), sowie für alle möglichen Zwischenergebnisse. Diesem Wust hätte man man mittels Refactoring nicht beikommen können. Für soetwas ist Wegwerfen und Neumachen die einzige Option.
Genausogut kann man in allen Files nach PORTG suchen und sich wundern, warum der im LCD-Modul erscheint.
Ich benenne die controllereigenen Schnittstellen in einem zentralen Headerfile in sinnvolle Namen um. d.h. PORTG taucht exakt einmal im ganzen Quelltext auf. Überall sonst steht dann z.B. TASTENPORT oder I2C_CONFIG.
Natürlich kann man immer noch mit Copy/Paste den falschen Port wählen. Wenn man nicht übermüdet ist, sieht man das aber sofort.
--
Gruß, Raimund
Mein Pfotoalbum
Mail ohne Anhang an wird gelesen. Im Impressum der Homepage
findet sich immer eine länger gültige Adresse.
Ich habe vor einem halben Jahr das letzte Mal C-Code für den µC geschrieben. Da habe ich mir die Display-Routine vom letzten Mal kopiert.
Leider habe ich mir beim Einrichten der Tasten ein #define dsplctrl DDRB mit DDRG überschrieben. Ok, in der Zeile verutscht. Dieser Fehler taucht also nur an einer einzigen Stelle auf, wird aber über den Namen mehrmals im Programm benutzt. Und nun mal ehrlich: Zwischen all den Zeilenkommentaren und anderen Definitionen sticht das G statt des Bs nun wirklich nicht besonders hervor.
Es wäre ja auch einfacher gewesen, wenn der daraus resultierende elektrische Fehler etwas "aufschlußreicher" gewesen wäre.
Gerade hier ist mir ja das Vergeben von sinnvollen Equations zum Verhängnis geworden. Der Fehler steht an einer einzigen Stelle, kommt aber in unterschiedlichen Routinen vor. Das soll aber nicht heißen, daß es besser wäre demnächst überall mit DDRx zu arbeiten, denn das ist schlecht portierbar.
Nachdem ich wußte, daß es ein Software-Fehler sein muß, habe ich mir den Quellcode in einem anderen Editor mit etwas anderem Syntax-Highlightning angeschaut. Erst da "sprang" mir der Fehler ins Auge.
Es würde mich aber mal brennend interessieren, wie ihr portierbaren Code schreibt. Wenn z. B. Routinen in eine Bibliothek kommen, die aber bestimmte Pins benutzen, die beim nächsten Projekt aber nicht die gleichen sind, wie löst ihr das sinnvoll? Eine readme.txt, welche Equations gesetzt werden müssen, oder Copy&Paste aus C-Dateien? Bestimmte Symbolnamen, die erwartet werden?
ElectronDepot website is not affiliated with any of the manufacturers or service providers discussed here.
All logos and trade names are the property of their respective owners.