Serielle Ausgabe auf AtMega88

Main,

Also isch werd' noch mal ...

Ich versuche verzweifelt einfach einen String über den seriellen Ausgang eines AtMega88 auszugeben:

  • Chip ist "jungfräulich" (interner Takt, /8-Prescaler enable-t)
  • Initialisierung wie im Datenblatt: UBRR0H/L auf 51 (bei 1MHz Takt sollte das 1200 Baud ergeben) UCSR0B = (1
Reply to
Josef Moellers
Loading thread data ...

Josef Moellers schrieb:

Hallo,

hast Du auch das berücksichtigt: "20.6 Data transmission ? The USART transmitter The USART Transmitter is enabled by setting the Transmit Enable (TXEN) bit in the UCSRnB Register. When the Transmitter is enabled, the normal port operation of the TxDn pin is overridden by the USART and given the function as the Transmitter?s serial output."

Der TxDn pin muß als UART Ausgang extra enabled werden!

Bye

Reply to
Uwe Hercksen

Am 16.5.2011 schrub Uwe Hercksen:

Ja, das steht da ja:

  1. Der Transmitter wird durch das Setzen des TXEN-Bits "enable"-t -> UCSR0B = (1
Reply to
Josef Moellers

Sieht für mich (mal abgesehen von der gräßlichen Sprache) soweit korrekt aus.

Wie gemessen, Multimeter oder Oszi?

Wenn Multimeter, würde ich mal sagen, daß du Dauer-0xff sendest. Plus noch zwei Stoppbits. Also zehn Bits high und nur eins low, daß kann einem mit einem billigen Multimeter u.U. schonmal entgehen.

Welche Frequenz hat der? Es sollten rund 54,5Hz sein.

Eigentlich nicht. Die USART funktioniert wie bei allen anderen neueren ATMegas auch.

Reply to
Heiko Nocon

Nein. Übersetze nochmal richtig. Die einzige notwendige Bedingung ist, daß TXENn gesetzt wird. Und das hat er getan.

Reply to
Heiko Nocon

Am 16.5.2011 schrub Heiko Nocon:

Sorry ... ja!

Nein, sowohl mit Oszi als auch mit Logic Analyzer (ab und an wird bei uns mal was de-investiert und wenn es voll abgeschrieben ist, ist es ein Schnäppchen ;-)

Muß ich noch mal nachmessen.

Dachte ich ja auch. Ich wollte mich nur vergewissern.

Heute abend werde ich mal versuchen, ob ich wenigstens Zeichen empfangen kann: Zeichen empfangen und auf PORTB ausgeben, dann mit LED oder so nachmessen.

Josef

--
These are my personal views and not those of Fujitsu Technology Solutions!
Josef Möllers (Pinguinpfleger bei FTS)
	If failure had no penalty success would not be a prize (T.  Pratchett)
Company Details: http://de.ts.fujitsu.com/imprint.html
Reply to
Josef Moellers

Dieser Code läuft bei mir einwandfrei. Hast du vieleicht den String im Code mem?

---------------------------------- #include

char message[]="**Hallo Welt**\n\r";

void putch(unsigned char ch) { while (!(UCSR0A & (1

Reply to
Gernot Fink

Das habe ich zuerst auch vermutet, aber selbst wenn das so ist, wäre die einzige Situation, in der nichts ausgegeben wird, wenn auf der Adresse von Message im ProgMem eine Null steht. Dann würde allerdings der der vom OP bereits durchgeführte Test mit dem Bitwackeln an PB1 nach jedem ausgegeben Byte ebenfalls nicht wackeln. Wackelt aber. Das kann's also wohl nicht sein.

Reply to
Heiko Nocon

Ich dachte in diesem angenommenen Fehlerfall wird der Inhalt des RAM ausgegeben während die Daten im Flash stehen. Leider sehen wir die Definition von s und greeting nicht.

--
MFG Gernot
Reply to
Gernot Fink

Ja, aber es müßte halt zumindest _irgendetwas_ ausgegeben werden. Nur in dem einem Fall nicht, wenn halt genau auf der Adresse von greeting im "falschen" Speicher eine Null steht. Dann greift die Abruchbedingung der for-Schleife, _bevor_ etwas gesendet wird. Aber dann dürfte halt auch nicht der Testpin wackeln, denn die Testroutine steht ja ebenfalls im Rumpf der for-Schleife und würde in diesem Fall genausowenig ausgeführt werden.

Reply to
Heiko Nocon

Moin!

Tja, vermutlich liegt der Fehler in dem Teil, den Du nicht gepostet hast. Irgendein blöder Tippfehler vielleicht...

Machst Du das in der Hauptschleife oder in der Ausgaberoutine? Wäre es möglich, daß die Routine überhaupt nicht aufgerufen wird? Sowas banales wie ein Semikolon hinter "void Ausgaberoutine (char ch)" würde schon reichen, und die Funktion ist leer.

Gruß, Michael.

Reply to
Michael Eggert

Am 18.5.2011 schrub Gernot Fink:

Ja, das war's!

char str[] = "Hallo Welt!\n"; ... UART_send(str);

und UART_send macht i.W. while (*s) UART_xmit(*s++);

Der Startup-Code kopiert den String sinnigerweise in den SRAM:

Der String steht im Flash auf Adresse 0x60.

00000026 : 26: 10 e0 ldi r17, 0x00 ; 0 28: a0 e6 ldi r26, 0x60 ; 96 2a: b0 e0 ldi r27, 0x00 ; 0 2c: ec e9 ldi r30, 0x9C ; 156 2e: f1 e0 ldi r31, 0x01 ; 1 30: 03 c0 rjmp .+6 ; 0x38

00000032 : 32: c8 95 lpm 34: 31 96 adiw r30, 0x01 ; 1 36: 0d 92 st X+, r0

00000038 : 38: ae 36 cpi r26, 0x6E ; 110 3a: b1 07 cpc r27, r17 3c: d1 f7 brne .-12 ; 0x32

Jedoch der Aufruf von UART_send bekommt die Flash-Adresse mit: 18c: 80 e6 ldi r24, 0x60 ; 96 18e: 90 e0 ldi r25, 0x00 ; 0 190: 9c df rcall .-200 ; 0xca

SRAM-Adresse 0x60 ist WDTCSR und wohl 0 Damit wird gar nix ausgegeben und der Pin bleibt auf "1"!

Ich hatte gedacht, zum Wiedereinstieg (ich hatte mal was mit dem c't-Netz-Schalter gemacht) was einfaches auszuprobieren: einen String auf der seriellen Schnittstelle auszugeben. Aber das war wohl schon *zu* kompliziert. Gestern haben ich erst mal nur versucht ein einzelnes Bit anzuknipsen (PB0) und das ging. Dann haben ich 0xa5 auf PORTB ausgegeben und das ging ... usw. Dann mal versucht, ein einzelnes Zeichen nach UDR0 und voila es kam auf dem Schirm! So habe ich mich dann vorwärts gehangelt bis ich das Problem erkannt habe.

Ich hatte irgendwo in meinen Gehirnwindungen gefunden, daß der Compiler bzw. das Laufzeitsystem den String in den SRAM kopiert und dann die SRAM-Adresse verwendet. Daß der kopiert und dann trotzdem die Flash-Adresse nutzt war mir nicht bewußt!

Naja ... Problem erkannt ... Problem umgehbar!

Danke an alle für die Diskussion!

Josef

--
These are my personal views and not those of Fujitsu Technology Solutions!
Josef Möllers (Pinguinpfleger bei FTS)
	If failure had no penalty success would not be a prize (T.  Pratchett)
Company Details: http://de.ts.fujitsu.com/imprint.html
Reply to
Josef Moellers

Am 18.5.2011 schrub Heiko Nocon:

Siehe mein anderes Posting von gerade betreffend der Ursache.

Warum der Testpin gewackelt hat, obwohl ich auf der seriellen Ausgabe nix gesehen habe, weiß ich auch nicht mehr.

Was ich aber auch gesehen habe ist, daß die fehlerhafte Programmierung wohl dazu geführt hat, daß der Chip regelmäßig über Los gegangen ist bzw. wohl irgendwie einen Reset aufgedrückt bekommen hat: wenn ich fix

0xa5 auf PORTB ausgegeben habe und dann "while (1);" mache, blinkte mein LED-Display (alle 8 Pins von PB), was es eigentlich gar nicht machen dürfte.

Vielleicht auch ein Spannungsversorgungsproblem ... obwohl das Netzteil aus einem alten DAP4 stammt, also rechlich A hat und auch ohne Last eine stabile Spannung liefert.

Ganz geklärt ist die Sache nicht, aber das Leben braucht Geheimnisse ;-)

Jetzt kann ich wenigstens meine eigentlichen Projekte angehen!

Danke nochmals,

Josef

--
These are my personal views and not those of Fujitsu Technology Solutions!
Josef Möllers (Pinguinpfleger bei FTS)
	If failure had no penalty success would not be a prize (T.  Pratchett)
Company Details: http://de.ts.fujitsu.com/imprint.html
Reply to
Josef Moellers

Nicht wirklich. Der so definierte String befindet sich im Adressraum des RAM. Da er vom Startupcode beim Boot erst dorthin kopiert werden muss befindet sich im Flash natuerlich eine Kopie, der Pointer str muss aber auf die Adresse im RAM zeigen.

Wenn du den String ausschliesslich im Flash haben willst, dann musst du ihn so definieren: const char PROGMEM str2[] = "Hallo Welt!\n"; Der Pointer str2 zeigt dann ins Flash und der Startup code muellt dir nicht das RAM voll. Durch die Harvard-Architektur der AVRs koennen normale Funktionen dann aber nicht drauf zugreifen weil der GCC den bei von Neumann Maschinen (dafuer wurde er eigentlich gemacht) einzigen Adressraum bei AVRs auf das RAM "mapped". In der avr-libc gibt es daher als Workaround alle String-Funktionen zweimal, z.B. strncpy() und strncpy_P(). Letztere dienen zum kopieren zwischen den beiden Adressraeumen.

Der Startup code sieht falsch aus, der ueberschreibt den memory mapped I/O-Bereich eines ATmega88. Bist du sicher, dass du dem Compiler

-mmcu=atmega88 angegeben hast? Offenbar verwendet er die memory map fuer einen uralten AVR ohne "extended I/O", bem ATmega88 sollte er das data segment ab 0x0100 anlegen (also fuer die obige Schleife X auf 0x0100 statt auf 0x0060 initialisieren).

Das wuerde auch erklaeren warum dein Programm Amok laeuft, I/O Register eignen sich nicht wirklich gut zum Speichern von Variablen ...

Micha

Reply to
Michael Baeuerle

Mit codemem sieht es natürlich auch gut aus (nur die relevanten Zeilen):

---------- #include char PROGMEM message[]="**Hallo Welt**\n\r";

00000034 : 34: 2a 2a 48 61 6c 6c 6f 20 57 65 6c 74 2a 2a 0a 0d **Hallo Welt**..

-----------

----------- for (s = message; pgm_read_byte(s) != '\0'; s++)putch(pgm_read_byte(s));

ae: e4 e3 ldi r30, 0x34 ; 52 . c4: 94 91 lpm r25, Z .

31 96 adiw r30, 0x01

-----------

AVRGCC scheint bei Pointern nicht zwishen den verschiedenen Addressräumen zu unterscheiden.

--
MFG Gernot
Reply to
Gernot Fink

Achtung: nicht nur dem Compiler, auch dem Linker! (BTDTGNT)

cu Michael

Reply to
Michael Schwingen

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.