www.mikrocontroller.net

Forum: Compiler & IDEs Zeichenempfang mit USART (HyperTerminal)


Autor: Jimmy (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

unsigned char USART_receive( void )
{
/* Wait for data to be received */
while ( !(UCSRA & (1<<RXC)) )
;
/* Get and return received data from buffer */
return UDR;
}

void USART_transmit( unsigned char data )
{
/* Wait for empty transmit buffer */
while ( !( UCSRA & (1<<UDRE)) )
;
/* Put data into buffer, sends the data */
UDR = data;
}

int main (void)
{
  UCSRB |= (1 << RXEN) | (1 << TXEN);   // Turn on the transmission and reception circuitry
  UCSRC |= (1 << URSEL) | (3 << UCSZ0); // Use 8N1

  UBRRL = BAUD_PRESCALE; // Load lower 8-bits of the baud rate value into the low byte of the UBRR register
  UBRRH = (BAUD_PRESCALE >> 8); // Load upper 8-bits of the baud rate value into the high byte of the UBRR register

  UCSRB |= (1 << RXCIE); // Enable the USART Recieve Complete interrupt (USART_RXC)
  
  sei(); // Enable the Global Interrupt Enable flag so that interrupts can be processed


        char ReceivedByte;

  for (;;) // Loop forever
  {
    USART_transmit('_'); //klappt
    ReceivedByte=USART_receive(); //klappt nicht :(
  }   
}

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

Autor: Falk Brunner (falk)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Stefan B. (stefan) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
   // ...
   UCSRB |= (1 << RXCIE); // Enable the USART Recieve Complete interrupt (USART_RXC)
   sei();
   // ...

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?

Autor: Jimmy (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Tobias (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht 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-Tu...

Und wenns nicht geht:
http://www.mikrocontroller.net/articles/AVR_Checkl...

Autor: Tobias (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Zusammen,
ich habe schon das geschafft aber leider kann ich nicht empfangen auf 
meinem LCD.
kann Jemand vielleicht mir helfen.
#include <avr/io.h>
#include <inttypes.h>
#include <avr/interrupt.h>
#include <util/delay.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";
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';
}
int main (void)
{
    //DDRD = 0xFF;
    //PORTD = 0xFF;
uart_init();
//sei();
while(1)
{
uart_puts(uart_string);
uart_puts("\n");
_delay_ms(5);
 }
}

Danke

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht 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
int main (void)
{
    //DDRD = 0xFF;
    //PORTD = 0xFF;
  uart_init();
  //sei();

  while(1)
  {
    uart_puts(uart_string);
    uart_puts("\n");
    _delay_ms(5);
  }
}

Ein kurzer Blick in die uart_init Funktion zeigt mir
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;
}

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
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';
}

mit dem hier
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';
}

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?

Autor: Tobias (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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();

     }
 }

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Tobias (Gast)
Datum:

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

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: ingo (Gast)
Datum:

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

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.