- LiFePO4 Speicher Test         
Ergebnis 1 bis 9 von 9

Thema: Falscher LowPegel am ATMega8535

  1. #1
    Benutzer Stammmitglied
    Registriert seit
    15.05.2005
    Beiträge
    48

    Falscher LowPegel am ATMega8535

    Anzeige

    Praxistest und DIY Projekte
    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

  2. #2
    Erfahrener Benutzer Roboter Experte Avatar von sternst
    Registriert seit
    07.07.2008
    Beiträge
    672
    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.
    MfG
    Stefan

  3. #3
    Benutzer Stammmitglied
    Registriert seit
    15.05.2005
    Beiträge
    48
    Vielen Dank!

    Vorher:
    Code:
    #include <avr/io.h>
    
    int main() {
    	PORTA = 0x00;
    }
    Nachher:
    Code:
    #include <avr/io.h>
    
    int main() {
    	DDRA = 0xff;
    	PORTA = 0x00;
    }

  4. #4
    Erfahrener Benutzer Roboter Experte
    Registriert seit
    20.05.2006
    Ort
    Lippe
    Alter
    54
    Beiträge
    524
    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

  5. #5
    Benutzer Stammmitglied
    Registriert seit
    15.05.2005
    Beiträge
    48
    Zitat Zitat von McJenso
    BTW Was macht der Controller, wenn er das Programm abgearbeitet hat?
    In dem letzten Pinzustand bleiben (im falle meines Programms 0x00 an PortA).

    Zitat Zitat von McJenso
    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:
    Code:
    #include <avr/io.h>
    
    int main() {
    	DDRA = 0xff;
    	PORTA = 0x00;
    }
    Mit return, main als int
    Code:
    #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'):
    Code:
    #include <avr/io.h>
    
    void main() {
    	DDRA = 0xff;
    	PORTA = 0x00;
    }
    Befehle zum Compilieren und Assemblercode erzeugen:
    Code:
    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:
    Code:
    [...]
    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.

    Zitat Zitat von McJenso
    BTW Was macht der Controller, wenn er das Programm abgearbeitet hat?
    Er geht in eine Endlosschleife:
    Code:
    00000076 <_exit>:
      76:   ff cf           rjmp    .-2             ; 0x76 <_exit>
    Danke fuer deine Hilfsbereitschaft

  6. #6
    Erfahrener Benutzer Roboter Experte
    Registriert seit
    20.05.2006
    Ort
    Lippe
    Alter
    54
    Beiträge
    524
    Hallo,

    Danke fuer deine Hilfsbereitschaft
    So bin ich halt

    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

  7. #7
    Benutzer Stammmitglied
    Registriert seit
    15.05.2005
    Beiträge
    48
    Zitat Zitat von McJenso
    Vielleicht wird mein nächstes Post dann hilfreicher
    Meine 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

  8. #8
    Erfahrener Benutzer Roboter Experte
    Registriert seit
    22.11.2005
    Ort
    Braunschweig
    Alter
    47
    Beiträge
    685
    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
    Meine kleine Seite
    http://home.arcor.de/volker.klaffehn
    http://vklaffehn.funpic.de/cms
    neuer Avatar, meine geheime Identität

  9. #9
    Benutzer Stammmitglied
    Registriert seit
    15.05.2005
    Beiträge
    48
    Zitat Zitat von Ofenrohr
    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

Berechtigungen

  • Neue Themen erstellen: Nein
  • Themen beantworten: Nein
  • Anhänge hochladen: Nein
  • Beiträge bearbeiten: Nein
  •  

12V Akku bauen