mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik Zeichen fehlerhaft über RS232 an/von ATmega16


Autor: Tom (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Spezialisten,

ich hoffe auf Hilfe von Euch bei folgendem Problem:

Ich habe ein kleines Programm auf dem ATmega16 über welches die Tasten 
der Tastatur des angeschlossenen Rechners eingelesen werden und über 
"Echo" sofort wieder an das Windows Hyperterminal gesendet und angezeigt 
werden.

Nun habe ich das Problem, dass bei vielen Tasten nicht das aufgedruckte 
Zeichen gesendet/empfangen wird, sondern willkürliche. Jedoch 
reproduzierbar immer das gleiche. Weiter tritt der Fehler auf, dass ca. 
jeder zehnter Tastendruck nicht das gewünschte Zeichen liefert. Z. B.: 
aaaaaaaaajaaaaaaa.

Habe ich einen grundsätzlichen Denkfehler im System bzgl. ASCII-Code o. 
ä.?

Gruß


Tom

Autor: Björn Wieck (bwieck)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Tom wrote:
> Hallo Spezialisten,

> Nun habe ich das Problem, dass bei vielen Tasten nicht das aufgedruckte
> Zeichen gesendet/empfangen wird, sondern willkürliche. Jedoch
> reproduzierbar immer das gleiche. Weiter tritt der Fehler auf, dass ca.
> jeder zehnter Tastendruck nicht das gewünschte Zeichen liefert. Z. B.:
> aaaaaaaaajaaaaaaa.
>
> Habe ich einen grundsätzlichen Denkfehler im System bzgl. ASCII-Code o.

Welcher Takt?
Welche Baudrate?
Welche einstellungen in Hyperterm?
Welcher Code?

so viele Fragen...

Grüße
Björn

Autor: Tom (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Sorry hatte ich vergessen anzufügen:

Initialisierung von USART stimmt. Das hab ich natürlich 
(achthunderdsiebzigmal) überprüft.

>>Welcher Code?
Hier war nur meine Frage, ob ich evtl. den ASCII-Code o. ä. falsch 
interpretiert habe.

Danke

Autor: Johannes M. (johnny-m)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Tom wrote:
>>>Welcher Code?
> Hier war nur meine Frage, ob ich evtl. den ASCII-Code o. ä. falsch
> interpretiert habe.
Woher sollen wir das bitteschön wissen, ohne Deinen *PROGRAMM*-Code?

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

Bewertung
0 lesenswert
nicht lesenswert
Tom wrote:
>>>Welcher Code?
> Hier war nur meine Frage, ob ich evtl. den ASCII-Code o. ä. falsch
> interpretiert habe.

Kann keiner wissen, du zeigst ja keinen Code.

Aber: Wie ist das zu interpretieren:
dass bei vielen Tasten nicht das aufgedruckte
Zeichen gesendet/empfangen wird

Heist das du legst den Finger auf die Taste und lässt ihn dort.
D.h. die Zeichen werden in schneller Folge gesendet.
Oder drückst du jedesmal die Taste erneut?

Erhöhe mal die Anzahl der Stoppbits auf 2. Dadurch verschaffst
du der jeweiligen Gegenstelle etwas mehr Zeit ein Zeichen zu
verarbeiten.

Autor: Michael Wilhelm (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
externer Quarz oder interner RC-Oszillator?

MW

Autor: Björn Wieck (bwieck)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Tom wrote:
> Sorry hatte ich vergessen anzufügen:
>
> Initialisierung von USART stimmt. Das hab ich natürlich
> (achthunderdsiebzigmal) überprüft.
>
>>>Welcher Code?
> Hier war nur meine Frage, ob ich evtl. den ASCII-Code o. ä. falsch
> interpretiert habe.

Wenn Du genau das wieder zurückschickst was reinkommt dann gibt es da 
nichts zu interpretieren.

Ich tippe mal auf ungünstigen Takt in verbindung mit der Baudrate..

Grüße
Björn

Autor: Tom (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Vielen Dank für die tolle Resonanz.

Anbei der Code:

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 
+

#include <avr/io.h>          //Deklarationen
#include <avr/interrupt.h>      //für Interrupt


#define TAKT 4000000UL        //Controllertakt 4MHz
#define PRESET 40000UL        //Taktteiler für Vorteiler
#define BAUD 9600UL          //Baudrate

//Festlegung unabhängiger Typennamen:
typedef unsigned int uint16;
typedef signed int sint16;
typedef unsigned short uint8;
typedef signed short sint8;

//Prototypen von Funktionen
void initusart (void);
void putch (uint8);
uint8 getch (void);
uint8 getche (void);
uint8 kbhit (void);

//globale Variablen
uint8 got_cha;              //Zeichen vom Kontroll-Rechner (MatLab; 
LabView)

SIGNAL(SIG_UART_RECV)          //Servicefunktion für Empfängerinterrupt
{
  getche();
  PORTB = got_cha;
}


int main (void)
{
  DDRB=0xff;
  PORTB = 0;

  initusart();
  UCSRB |= (1<<RXCIE);
  sei();
  putch('>');

  while(1)
  {
  }

   return 0;

}




/* ********** Nachfolgend Funktionen für USART-Kommunikation ********** 
*/


//USART bzw. UART initialisieren
void initusart (void)
{
  uint8 x;              //lokale Hilfsvariable

  #ifdef UBRRL            //USART-Schnittstelle
  UBRRL = (TAKT / (16ul * BAUD)) - 1;  //Baudrate mit TAKT und BAUD
  UCSRB |= (1<<TXEN) | (1<<RXEN);    //Sender und Empränger ein
  UCSRC |= (1<<URSEL) | (1<<UCSZ1) | (1<<UCSZ0) | (1<<USBS) | (1<<UPM1); 
//async 8bit

  #else
  UBRR = (TAKT / (16ul * BAUD)) - 1;  //Baudrate
  UCR |= (1<<TXEN) | (1<<RXEN);    //Sender und Empfänger ein

  #endif
  x = UDR;              //Empfänger leeren
}



//warten und Zeichen senden
void putch (uint8 x)
{
  #ifdef UCSRA            //USART
  while (!(UCSRA & (1<<UDRE)));    //warte, solange Sender besetzt

  #else                //UART
  while (!(USR & (1<<UDRE)));      //warte, solange Sender besetzt

  #endif
  UDR = x;              //Zeichen nach Sender
}


//warten und Zeichen abholen
uint8 getch (void)
{
  #ifdef UCSRA            //USART
  while (!(UCSRA & (1<<RXC)));    //warte, bis Zeichen da

  #else                 //UART
  while (!(USR & (1<<RXC)));      //warte, bis Zeichen da

  #endif
  return UDR;              //Zeichen abholen
}


//warten und Zeichen abholen mit Echo
uint8 getche (void)
{
                  //Hilfsvariable

  #ifdef UCSRA            //USART
  while (!(UCSRA & (1<<RXC)));    //warte, bis Zeichen da
  got_cha = UDR;              //abholen und speichern
  while (!(UCSRA & (1<<UDRE)));    //warte, solange Sender besetzt

  #else                //UART
  while (!(UCSRA & (1<<RXC)));    //warte, bis Zeichen da
  got_cha = UDR;              //abholen und speichern
  while (!(UCSRA & (1<<UDRE)));    //warte, solange Sender besetzt

  #endif
  UDR = got_cha;              //Echo senden

  return got_cha;              //Zeichen zurückgeben
}


//Empfänger testen
uint8 kbhit (void)
{
  #ifdef UCSRA            //USART
  if (UCSRA & (1<<RXC)) return UDR; else return 0;

  #else                //UART
  if (USR & (1<<RXC)) return UDR; else return 0;

  #endif
}


++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 
+++


@Michael Wilhelm
interner RC (4MHz)

@Karl heinz Buchegger
bei beiden Versionen. D. h. egal, ob ich die Taste wieder loslasse, oder 
draufbleibe

Autor: Michael Wilhelm (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Der interne Oszillator ist sehr Temperatur- und 
Betriebsspannungsabhängig. Externer Baudratenquarz wird dein Problem 
lösen.

MW

Autor: Björn Wieck (bwieck)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Michael Wilhelm wrote:
> Der interne Oszillator ist sehr Temperatur- und
> Betriebsspannungsabhängig. Externer Baudratenquarz wird dein Problem
> lösen.
>
> MW

Mein reden...

mit Baudrate 4800 könnte es eventuell gerade so gehen...

Autor: Johannes M. (johnny-m)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wenn der RxC-Interrupt auftritt, dann wurde bereits ein Zeichen 
empfangen! Der Aufruf der Funktion getche in der ISR ist völliger Murks. 
Bitte schau Dir im AVR-GCC-Tutorial die entsprechenden Abschnitte 
an. Da steht wie's geht.

Autor: Tom (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Heist das, dass ich einen externen Quarz einbaue?

Welche einstellungen muss ich dann vornehmen?

Bitte entschuldigt die dumme Fragerei, ich bin noch ein wenig 
unerfahren, was Fuses usw. betrifft.

Übrigens: Ich verwende STK500 und AVRStudio 4.13

Autor: Johannes M. (johnny-m)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> typedef unsigned int uint16;
> typedef signed int sint16;
> typedef unsigned short uint8;
> typedef signed short sint8;
In der Headerdatei stdint.h sind bereits Typen mit Längenangabe 
definiert. Warum muss da jeder seinen eigenen Mist definieren?

Autor: Tom (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@Johannes M.

Das sollt natürlich keine Provokation darstellen. Dies wurde mir 
empfohlen, um das Programm für andere Compiler lesbar zu machen....

Autor: Johannes M. (johnny-m)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Björn Wieck wrote:
> Mein reden...
>
> mit Baudrate 4800 könnte es eventuell gerade so gehen...
Der Fehler ist relativ und tritt, wenn vorhanden, dann bei jeder 
Baudrate auf, die sich mit gleichem Grundfehler einstellen lässt. Und 
bei 4 MHz CPU-Takt ist es wurscht, ob man 9600 oder 4800 Baud nimmt, 
haben beide 0,2%...

Autor: Johannes M. (johnny-m)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Tom wrote:
> Das sollt natürlich keine Provokation darstellen. Dies wurde mir
> empfohlen, um das Programm für andere Compiler lesbar zu machen....
Hab ja auch nicht von einer Provokation geredet. Und die stdint.h ist 
Bestandteil von C und kann deshalb auch von jedem C-Compiler verarbeitet 
werden.

Autor: mik (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
ich find das so lustig, wie sehr da immer die rede von internem Osci und 
UART ist. Ich hab in meinen Computer (mal esikalt, mal sehr warm) eine 
LedMatrix eingebaut, die wird von einem Atmega16 (osci intern 8Mhz) 
gesteuert, welcher über FTDI-USB mit dem computer redet. Solange die 
Baudrate nicht höher als 14400 ist, gibt es mit 1 stopbit keine 
probleme. schon seit monaten.

lg mik

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

Bewertung
0 lesenswert
nicht lesenswert
Der springende Punkt ist:
Das sind deine Erfahrungen.
Andere haben andere Erfahrungen.
Hängt auch davon ab, welchen AVR du konkret benutzt. Unterschiedlich
AVR haben unterschiedliche RC-Oszillatoren implementiert, die
unterschiedliche Temperaturabhängigkeiten haben.

interner Oszi + UART kann funktionieren, muss aber nicht.

Autor: Andreas K. (a-k)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Vorausetzung für den internen Oszillator ist zunächst, dass man den 
Kalibrierungswert verwendet. Die AVRs haben dafür eine etwas 
eigenwillige Methode, denn der Oszillator ist von Haus aus unkalibriert 
und es muss ein auf dem Umweg über den Programmer aus einem speziellen 
dem Controller selbst nicht zugänglichen Bereich entnommener 
Kalibrierwert in OSCAL reingeschrieben werden. Ein Zirkus, der bei 
anderen µC-Familien mit leidlich genauem internem Oszillator nicht 
erforderlich ist.

Die Chancen auf leidlich verwendbare UART stehen dann bedeutend besser.

Aber trotzdem sollte man das dann allenfalls für Testzwecke so machen, 
beispielsweise bei einem Debug-Ausgang. Nicht für produktiv verwendet 
Schnittstellen.

Autor: Björn Wieck (bwieck)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Karl heinz Buchegger wrote:
>
> interner Oszi + UART kann funktionieren, muss aber nicht.

So wie bei mir. 2 MHz interner OSC:
9600 und drüber geht nicht, kommt nur Müll.
4800 und drunter geht.

Für ein paar Debuginformationen ist das noch zu verkraften aber eine
ernsthafte Kommunikation würde ich mit dem internen RC nicht machen 
wollen.

Grüße
Björn

Autor: Johannes M. (johnny-m)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Björn Wieck wrote:
> So wie bei mir. 2 MHz interner OSC:
> 9600 und drüber geht nicht, kommt nur Müll.
> 4800 und drunter geht.
Wundert mich, dass die 9600 auch schon nicht laufen, wenn 2400 und 4800 
gehen (sind schließlich alle mit 0,2% Grundabweichung machbar)... Dass 
die Raten über 9600 Bd allesamt mit 2 MHz nicht gehen, kann man 
allerdings dem Datenblatt entnehmen.

Autor: Björn Wieck (bwieck)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Johannes M. wrote:
> Wundert mich, dass die 9600 auch schon nicht laufen, wenn 2400 und 4800
> gehen (sind schließlich alle mit 0,2% Grundabweichung machbar)... Dass
> die Raten über 9600 Bd allesamt mit 2 MHz nicht gehen, kann man
> allerdings dem Datenblatt entnehmen.

Ist auch nur eine Erfahrung die ich mal gemacht habe.
Vielleicht ist ja auch der PC der daranhängt besonders gutmütig oder so.

Die Übertragung mit 4800 ist ja auch nicht immer fehlerfrei gewesen aber 
für Debug hats gelangt.

Die meisten meiner µC Anwendungen sind eh zeitunkritisch so das ich oft 
den internen RC nehme.

Aber wie ich schon sagte: RC Oszillator und UART ist Pfui wenns 
zuverlässig sein soll.

Grüße
Björn

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.