mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik Senden und Empfangen


Autor: uz (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Tag Zusammen

Ich hab folgendes Problem ich will mit einem Atmega 32 und dem Max232 
über einen seriale zu usb adapter Daten mit hilfe des AVR Terminal 
Senden und Empfangen. Der Atmega 32 wird extern mit 7372800 herz 
getaktet. Hier der Code.


#include <avr/io.h>
#include <string.h> // Für "strcmp"
#include <stdlib.h> // Für "itoa"
#ifndef F_CPU
#warning "F_CPU war noch nicht definiert, wird nun nachgeholt mit 7372800"
#define F_CPU 7372800UL  // Systemtakt in Hz - Definition als unsigned long beachten 
                         // Ohne ergeben sich unten Fehler in der Berechnung
#endif
 
#define BAUD 9600UL      // Baudrate
 
// Berechnungen
#define UBRR_VAL ((F_CPU+BAUD*8)/(BAUD*16)-1)   // clever runden
#define BAUD_REAL (F_CPU/(16*(UBRR_VAL+1)))     // Reale Baudrate
#define BAUD_ERROR ((BAUD_REAL*1000)/BAUD) // Fehler in Promille, 1000 = kein Fehler.
 
#if ((BAUD_ERROR<990) || (BAUD_ERROR>1010))
  #error Systematischer Fehler der Baudrate grösser 1% und damit zu hoch! 
#endif

/* UART-Init  */
 

void uart_init(void)
{
  UCSRB |= (1<<TXEN);  // UART TX einschalten
  UCSRC |= (1<<URSEL)|(1<<UCSZ1)|(1<<UCSZ0);  // Asynchron 8N1 
 
  UBRRH = UBRR_VAL >> 8;
  UBRRL = UBRR_VAL & 0xFF;
}

void uart_putchar(char c)
{
  // Warten bis Buffer bereit ...
  while (!(UCSRA & (1 << UDRE)))
    ;

  // Senden...
  UDR = c;
}

void uart_putstring(char *str)
{
  unsigned char i;

  for (i=0;i<255;i++) /* Maximal 255 Zeichen ausgeben ... */
  {
    if (str[i] != 0)
      uart_putchar(str[i]);
    else
      break; // Ende des Strings erreicht
  }
}

char uart_getchar()
{
  // Ist schon ein Zeichen im Buffer?
  if (bit_is_set(UCSRA, RXC))
    return UDR;
  else 
    return -1;
}

void uart_readline(char *str)
{
  char c;
  unsigned char index;
  
  index = 0;

  while (1)
  {
    c = uart_getchar();
    if (c != -1)
    {
      if (c == 13) /* ASCII: NewLine */
      {
        /* Ende der Zeile erreicht,
           also String abschließen */
        str[index] = 0;

        /* Funktion beenden */
        return;
      }
      else /* Normales Zeichen, anhängen an die Zeichenkette */
      {
        str[index] = c;
        index++;
      }
    }
  }
}

int main(void)
{
  char kommando[255];
  char temp[10];
  unsigned char zahl=0;

  /* RS232 einschalten ... */
  uart_init();

  /* Willkommensnachricht senden ... */
  uart_putstring("Serielle Kommunikation gestartet ...\r\n\r\n");

  while (1)
  {
    /* Auf komplettes Kommando warten ... */
    uart_readline(kommando);

    /* Welcher Befehl wurde geschickt? ============ */

    /* ==== BEFEHL: "version" */
    if (strcmp(kommando, "version")==0)
    {
      uart_putstring("OK: Version 1.00\r\n");
    }

    /* ==== BEFEHL: "up" */
    else if (strcmp(kommando, "up")==0)
    {
      if (zahl<255)
      {
        zahl++;
        uart_putstring("OK: Zahl wurde erhoeht\r\n");
      }
      else
        uart_putstring("ERROR: Maximum erreicht (Zahl=255)\r\n");
    }

    /* ==== BEFEHL: "down" */
    else if (strcmp(kommando, "down")==0)
    {
      if (zahl>0)
      {
        zahl--;
        uart_putstring("OK: Zahl wurde verringert\r\n");
      }
      else
        uart_putstring("ERROR: Minimum erreicht (Zahl=0)\r\n");
    }

    /* ==== BEFEHL: "show" */
    else if (strcmp(kommando, "show")==0)
    {
      itoa(zahl, temp, 10);
      uart_putstring("OK: Zahl = ");
      uart_putstring(temp);
      uart_putstring("\r\n");
    }
  }

  return 0;
}


Ich bekomme die Rückmeldung "Serielle Kommunikation gestartet ..." am 
AVR Terminal .Also funst RX. Das TX Singnal Kommt am Microcontroller an 
siehe Oszi Bild

Gelb Eingang R1IN
Grün Nach Max232 R2OUT
Magenta am uC an bin 14

(Befehl version)

Nur der  pin 15 am TXD vom uC bleibt still.
An was könnte das liegen ich denk mal das ist ne Software Geschichte 
verzweiflung

Autor: ... ... (docean) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
if (c == 13) /* ASCII: NewLine */

Sendet dein Programm auf dem PC wirklich eine 13? oder kommt vlt was 
anderes an?

Autor: Lord Ziu (lordziu)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Tx sendet vom Controller.
Rx empfängt.

Zeig mal deinen Schaltplan und vielleicht das Oszi-Bild.

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

Bewertung
0 lesenswert
nicht lesenswert
uz schrieb:

> Ich bekomme die Rückmeldung "Serielle Kommunikation gestartet ..."

also geht, aus µC Sicht, schon mal das Senden

> AVR Terminal .Also funst RX. Das TX Singnal Kommt am Microcontroller an
> siehe Oszi Bild

Also am Pin 14

> Nur der  pin 15 am TXD vom uC bleibt still.

Auf dem Pin sendet der µC


Ich denke du hast da einen Haufen Mischmasch was Rx und Tx angeht.

Wir sprechen bei Rx und Tx immer aus Sicht des µC.

Rx, Pin 14.     Auf dem Pin gehts in den µC rein
Tx, Pin 15.     Auf dem Pin gehts aus dem µC raus


Und dein erstes Testprogramm sollte deutlich einfach sein.
int main(void)
{
  char c;

  /* RS232 einschalten ... */
  uart_init();

  /* Willkommensnachricht senden ... */
  uart_putstring("Serielle Kommunikation gestartet ...\r\n\r\n");

  while (1)
  {
    c = uart_getchar();
    if( c != -1 )
      uart_putchar( c );
  }
}

mehr nicht.
Alles was du am Terminal klimperst, wird vom µC sofort einfach nur 
zurückgeschickt. Auch den Gegentest machen: Kabel abziehen. Wenn du 
jetzt Tasten drückst, darf nichts mehr zurückgeschickt werden.

Ehe das nicht funktioniert hat es keinen Sinn, da noch 20 
fehleranfällige Softwareschichten drüberzustülpen

Autor: Stefan B. (stefan) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>   UCSRB |= (1<<TXEN);  // UART TX einschalten

Wo ist RXEN?

Autor: uz (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Morgen
Das mit Rx und Tx hab ich wohl einwenig durcheinander gebracht.
Rxen hab ich wohl vergessen zu aktivieren was ich nach geholt hab. Das 
kleine Programm von  Karl heinz Buchegger läuft auch soweit. Jetzt ist 
noch die Frage warum läuft meins noch nicht richtig Senden und Empfangen 
läuft ja soweit aber warum funktionieren die Befehle nicht ? Wie kann 
ich nachschauen ob meine PC 16 sendet?

Danke für die Hile ich hätte nicht gedacht das mir so schnell und gut 
geholfen wird!

p.s Ich hab kein Schaltplan zur Hand aber der Aufbau stimmt ja soweit

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

Bewertung
0 lesenswert
nicht lesenswert
uz schrieb:

> Rxen hab ich wohl vergessen zu aktivieren was ich nach geholt hab. Das
> kleine Programm von  Karl heinz Buchegger läuft auch soweit.

Das heisst du kannst prinzipiell senden und empfangen?

> Jetzt ist
> noch die Frage warum läuft meins noch nicht richtig Senden und Empfangen
> läuft ja soweit aber warum funktionieren die Befehle nicht ?

Jetzt schlägt für dich die Stunde. Das nennt sich debugging und du wirst 
noch viele Stunden/Tage damit zubringen. Debuggen ist das Finden von 
logischen Fehlern, Dingen die man vergessen hat etc.

Aber: Du hast ja jetzt eine UART, über die du dir Ausgaben auf ein 
Terminal machen lassen kannst. Wenn du wissen willst, ob dein Programm 
an einer gewissen Stelle vorbeikommt, dann lass dein Programm einfach 
eine Ausgabe machen, dann zeigt dir das Programm mit seiner Ausgabe an, 
wo es ist und was es tut. Wenn du wissen willst, welchen Wert bestimmte 
Variablen an eine bestimmten Stelle haben, dann bau dir dort eine 
entsprechende AUsgabe rein und dein Programm schreibt dir am Terminal 
das hin was du wissen willst.

Auf Deutsch: Du kannst deine Programme jetzt mit Ausgaben spicken, die 
dir alles erzählen, was du wissen musst um Fehler zu finden. Du musst es 
nur tun.

Zum Beispiel würde ich mir an deiner Stelle in die uart_getchar 
Funktion, gleich nachdem diese Funktion ein Zeichen erhalten hat, eine 
Ausgabe rein machen, die das Zeichen auf das Terminal zurückschickt. zb 
als ASCII Code und auch in Hexadezimal damit auch Sonderzeichen wie 
Carriage Return sichtbar gemacht werden können. Du kannst auch noch 
ander Ausgaben rein geben, die dir erzählen was gerade passiert
void uart_readline(char *str)
{
  char c;
  unsigned char index;
  
  index = 0;

  while (1)
  {
    c = uart_getchar();

    if (c != -1)
    {

      uart_putstring( "Empfangen : +" );
      uart_putchar( c );
      uart_putstring( "+ " );

      if (c == 13) /* ASCII: NewLine */
      {
        uart_putstring( "-> Zeilenende" );

        /* Ende der Zeile erreicht,
           also String abschließen */
        str[index] = 0;

        /* Funktion beenden */
        return;
      }
      else /* Normales Zeichen, anhängen an die Zeichenkette */
      {

        uart_putstring( "-> Zeichen an Zeile anhaengen" );

        str[index] = c;
        index++;
      }

      uart_putstring( "\r\n" );
    }
  }
}

Du kannst dir ausgeben lassen was du willst. Es sollte nur nicht 
allzulang sein und du musst natürlich mit der Ausgabe auch etwas 
anfangen können. Diese Ausgabe ist dein Fenster in das laufende 
Programm. Durch Analysieren dieser Ausgabe und logischem Folgern musst 
du damit die Fehler und Probleme finden können.

Autor: STK500-Besitzer (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
void uart_readline(char *str)
{
  char c;
  unsigned char index;
  
  index = 0;

  while (1)
  {
    c = uart_getchar();
    if (c != -1)
    { 
      uart_putchar(c);
      if (c == 13) /* ASCII: NewLine */
      {
        /* Ende der Zeile erreicht,
           also String abschließen */
        str[index] = 0;

        /* Funktion beenden */
        return;
      }
      else /* Normales Zeichen, anhängen an die Zeichenkette */
      {
        str[index] = c;
        index++;
      }
    }
  }
}

Als Modifikation, um zu sehen, was am µC so alles ankommt, schickst du 
einfach die empfangenen Zeichen wieder zurück an den Absender.
Du solltest dann noch ein Terminalprogramm wie HTerm benutzen, das 
verschiedene Zeichen-Darstellungsformen kennt.
Es kann auch sein, dass der PC nur ein Linefeed (ASCII(10)) oder ein 
Linefeed und ein CarriageReturn sendet.
Man kann im Terminal-Programm meist angeben, welche Zeichen(-folge) am 
Zeilenende übertragen wird.
Übrigens ist es sinnvoll, alle Zeichen <32 des ASCII auszublenden, da es 
sich dabei immer umm Steuerzeichen handelt.

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.