Forum: Compiler & IDEs Zeichenempfang mit USART (HyperTerminal)


von Jimmy (Gast)


Lesenswert?

Hi,

Ich kann auf dem HyperTerminal alle gesendeten Strings, Zeichen etc. 
korrekt sehen, das Senden klappt also. Aber wenn ich was in den 
HyperTerminal tippe, kann mein ATmega32 nichts empfangen. Hab den 
Standard-code aus dem Manual ausprobiert.
1
unsigned char USART_receive( void )
2
{
3
/* Wait for data to be received */
4
while ( !(UCSRA & (1<<RXC)) )
5
;
6
/* Get and return received data from buffer */
7
return UDR;
8
}
9
10
void USART_transmit( unsigned char data )
11
{
12
/* Wait for empty transmit buffer */
13
while ( !( UCSRA & (1<<UDRE)) )
14
;
15
/* Put data into buffer, sends the data */
16
UDR = data;
17
}
18
19
int main (void)
20
{
21
  UCSRB |= (1 << RXEN) | (1 << TXEN);   // Turn on the transmission and reception circuitry
22
  UCSRC |= (1 << URSEL) | (3 << UCSZ0); // Use 8N1
23
24
  UBRRL = BAUD_PRESCALE; // Load lower 8-bits of the baud rate value into the low byte of the UBRR register
25
  UBRRH = (BAUD_PRESCALE >> 8); // Load upper 8-bits of the baud rate value into the high byte of the UBRR register
26
27
  UCSRB |= (1 << RXCIE); // Enable the USART Recieve Complete interrupt (USART_RXC)
28
  
29
  sei(); // Enable the Global Interrupt Enable flag so that interrupts can be processed
30
31
32
        char ReceivedByte;
33
34
  for (;;) // Loop forever
35
  {
36
    USART_transmit('_'); //klappt
37
    ReceivedByte=USART_receive(); //klappt nicht :(
38
  }   
39
}

Kann es sein, das evtl. der rx-teil des Kabels defekt ist oder sowas?
Gruß,
Jimmy

von Falk B. (falk)


Lesenswert?

@ Jimmy (Gast)

>HyperTerminal tippe, kann mein ATmega32 nichts empfangen. Hab den
>Standard-code aus dem Manual ausprobiert.

Dein Quelltext sieht OK aus.

>Kann es sein, das evtl. der rx-teil des Kabels defekt ist oder sowas?

Möglich. Klemm einfach mal das TX Pin des MAX232 vom AVR ab und verbinde 
es mit dem RX Pin. Dann müssten die Zeichen zurückkommen. Wenn nicht ist 
dein Kabel oder Pegelwandler defekt.

MFG
Falk

von Stefan B. (stefan) Benutzerseite


Lesenswert?

1
   // ...
2
   UCSRB |= (1 << RXCIE); // Enable the USART Recieve Complete interrupt (USART_RXC)
3
   sei();
4
   // ...

Jimmy, wo ist dein Interrupthandler? Bzw. was soll dieser Code, wenn 
dein USART_receive ein stinknormales RS232-Polling macht?

Und im Code oben fehlen noch Teile (mindestens die Includes und ein paar 
Defines).

Und woran meinst du genau zu erkennen, dass auf dem Atmega32 keine 
Zeichen empfangen werden?

von Jimmy (Gast)


Lesenswert?

Mhhja, soll eigentlich interrupt gesteuert funktionieren, da aber das 
Empfangen nicht ging, hab ich den "einfachsten" Code ausprobiert. Nun 
ja, war wirklich ein Kabeldefekt. Empfangen funktioniert jetzt prima, 
danke für die Mühe, Jungs.

von Tobias (Gast)


Lesenswert?

Hallo Jimmy,
ich habe jetzt das gleiche Problem wie du,
könntest du mir bitte dein Code senden, damit ich Senden und Empfangen 
mit USART schaffen kann.
DANKE.

von Karl H. (kbuchegg)


Lesenswert?

Tobias schrieb:
> Hallo Jimmy,
> ich habe jetzt das gleiche Problem wie du,
> könntest du mir bitte dein Code senden, damit ich Senden und Empfangen
> mit USART schaffen kann.


Lies dir den Abschnitt im AVR-GCC-Tutorial durch.
Dann schaffst du es ebenfalls - ganz alleine.

http://www.mikrocontroller.net/articles/AVR-GCC-Tutorial/Der_UART

Und wenns nicht geht:
http://www.mikrocontroller.net/articles/AVR_Checkliste#UART.2FUSART

von Tobias (Gast)


Lesenswert?

Hallo Zusammen,
ich habe schon das geschafft aber leider kann ich nicht empfangen auf 
meinem LCD.
kann Jemand vielleicht mir helfen.
1
#include <avr/io.h>
2
#include <inttypes.h>
3
#include <avr/interrupt.h>
4
#include <util/delay.h>
5
6
#define F_CPU 1000000UL
7
8
#define BAUD 9600UL // Baudrate
9
#define UBRR_VAL (F_CPU/(BAUD*8)-1)
10
#define uart_maxstrlen 25 // Definiere maximale Laenge für Empfang
11
volatile uint8_t uart_str_complete=0;
12
volatile uint8_t uart_str_count=0;
13
volatile char uart_string[uart_maxstrlen+1]="Test";
14
ISR(USART_RXC_vect)
15
{
16
unsigned char buffer;
17
buffer = UDR1;
18
if ( uart_str_complete==0 )
19
{
20
if (buffer!='\n' && buffer!='\r' && uart_str_count<uart_maxstrlen-1)
21
{
22
uart_string[uart_str_count]=buffer;
23
uart_str_count++;
24
}
25
 else 
26
 {
27
uart_string[uart_str_count]='\0';
28
uart_str_count=0;
29
uart_str_complete=1;
30
}
31
}
32
uart_str_complete=0;
33
}
34
void uart_init(void)
35
{
36
UCSR1A |= (1<<U2X1);
37
UCSR1B |= (1<<RXEN1)|(1<<TXEN1); //|(1<<RXCIE1); // UART RX, TX und RX Interrupt einschalten
38
UCSR1C |= (1<<UCSZ11)|(1<<UCSZ10); // Asynchron 8N1 // (1<<UMSEL11)|
39
UBRR1H = UBRR_VAL >> 8;
40
UBRR1L = UBRR_VAL & 0xFF;
41
}
42
int uart_putc(unsigned char c)
43
{
44
while (!(UCSR1A & (1<<UDRE1))) // Wait for empty transmit buffer
45
{
46
}
47
UDR1 = c; // put c into buffer, sends the c
48
return 0;
49
}
50
uart_puts (char *s)
51
{
52
while (*s)
53
{
54
uart_putc(*s);
55
s++;
56
}
57
}
58
uint8_t uart_getc(void)
59
{
60
while (!(UCSR1A & (1<<RXC1))) // warten bis Zeichen verfuegbar
61
;
62
return UDR1; // Zeichen aus UDR an Aufrufer zurueckgeben
63
}
64
void uart_gets( char* Buffer, uint8_t MaxLen )
65
{
66
uint8_t NextChar;
67
uint8_t StringLen = 0;
68
NextChar = uart_getc(); // Warte auf und empfange das nächste Zeichen
69
// Sammle solange Zeichen, bis:
70
// * entweder das String Ende Zeichen kam
71
// * oder das aufnehmende Array voll ist
72
while( NextChar != '\n' && StringLen < MaxLen - 1 ) 
73
{
74
*Buffer++ = NextChar;
75
StringLen++;
76
NextChar = uart_getc();
77
}
78
// Noch ein '\0' anhängen um einen Standard
79
// C-String daraus zu machen
80
*Buffer = '\0';
81
}
82
int main (void)
83
{
84
    //DDRD = 0xFF;
85
    //PORTD = 0xFF;
86
uart_init();
87
//sei();
88
while(1)
89
{
90
uart_puts(uart_string);
91
uart_puts("\n");
92
_delay_ms(5);
93
 }
94
}

Danke

von Karl H. (kbuchegg)


Lesenswert?

1) Rücke deinen Code ein!

2) entscheide dich, ob du den Empfang mittels Interrupt oder mittels
   Polling machen willst und wirf den jeweils anderen Code raus. Auf
   Dauer verwirrt das, wenn beide Möglichkeiten im Code vorhanden sind.

3) Rücke deinen Code ein

Berücksichtige ich Punkt 1) und Punkt 3), dann lande ich bei
1
int main (void)
2
{
3
    //DDRD = 0xFF;
4
    //PORTD = 0xFF;
5
  uart_init();
6
  //sei();
7
8
  while(1)
9
  {
10
    uart_puts(uart_string);
11
    uart_puts("\n");
12
    _delay_ms(5);
13
  }
14
}

Ein kurzer Blick in die uart_init Funktion zeigt mir
1
void uart_init(void)
2
{
3
  UCSR1A |= (1<<U2X1);
4
  UCSR1B |= (1<<RXEN1)|(1<<TXEN1); //|(1<<RXCIE1); // UART RX, TX und RX Interrupt einschalten
5
  UCSR1C |= (1<<UCSZ11)|(1<<UCSZ10); // Asynchron 8N1 // (1<<UMSEL11)|
6
7
  UBRR1H = UBRR_VAL >> 8;
8
  UBRR1L = UBRR_VAL & 0xFF;
9
}

dass Interrupts nicht eingeschaltet sind, was ok ist. Das bedeutet aber 
auch, du musst die Funktion uart_gets aufrufen, damit irgendein Code 
einen empfangenen String in das Array uart_string schreibt. Wieder 
zurück in die main() Funktion: Wo genau ist denn da jetzt der Aufruf der 
Funktion uart_gets? Ich kann keinen entdecken.


Sagte ich schon, dass du deinen Code einrücken sollst? Code 
übersichtlich anzuordnen ist ein nicht ganz unwesentlicher Baustein, 
wenn es darum geht zu analysieren, wass denn eigentlich der Code macht, 
bzw. nicht macht. Dazu gehören Einrückungen genauso, wie es Leerzeilen 
sind, die man nach funktionalen Blöcken einfügt (zb wenn die 
Initialisierung in main() beednet ist und die Hauptschleife beginnt) um 
dort dem Gehirn einen optischen Trenner zu präsentieren. Das schlimmste 
was du tun kannst: Code in einer Wurscht ohne irgendwelcher Trenner und 
alles am linken Rand runterzuschreiben. Denn dann erkennt man genau gar 
nicjts mehr. Vor allen Dingen dann nicht, wenn man noch keine Übung hat.
Vergleiche das hier
1
void uart_gets( char* Buffer, uint8_t MaxLen )
2
{
3
uint8_t NextChar;
4
uint8_t StringLen = 0;
5
NextChar = uart_getc(); // Warte auf und empfange das nächste Zeichen
6
// Sammle solange Zeichen, bis:
7
// * entweder das String Ende Zeichen kam
8
// * oder das aufnehmende Array voll ist
9
while( NextChar != '\n' && StringLen < MaxLen - 1 ) 
10
{
11
*Buffer++ = NextChar;
12
StringLen++;
13
NextChar = uart_getc();
14
}
15
// Noch ein '\0' anhängen um einen Standard
16
// C-String daraus zu machen
17
*Buffer = '\0';
18
}

mit dem hier
1
void uart_gets( char* Buffer, uint8_t MaxLen )
2
{
3
  uint8_t NextChar;
4
  uint8_t StringLen = 0;
5
6
  NextChar = uart_getc(); // Warte auf und empfange das nächste Zeichen
7
8
  // Sammle solange Zeichen, bis:
9
  // * entweder das String Ende Zeichen kam
10
  // * oder das aufnehmende Array voll ist
11
  while( NextChar != '\n' && StringLen < MaxLen - 1 ) 
12
  {
13
    *Buffer++ = NextChar;
14
    StringLen++;
15
    NextChar = uart_getc();
16
  }
17
18
  // Noch ein '\0' anhängen um einen Standard
19
  // C-String daraus zu machen
20
  *Buffer = '\0';
21
}

In welcher Version wird die Struktur deutlicher, nämlich dass die 
Funktion im wesentlichen aus einer Schleife besteht in der die 
Einzelzeichen gesammelt und zusammengesetzt werden, garniert von ein 
bischen Code davor und danach? In welcher Version erkennt man schneller, 
was eigentlich alles innerhalb der Schleife steht?

von Tobias (Gast)


Lesenswert?

Ich bedanke mich Herr Karl Heinz Buchegger für die Hilfe aber leider 
konnte ich nicht weitergehen.
Ich habe mein LCD in PortA angeschlossen aber leider ich kann nur auf 
mein Hyperterminal "Test" senden und auf mein LCD nichts empfangen.
ich habe AT90USB1287.

mein Code sieht jetzt so aus.
#include <avr/io.h>
#include <avr/iousbxx6_7.h>
//#include "my_string.h"
#include <string.h>
#include <stdint.h>
#include <stdlib.h>
#include <stdio.h>
#include <util/delay.h>
#include <avr/interrupt.h>
#include "lcd.h"

#define F_CPU 1000000UL
#define BAUD 9600UL     // Baudrate

#define UBRR_VAL (F_CPU/(BAUD*8)-1)
#define uart_maxstrlen 25           // Definiere maximale Laenge für 
Empfang.

volatile uint8_t uart_str_complete=0;
volatile uint8_t uart_str_count=0;
volatile char uart_string[uart_maxstrlen+1]="Test";

// Variable


char c1;



//-----------------------------------------------------
//-----------------------------------------------------

ISR(USART_RXC_vect)
{
  unsigned char buffer;
  buffer = UDR1;

       if ( uart_str_complete==0 )

        {
          if (buffer!='\n' && buffer!='\r' && 
uart_str_count<uart_maxstrlen-1)

           {
             uart_string[uart_str_count]=buffer;
             uart_str_count++;
           }

            else

             {
                uart_string[uart_str_count]='\0';
                uart_str_count=0;
                uart_str_complete=1;
             }
        }
uart_str_complete=0;

}

//-----------------------------------------------------
//-----------------------------------------------------

void uart_init(void)
{
    UCSR1A |= (1<<U2X1);
    UCSR1B |= (1<<RXEN1)|(1<<TXEN1);    //|(1<<RXCIE1); // UART RX, TX 
und RX Interrupt einschalten
    UCSR1C |= (1<<UCSZ11)|(1<<UCSZ10); // Asynchron 8N1 // (1<<UMSEL11)

    UBRR1H = UBRR_VAL >> 8;
    UBRR1L = UBRR_VAL & 0xFF;
}

//-----------------------------------------------------
//-----------------------------------------------------

int uart_putc(unsigned char c)

{
  while (!(UCSR1A & (1<<UDRE1))) // Wait for empty transmit buffer
   {
   }
      UDR1 = c;                 // put c into buffer, sends the c
      return 0;
}


//-----------------------------------------------------
//-----------------------------------------------------

uart_puts (char *s)
{
   while (*s)
    {
      uart_putc(*s);
      s++;
    }
}

//-----------------------------------------------------
//-----------------------------------------------------

uint8_t uart_getc(void)
{
   while (!(UCSR1A & (1<<RXC1)) ); // warten bis Zeichen verfuegbar

   return UDR1;                   // Zeichen aus UDR an Aufrufer 
zurueckgeben
}

//-----------------------------------------------------
//-----------------------------------------------------

void uart_gets( char* Buffer, uint8_t MaxLen )

 {

    uint8_t NextChar;
    uint8_t StringLen = 0;

    NextChar = uart_getc(); // Warte auf und empfange das nächste 
Zeichen.

                               // Sammle solange Zeichen, bis:
                               // * entweder das String Ende Zeichen kam
                               // * oder das aufnehmende Array voll ist

       while( NextChar != '\n' && StringLen < MaxLen - 1 )
          {

            *Buffer++ = NextChar;
            StringLen++;
            NextChar = uart_getc();

          }

        // Noch ein '\0' anhängen um einen Standard
        // C-String daraus zu machen

        *Buffer = '\0';

 }

 //-----------------------------------------------------
 //-----------------------------------------------------

           // Main


int main (void)

 {
    init_timer(); // Initialisierung des Timers
    uart_init();
    lcd_init(LCD_DISP_ON);
    lcd_clrscr();
    lcd_gotoxy(0,0);
    DDRA |= (1<<2);
    //sei();
     while(1)

      {
        uart_puts(uart_string);
        uart_puts("\n");
        _delay_ms(500);
        //uart_gets();


    if (c1=='1')
         {
           c1=0;
             uart_putc(c1);
            lcd_putc(c1);
          PORTA |= (1<<2);
         }

       if(c1=='2')
         {
           c1=0;
             uart_putc(c1);
            lcd_putc(c1);
          PORTA &=~ (1<<2);
         }

       cli();

     }
 }

von Karl H. (kbuchegg)


Lesenswert?

Tobias schrieb:
> Ich bedanke mich Herr Karl Heinz Buchegger für die Hilfe aber leider
> konnte ich nicht weitergehen.
> Ich habe mein LCD in PortA angeschlossen aber leider ich kann nur auf
> mein Hyperterminal "Test" senden und auf mein LCD nichts empfangen.

Und wo genau ist da jetzt in deinem Code der Aufruf von uart_gets()?

Kein Aufruf, kein Empfang. Ist doch nicht so schwer zu verstehen.

von Tobias (Gast)


Lesenswert?

Ja das stimmt aber auch wenn ich uart_gets() aufrufe zeigt, dass es 
wenig Argumete gibt.
danke

von Karl H. (kbuchegg)


Lesenswert?

Tobias schrieb:
> Ja das stimmt aber auch wenn ich uart_gets() aufrufe zeigt, dass es
> wenig Argumete gibt.


Dann musst du das im AUfruf eben korrigieren.

Das ist deine uart_gets()

void uart_gets( char* Buffer, uint8_t MaxLen )


das zeigt, dass uart_gets 2 Argumente haben will. Der erste ist das char 
Array, in dem uart_gets die empfangene Zeile ablegen soll, der zweite 
ist die Größe dieses Arrays.

Also muss der Aufruf lauten

     uart_gets( uart_string, uart_maxstrlen );

denn uart_gets soll die empfangene Zeile in uart_string ablegen und das 
Array uart_string ist uart_maxstrlen Zeichen gross.

Dann hast du die korrekte Anzahl an Parametern. (Dass es da jetzt eine 
Warnung wegen dem volatile geben wird, kannst du fürs erste ignorieren)


Tut mir leid. Aber um C lernen wirst du nicht rumkommen. Durch 
Zusammenkopieren von fremden Code hat noch keiner eine 
Programmiersprache (überhaupt die erste) gelernt.

von ingo (Gast)


Lesenswert?

Im HT die Flusskontrolle ausgeschaltet, oder CTS mit RTS gebrückt?
Sonst wartet HT umsonst auf die Empfangsbereitschaft seines Gegenüber.
mfG ingo

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.