Atmega8 und USART - Empfangen funktioniert, Senden nicht.

Gast #1309598
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
Gast #1309717
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.
#1309879
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.
Gast #1310503
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.
Gast #1310567
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.
#1310579
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.
#1310631
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.
Gast #1312223
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?
#1312545
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.
#1312559
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.
#4960643
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 =)
Gast #4960789
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 ;-)

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren