Forum: Mikrocontroller und Digitale Elektronik Atmega8 und USART - Empfangen funktioniert, Senden nicht.


von Julian Schmitz (Gast)


Lesenswert?

Hallo,

ich weiß, dass dieses Feld schon reichlich beackert wurde, aber ich habe 
zu meinem Problem tatsächlich keine passende Lösung gefunden.

Mein Atmega8 mit MAX232 empfängt zuverlässig Daten vom PC, aber beim 
Versand kommt am PC nichts an. Das Kabel ist mit 'nem Modem geprüft.

Ich habe mein Testprogramm nun völlig auf den Rahmen des im Datenblatts 
angegebenen Codes zurückgebaut:
1
#include <stdint.h>
2
#include <avr/io.h>
3
#include <avr/interrupt.h>
4
#include <avr/signal.h>
5
#include <util/delay.h>
6
#define F_CPU 3686400
7
8
void USART_Init( unsigned int baud )
9
{
10
    /* Set baud rate */
11
    UBRRH = (unsigned char)(baud>>8);
12
    UBRRL = (unsigned char)baud;
13
    /* Enable Receiver and Transmitter */
14
    UCSRB = (1<<RXEN)|(1<<TXEN);
15
    /* Set frame format: 8data, 2stop bit */
16
    UCSRC = (1<<URSEL)|(1<<USBS)|(3<<UCSZ0);
17
}
18
19
void USART_Transmit( unsigned char data )
20
{
21
    /* Wait for empty transmit buffer */
22
    while ( !( UCSRA & (1<<UDRE)) ){
23
    }
24
    /* Put data into buffer, sends the data */
25
    UDR = data;
26
}
27
28
unsigned char USART_Receive( void )
29
{
30
    /* Wait for data to be received */
31
    while ( !(UCSRA & (1<<RXC)) );
32
    /* Get and return received data from buffer */
33
    return UDR;
34
}
35
36
void USART_Flush( void )
37
{
38
    unsigned char dummy;
39
    while ( UCSRA & (1<<RXC)){
40
        dummy = UDR;
41
    }
42
}
43
44
int main(void){
45
    USART_Init(95); //2400 BAUD bei 3686400
46
    DDRD = 12;
47
    PORTD = 0;
48
    while(1){
49
        /*if(USART_Receive() == 8){
50
            PORTD ^= 4;
51
        }
52
        else if(USART_Receive() == 16){
53
            PORTD ^= 8;
54
        }*/
55
        _delay_ms(100);
56
        USART_Transmit('A');
57
        PORTD ^= 4;
58
    }
59
}

Der auskommentierte Teil ist der Empfangsteil, der tadellos funktioniert 
(lässt 2 unterschiedliche LEDs an und ausgehen, durch das "==" gehe ich 
mal von einem stabilen Empfang aus).
Aber das Senden klappt absolut nicht. Ich habe mittlerweile auch schon 
verschiedene Terminalprogramme, inkl. eines Selbstgeschriebenen 
verwendet, aber es kommt absolut nichts an.

BAUD-Raten habe ich auch Verschiedene getestet, daran dürfte es nicht 
liegen (auch hier auf Basis der im Datenblatt angegebenen Werte).

Ich werde beinahe verrückt, kann mir jemand weiterhelfen und sagen woran 
es noch liegen könnte?

Gruß
Julian

von Andreas (Gast)


Lesenswert?

Hilf du uns mal mit nem Schaltplan

von Julian Schmitz (Gast)


Lesenswert?


von Julian Schmitz (Gast)


Lesenswert?

Also dieser Bausatz natürlich, der Link oben ist vom schon bestückten 
Board.

http://shop.myavr.de/Bausätze%20und%20Platinen/myAVR%20Board%20MK1%20LPT%20PLUS,%20Bausatz.htm?sp=article.sp.php&artID=17

Dürfte aber keine Rolle spielen.

von Falk B. (falk)


Lesenswert?


von Walter (Gast)


Lesenswert?

wenn möglich schau dir mal das Ausgangssignal an, wenn du kein oszi hast 
kannst du auch endlos 0xaa senden, dann soltte etwa die halbe Spannung 
anliegen

von Julian Schmitz (Gast)


Lesenswert?

Falk: Danke für die Checkliste, aber ich kann da jetzt erstmal keinen 
Punkt entdecken der bei mir zutrifft. Zumal das Empfangen ja stabil 
funktioniert.

Walter: Habe weder Oszi noch Multimeter, aber kann mir sicher die Tage 
mal eines leihen, so dass ich zumindest mal die Spannungen auf'm TX 
checken kann, danke für den Tipp.

von Christopher G. (cbg)


Lesenswert?

Julian Schmitz schrieb:
> ...
> void USART_Transmit( unsigned char data )
> {
>     /* Wait for empty transmit buffer */
>     while ( !( UCSRA & (1<<UDRE)) ){
>     }
>     ...
> }
>
> unsigned char USART_Receive( void )
> {
>     /* Wait for data to be received */
>     while ( !(UCSRA & (1<<RXC)) );
>     ...
> }

Vl optimiert der compiler die Warteschleife beim senden weg, da sie 
wirklich leer ist. Mach sie mal so wie beim Receive also while(); oder 
gib ein asm volatile("nop\n\t" ::); rein.

von Julian Schmitz (Gast)


Lesenswert?

An der Leerschleife lag es nicht. Wäre mir aber auch neu, dass eine 
While-Schleife ohne Körper, vom Compiler anders behandelt als eine mit 
leerem Körper.
Ich hab's mittlerweile auch auf dem baugleichen Board eines Kollegen 
getestet mit exakt gleichem Ergebnis.

Ich bin immer noch für weitere Vorschläge offen.

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

Lass die UDRE-Abfrage einfach mal ganz weg, mit dem 100ms-Delay sollte 
das vorige Zeichen ja garantiert schon weg sein :-/

BTW:
Hängt der uC an der UDRE-Abfrage fest, oder blinkt die LED an
>> PORTD ^= 4;

von Julian Schmitz (Gast)


Lesenswert?

Die LED blinkt, er hängt also nicht in der Warteschleife.
Ich habe diese jetzt auch mal weggelassen, ohne Erfolg.

Wie verhält sich der MAX232 eigentlich wenn von außen ein Signal auf TX 
ankommt?

Btw. vielen Dank für die große Resonanz.

von Michael M. (mikmik)


Lesenswert?

könnte es daran liegen, dass du DDR setzt nachdem du den uart init 
machst?
in deinem code setzt du ja das DDRD für pin 0-4 (dec. 12) wo auch der 
UART dranhängt (pin0 & pin1).

von Karl H. (kbuchegg)


Lesenswert?

Julian Schmitz schrieb:

> Walter: Habe weder Oszi noch Multimeter, aber kann mir sicher die Tage
> mal eines leihen, so dass ich zumindest mal die Spannungen auf'm TX
> checken kann, danke für den Tipp.

In der Zwischenzeit kannst du auch mal ein LED an den Ausgang hängen 
(mit Vorwiderstand). Das Blinzeln der LED wirst du sehen können. Zur Not 
einfach mit der Baudrate runtergehen. Bei 300 Baud sieht man eine LED 
schon wunderbar blinken.

von Julian Schmitz (Gast)


Lesenswert?

Habe gerade alle DDR-Geschichten auskommentiert - keine Änderung. :/

von Christopher G. (cbg)


Lesenswert?

Also bei mir funktionniert das Programm. Muss wohl an der Verkabelung 
liegen.
Ich hab nur #define F_CPU als erste Zeile stehen (für delay.h), #include 
<avr/delay.h> (avr libc 1.2.5) und den entsprechenden UBRR Wert für 2400 
bps bei 16 MHz eingetragen.

Weiters ist _delay_ms(100) auch bei 3 MHz nicht möglich. "The maximal 
possible delay is 262.14 ms / F_CPU in MHz." Dadurch kommen die Zeichen 
aber einfach nur schneller daher.
Hab mit
1
  uint8_t w;
2
  for(w = 0; w < 100; w++)
3
          _delay_ms(10);
 einen 1 Sek busy-wait gemacht.

von Julian Schmitz (Gast)


Lesenswert?

Ach, der delay ist nur schnell reingesetzt, normalerweise arbeite ich 
mit _delay_loop2 in Schleifen.

Also ich habe jetzt mal mit 'ner LED geguckt ob da überhaupt irgendwas 
rausgeht. Es geht nichts raus :S

Gibt es vielleicht irgendeine Form von Flußkontrolle, also z.B. CTS/RTS?

von Hubert G. (hubertg)


Lesenswert?

Julian Schmitz schrieb:
> Falk: Danke für die Checkliste, aber ich kann da jetzt erstmal keinen
> Punkt entdecken der bei mir zutrifft. Zumal das Empfangen ja stabil
> funktioniert.
>
Das heisst das du die Checkliste nicht durchgearbeitet hast. Würde ich 
an deiner Stelle aber machen, bei mir läuft dein Programm einwandfrei, 
schreibt schöne A ins Terminalfenster.

von Karl H. (kbuchegg)


Lesenswert?

Julian Schmitz schrieb:

> Also ich habe jetzt mal mit 'ner LED geguckt ob da überhaupt irgendwas
> rausgeht. Es geht nichts raus :S

Wo hast du kontrolliert?
Halt die LED einfach mal an den Prozessorpin.
Wenns dort wackelt, dann verfolg das Signal über die Platine, bis du 
letztendlich am Kabelanschluss angelangt bist. Irgendwo dazwischen geht 
es verloren.

von Sercan S. (disaster35)


Lesenswert?

Hallo ich habe exakt das gleiche Problem gehabt,

ich möchte zwar ungerne ein Beitrag aus 2009 wieder hochholen, da Ihr 
nicht zu einer Lösung gekommen seid, denke ich mal wäre es nicht 
schlecht, für anderen ein weiteren Info hier reinzutun, bevor da ein 
neuer Beitrag erstellt wird.

Bei mir lag es daran, dass ich den TXEN beim init() nicht mit 
eingeschaltet habe.

1
//SO IST NUR DER EMPFANGPIN RX EINGESCHALTET
2
//UCSRB |= (1<<RXEN);
3
4
//NUN SIND BEIDE PINS EINGESCHALTET UND EMPFANGEN SOWIE SENDEN KLAPPT //EINWANDFREI
5
UCSRB |= (1<<RXEN)| (1<<TXEN);

Ich hoffe, dass es irgendwann mal jemanden helfen, der genau den 
gleichen dummen Fehler wie ich gemacht hat.

Liebe Grüße =)

: Bearbeitet durch User
von tommy (Gast)


Lesenswert?

Auch wenn's 8 Jahre her ist...

Julian Schmitz schrieb:
> #define F_CPU 3686400
>
> void USART_Init( unsigned int baud )
> {
>     /* Set baud rate */
>     UBRRH = (unsigned char)(baud>>8);
>     UBRRL = (unsigned char)baud;
>     /* Enable Receiver and Transmitter */
>     UCSRB = (1<<RXEN)|(1<<TXEN);
>     /* Set frame format: 8data, 2stop bit */
>     UCSRC = (1<<URSEL)|(1<<USBS)|(3<<UCSZ0);
> }

Julian Schmitz schrieb:
> int main(void){
>     USART_Init(95); //2400 BAUD bei 3686400

hier-------------^^ sollte dann besser 2400 stehen ;-)

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.