Forum: Compiler & IDEs USART sendet falsch


von Julien M. (ljminti)


Lesenswert?

Hallo zusammen,

Ich habe mir nun einmal das GCC-Tutorial durchgelesen und auch das
senden mit dem USART ausprobiert.
AVR: mega8515
Terminalprogramm: Br@y

Den Sendecode habe ich 1:1 aus dem Tutorial übernommen.
------------------------
#include <avr/io.h>
#include <avr/interrupt.h>
#include <inttypes.h>

#define CLOCK    8000000          //Clock 8MHz
#define BAUD    19200          //USART BAUD
#define UBRR_BAUD  ((CLOCK/(16*BAUD))-1)

int uart_putc(unsigned char c)
{
    while (!(UCSRA & (1<<UDRE))); /* warten bis Senden moeglich */
    UDR = c;                      /* sende Zeichen */
    return 0;
}

int main(void) {

    DDRD   = 0xff;
  PORTD   |= (1 << PD7);
    UCSRB   |= (1<<TXEN);  // UART TX einschalten
  UCSRA   |= (1 << U2X);
    UCSRC   |= ( 1 << URSEL )|( 3<<UCSZ0 );  // Asynchron 8N1
    UBRRH  = (uint8_t) (UBRR_BAUD>>8);  // USART Baud
  UBRRL    = (uint8_t) UBRR_BAUD;

  uart_putc('A');
}
-----------------------

Mein Problem ist jetzt dass im Terminal zwar jedesmal wenn ich den AVR
resete was ankommt allerding immer 0x00, obwohl ich ja 'A' sende.
Bin noch Neuling in der Welt von C :)

Woran kann das liegen?

Gruß Julien

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Taktfrequenz des ATmega auch wirklich von 1 MHz auf 8 MHz
gedreht?

von Julien M. (ljminti)


Lesenswert?

Nun der mega8515 hängt auf nem STK500 mit externem 8MHz Quarz.
Muss hier dann noch was anderes eingestellt werden bzw dann an den FUSE
BITs?

RS232 SPARE ist mit PortD des Megas verbunden.

Zum Proggen nehme ich das AVR Studio.-->erhalte dort keinerlei
Fehlermeldungen.

von Simon K. (simon) Benutzerseite


Lesenswert?

Jap, schau dir mal die Registerkarte "Fuses" im AVR Studio an. da
kannst du das schön bequem auswählen woher er den takt nehmen soll.
dann klappts auch mitm nachbarn.

von Julien M. (ljminti)


Lesenswert?

Nun dort ist EXT. CRYSTAL/RESONATOR HIGH SPEED ausgewählt.
CKSEL=1111
SUT=11

ebenso:
BODLEVEL=1
BOOTSZ=00

Leider funktioniert es nicht, oder ist eben gerade diese einstellung
falsch?

von Olaf_K (Gast)


Lesenswert?

Die Portinitialisierung in main() birgt eine Falle:

    DDRD   = 0xff;

Beim "DDRD = 0xff" schaltest Du alle Pins als Output, also geht auch
der TX-Pin (PD1) auf Low, da in PortD zu dieser Zeit nur Nullen stehen.
Diese Low-Flanke gelangt aber als Startbit zum PC und dessen UART
versucht nun, ein Zeichen zu samplen. Das kurz danach korrekt
abgesendete 'A' kann dadurch nicht korrekt empfangen werden.

Lösung:
Am besten den TX-Pin erstmal als Eingang lassen, d.h. bei der
DDR-Anweisung auf Null lassen. Sobald der Transmitter über das TXEN-Bit
aktiviert wird, setzt der Controller den Pin automatisch auf High und
als Ausgang. Also z.B.:

. . .
int main(void) {

    DDRD = 0xff - (1<<PD1);
    . . .


Oder: Zuerst PORTD setzen, dabei das TX-Bit (PD1) auf High setzen. Dann
erst im DDRD als Ausgang setzen. Dadurch bleibt der Pin die ganze Zeit
auf High. Also:

. . .
int main(void) {

    PORTD = (1 << PD7) | (1 << PD1) ;
    DDRD  = 0xff;
    . . .


Während Reset sind die Controller-Pins übrigens hochohmig und werden
vom MAX232 automatisch als High erkannt (über interne Pullups im
MAX232).

MfG Olaf

von Julien M. (ljminti)


Lesenswert?

@Olaf
Vielen Dank für diesen Hinweis:)
Leider hat sich das Problem dadurch noch nicht gelöst!

Es wird immernoch nach jedem RESET eine 0 gesendet.
Wo können denn noch Fehler stecken?

Gruß

von Julien M. (ljminti)


Lesenswert?

Hab gerade gesehen dass U2X = 1
Dann stimmt natürlich die Berechnung von UBRR nicht.

Aber egal was ich nehme, U2X = 0 mit entsprechender Berechnungsformel
oder obengenanntes. Nix geht-> außer der netten NULL.
Gibt es irgendwelche Vorgaben, wie mann übertragen muss damit der PC
was erkennt?

von Julien M. (ljminti)


Angehängte Dateien:

Lesenswert?

Naja also irgendwie verzweifel ich langsam an diesem USART!

Wenn schon das senden nicht funktioniert dann wollte ich mal sehen ob
er wenigstens was vom PC empfangen kann. Aber ebenfalls vergeblich :(

Ich habe jetzt einfach mal meinen Source inden Anhang gepackt.
Es wäre sehr hilfreich wenn sich jemand erbarmen könnte unter
Zuhilfenahme dieses Source(enthält eine USART lib)einen kleinen Code zu
schreiben der folgendes prüft.

- Zeichen(BYTE) an den PC senden (kann dann ja übers terminalprogramm
ekannt werden)
- Zeichen(BYTE) an den µC senden und dieses dann an PORTB über LEDs
ausgeben.

Vielen Dank im Vorraus.

Aber wenigstens gibt es Lichtblicke für mich als Anfänger in der Welt
der Hochsprache.
Ansteuerung von Ports (LEDs Taster) sowie einer PWM funktionieren sehr
gut!

Gruß Julien

von Dirk B. (dirk-)


Lesenswert?

Hi,

fehlt da kein " sei(); " ?

Gruß,
Dirk

von Simon K. (simon) Benutzerseite


Lesenswert?

Nö, gibt ja auch keine Interrupts. Also brauch man auch kein sei();

von Peter (Gast)


Angehängte Dateien:

Lesenswert?

Auf die schnelle sieht es soweit ganz gut aus!

Habe folgendes korrigiert:

in usart.c sowie in (usart)test.c
=> #include "usart.h"     //Hochkommas "" statt <>

in usart.c Zeile 35:
=> kein semicolon [;] nach dem #endif

Weiss nicht ob's daran lag.

Hab das ganze als AvrStudio-Projekt angehängt, probier mal ob's bei
Dir tut. Ich hab leider kein AtMega8515 zum ausprobieren

Gruss Peter

von Patrick D. (oldbug) Benutzerseite


Lesenswert?

>=> kein semicolon [;] nach dem #endif

Das ist auch nicht notwendig. Präprozessoranweisung terminiert man
nicht mit Semikola.

von Julien M. (ljminti)


Lesenswert?

@Peter

Vielen Dank für deine Arbeit, habs auch mal getestet, aber irgendwie
rührt sich da nix.
Hab leider auch kein scope da um zu sehen was am TX bzw. Rx raus-/rein
geht :(

P.S.: der code von Dir sollte Eigentlich auf den meisten megas laufen!

Ich werde jetzt nochmal einen Test machen, bei dem ich auschließlich
das ganze interuptgesteuert mache. Mal sehen ob dann was geht.
Ansonsten kann ja nur noch was am STK500 nicht stimmen.
Ist aber eigentlich auzuschließen da ja mal nur "0" nach einem rest
ankam.

Gruß

von Karl H. (kbuchegg)


Lesenswert?

Schreibs nochmal um, sodass ein einer Schleife
staendig gesendet wird. Dann haeng mal eine
LED an den Transmit Ausgang. Die muesste eigentlich
flackern. Dann check nochmal das Seriell-Kabel durch
(gekreuzt, nicht-gekreuzt) und stell sicher, dass
das Sende-Signal am PC auch am richtigen Pin ankommt.

Meistens sind es die einfachen Dinge, die schief gehen.

Auf Interrupt wuerde ich da zunaechst mal nicht bauen.
Wenns in der allereinfachsten Version nicht geht, dann
bringen Interrupts nur einen Level Komplexitaet mehr
ins Spiel. Zum Fehlersuchen sollen die Dinge aber so
einfach wie moeglich sein.

von Julien M. (ljminti)


Lesenswert?

Hier noch der geänderte Code:

#include <avr/io.h>
#include <avr/interrupt.h>
#include <inttypes.h>
#include "usart.h"

typedef unsigned char BYTE;
typedef unsigned short WORD;

void reset(void)
{
  DDRB   = 0xff;
  PORTB  = 0x00;
  DDRD  |= (1<<DDD1);
  PORTD   |= (1<<PD1);
}

int main(void)
{
  reset();
    usart_init(9600, 8, 'N', 1);    //Init USART mit 9600 8N1
  while(1)
  {
    usart_putc(2);
  }
}

Wenn ich den jetzt ausführe Leuchtet die LED an PD1 permanent.
ist das jetzt richtig? ich vermute dass Sie leuchtet da ich PD1 auf
High beim reset gesetz habe.

Weiter ist mir beim debuggen noch folgendes aufgefallen.
Nach der initialisierung des USART **usart_init(9600, 8, 'N', 1); **
Hat UBRRL = 51 und in UBRRH sind Bit 1,2 und 7 gesetzt.
Hat das nicht zur folge das dann die Baudrate nicht mehr stimmt? oder
hat des mit URSEL(Bit7) zu tun und spielt keine rolle?

Gruß

von Julien M. (ljminti)


Lesenswert?

Es könnte alles so einfach sein:)
Hab den Fehler endlich gefunden

Es lag am STK500

Entgegen den angaben im AVR Studio muss Pin RXD vom SPARE mit dem RX
vom  µC verbunden werden. genauso TXD

komisch, iss aber so

Trotzdem nochmals vielen Dank für eure Bemühungen.
Man merkt wieder einmal, wie hilfreich es ist gemeinsam Probleme zu
lösen.

Gruß Julien

von Peter (Gast)


Lesenswert?

@Patrick Dohmen

>>kein semicolon [;] nach dem #endif

>Das ist auch nicht notwendig. Präprozessoranweisung
>terminiert man nicht mit Semikola.
_______________________

Mein ich ja auch, das Semikolon war zuviel! Doch ich habe mich
zugegebenermassen nicht klar genug ausgedrück!

Gruzzo  Peter

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.