Archiv verlassen und diese Seite im Standarddesign anzeigen : Falscher LowPegel am ATMega8535
Ofenrohr
20.07.2008, 18:14
Moin,
ich habe mir vor ein paar Tagen das AVR-Evaluationsboard von Pollin zusammengeloetet. Dabei habe ich den 7805 zerstoert und als alternative Stromversorgung 5v von einem AT-Netzteil angeschlossen (den +Pol an den ehemaligen Ausgang des 7805 auf dem Board und Masse dementsprechend an den dazugehoerigen Masseanschluss).
Habe anschlieszend erfolgreich einen ATMega8535 (mit uisp) programmiert. Pins sind wie gewuenscht an und aus gegangen. Als ich versucht hab einen (mit Parport auf Funktionsfaehigkeit getesteten) 74hc595 anzusteuern hats nicht funktioniert. Nach einigem Messen habe ich festgestellt, dass der AVR zwar +5v High Pegel liefert, aber beim Low Pegel genau 0v hat (egal ob ich Volt zwischen Pin und + oder Pin und - messe). Soweit ich weisz muesste das leicht im negativen Bereich sein, damit TTL Bausteine funktionieren.
Welchen Fehler kann ich gemacht haben? Wonach muss ich suchen?
Ofenrohr
Soweit ich weisz muesste das leicht im negativen Bereich sein, damit TTL Bausteine funktionieren.
Nein. Für TTL muss der Low-Pegel <0,8V sein.
aber beim Low Pegel genau 0v hat (egal ob ich Volt zwischen Pin und + oder Pin und - messe)
Wenn du sowohl zwischen Pin und VCC 0 Volt misst, wie auch zwischen Pin und GND, dann ist der Pin hochohmig, also wahrscheinlich als Eingang konfiguriert. Ist vermutlich ein Fehler in deinem Programm.
Ofenrohr
20.07.2008, 19:18
Vielen Dank!
Vorher:
#include <avr/io.h>
int main() {
PORTA = 0x00;
}
Nachher:
#include <avr/io.h>
int main() {
DDRA = 0xff;
PORTA = 0x00;
}
Hallo,
wenn ein Pin Ausgang seien soll muss das DDR gesetzt (1) sein. Der Ausgang kann dann 0V low oder 5V (Versorgung) height annehemen, abhängig vom Port Register.
Ist das DDR nicht gesetzt, ist das Potential am Pin nicht definiert. Wenn du nun aber das Port Register setzt aktiviert du den internen Pullup und ziehst den Pin damit auf 5V.
Hoffe jetzt dass, das die Antwort war die du suchst.
BTW Was macht der Controller, wenn er das Programm abgearbeitet hat?
Es feht eine Endlosschleife wie z.B. while (1){};
Nett ist es die int main () mit return 0; abzuschließen. Das int steht immerhin für einen Rückgabewert.
Gruß
Jens
Ofenrohr
21.07.2008, 09:42
BTW Was macht der Controller, wenn er das Programm abgearbeitet hat?
In dem letzten Pinzustand bleiben (im falle meines Programms 0x00 an PortA).
Es feht eine Endlosschleife wie z.B. while (1){};
Nett ist es die int main () mit return 0; abzuschließen. Das int steht immerhin für einen Rückgabewert.
Es handelt sich bei meinem Code nicht um den Code, den ich tatsaechlich verwende, sondern um eine soweit wie moeglich vereinfachte Form, um anderen, die vielleicht das selbe Problem haben, die Suche nach der Loesung so einfach wie moeglich zu machen.
Trotzdessen: Warum sollte ich eine Schleife verwenden, wenn der Zustand sowieso erhalten bleibt?
Und warum sollte ich ne Zahl zurueckgeben, wenn die sowieso von keinem Programm ausgelesen wird?
Habe grad mal drei unterschiedliche Varianten ausprobiert, die alle den gleichen ASM Code erzeugen:
Ohne return, main als int:
#include <avr/io.h>
int main() {
DDRA = 0xff;
PORTA = 0x00;
}
Mit return, main als int
#include <avr/io.h>
int main() {
DDRA = 0xff;
PORTA = 0x00;
return 0;
}
ohne return, main als void (mit warning: return type of 'main' is not 'int'):
#include <avr/io.h>
void main() {
DDRA = 0xff;
PORTA = 0x00;
}
Befehle zum Compilieren und Assemblercode erzeugen:
maratox ~/Programmieren/avr/test $ make
avr-gcc test.c -Os -g -mmcu=atmega8535 -c -o test.o
avr-gcc test.o -o test.elf -mmcu=atmega8535
avr-objcopy -j .text -j .data -O ihex test.elf test.hex
maratox ~/Programmieren/avr/test $ avr-objdump -d test.elf --source test.c
Assemblercode der drei Quellen:
[...]
00000062 <main>:
#include <avr/io.h>
int main() {
62: cf e5 ldi r28, 0x5F ; 95
64: d2 e0 ldi r29, 0x02 ; 2
66: de bf out 0x3e, r29 ; 62
68: cd bf out 0x3d, r28 ; 61
DDRA = 0xff;
6a: 8f ef ldi r24, 0xFF ; 255
6c: 8a bb out 0x1a, r24 ; 26
PORTA = 0x00;
6e: 1b ba out 0x1b, r1 ; 27
return 0;
}
70: 80 e0 ldi r24, 0x00 ; 0
72: 90 e0 ldi r25, 0x00 ; 0
74: 00 c0 rjmp .+0 ; 0x76 <_exit>
00000076 <_exit>:
76: ff cf rjmp .-2 ; 0x76 <_exit>
Da bei jeder Version dieser Code erzeugt wird ist es folglich egal, ob ich return hinschreib oder nicht, weil die return-Zahl sowieso nicht ausgewertet wird.
BTW Was macht der Controller, wenn er das Programm abgearbeitet hat?
Er geht in eine Endlosschleife:
00000076 <_exit>:
76: ff cf rjmp .-2 ; 0x76 <_exit>
Danke fuer deine Hilfsbereitschaft
Hallo,
Danke fuer deine Hilfsbereitschaft
So bin ich halt :cheesy:
Im ernst, dass return wird durch die Angabe int vor main gefordert. Auch wenn es ohne funktioniert, wird es nicht richtiger. Wenn du genau weißt, was der Controller nach Abarbeitung des Programmes macht, ist ja alles gut. Diese beiden Hinweise waren gut gemeint. Vielleicht klärst du mich ja auf, was mir die beiden Codeschnipsel sagen sollen. Vielleicht wird mein nächstes Post dann hilfreicher.
Gruß
Jens
Ofenrohr
21.07.2008, 21:00
Vielleicht wird mein nächstes Post dann hilfreicherMeine Frage wurde eine gute Stunde vor Deinem ersten Post vollstaendig beantwortet. (Ist nicht boese oder unfreundlich gemeint)
Ich vermute, dass Du mit den beiden Codeschnipseln jene aus meinem ersten Post meinst.
Sternst sagte, dass ich vermutlich PORTA als Eingang definiert habe und einen Fehler in meinem Programm habe. Daraufhin habe ich gesucht, wie ich den Port als Ausgang definiere und konnte mein Problem mit DDRA = 0xff; loesen. Um anderen diese Suche zu ersparen, habe ich schnell noch einen (nicht funktionierenden) vorher Code und einen (funktionierenden) nachher Code geschrieben und mich bei Sternst bedankt.
Dann hast Du mich auf Fehler in meinem Code aufmerksam gemacht (keine Endlosschleife am Ende + kein return). Da avr-gcc keine Warnings beim Compile ausgegeben hat, habe ich mich gefragt, ob es wirklich falsch ist, beides wegzulassen. Um das herauszufinden habe ich nach nem disassembler gesucht und mir den Assemblercode von meinem urspruenglichem (dem "nachher" Code) angesehen. Heraus kam, dass der Compiler automatisch am Ende des main-Codes eine Endlosschleife erzeugt (rjmp .-2). Folglich erzeugt der Compiler von selbst am Ende meines Codes eine Endlosschleife, muss ich also nicht selbst machen.
Bleibt noch das return. Habe den Ausgangscode genommen und ein return 0; eingefuegt und wieder durch den disassembler gejagt. Wie ich bereits vermutete hat der Compiler das return einfach nicht uebersetzt (warum sollte der Compiler etwas fordern, das er nicht uebersetzt?). Daraufhin habe ich noch einen weiteren Code geschrieben, der main als void definiert (natuerlich ohne return). Compiler hat ein Warning ausgegeben, aber wieder den gleichen Assemblercode erzeugt.
Auf Systemen, die mehr als ein Programm beherbergen, macht es selbstverstaendlich Sinn, return hinzuschreiben, um dem nachfolgenden Programm mitzuteilen, ob das vorhergehende Programm erfolgreich oder nicht erfolgreich abgeschlossen wurde. Da dies auf einem AVR ehr nicht der Fall ist bzw alles in einem Programm ist, ist ein return 0 nicht notwendig.
Ofenrohr
vklaffehn
22.07.2008, 01:07
Moin!
Das fehlende warning überrascht mich allerdings, wenn ich meine Main als 'void main' deklariere, bekomme ich bei mir schon ein warning, und natürlich auch eins, wenn ich es als 'int main' deklariere und keinen Rückgabewert liefere, was ja auch richtig ist.... Naja, hauptsache geht ;-)
MfG
Volker
Ofenrohr
22.07.2008, 08:49
Daraufhin habe ich noch einen weiteren Code geschrieben, der main als void definiert (natuerlich ohne return). Compiler hat ein Warning ausgegeben
Wenn ich noch -Wall als compile flag setze bekomme ich auch fuer ein fehlendes return ein Warning.
Funktionieren tuts allerdings, simmt :)
Ofenrohr
Powered by vBulletin® Version 4.2.5 Copyright ©2024 Adduco Digital e.K. und vBulletin Solutions, Inc. Alle Rechte vorbehalten.