Forum: Mikrocontroller und Digitale Elektronik AVR/Atmega8 an STK500 - UART/USART


von Andrey B. (rrreey)


Lesenswert?

Hallo zusammen,

vielleicht kann mir jemand helfen. Ich habe ein STK500 und ein Atmega8 
da drauf. Eine UART Kommunikation habe ich zum PC hergestellt bzw. 
schicke ein Zeichen von dem Controller an den PC. Dazu verwende ich bei 
dem Atmega 1MHz und Baudrate von 4800. Allerdings wenn ich das am 
Computer lesen möchte, zeigt er mir nur Nullen an bzw. dass er nur 
Nullen bekommt,egal welches Zeichen ich sende. Am Oszilloskop sehe ich 
dagegen die unterschiedlichen Signale. Zum Empfangen bzw. Anzeigen  der 
Daten verwende ich das Programm HTerm. Woran könnte das liegen? Hat da 
jemand eine Idee?
Vielen Dank im voraus!

von Hubert G. (hubertg)


Lesenswert?

Falsche Initialisierung des µC wäre eine Möglichkeit.

von Harald M. (mare_crisium)


Lesenswert?

Andrey,

hast Du auf dem STK500 die Verbindung vom PortD (Pins PD0 und PD1) zum 
Anschluss "RS232 SPARE" (STK500-User Guide, Seite 3-5) hergestellt? 
Steckt Dein RS232-Kabel im Anschluss "RS232 Port for Communication" 
(STK500-User Guide, Seite 3-1)?

Ciao,

mare_crisium

von Karl H. (kbuchegg)


Lesenswert?

Ich muss nachhaken
> zeigt er mir nur Nullen an bzw. dass er nur Nullen bekommt
heißt das, das du in hTerm siehst, das etwas ankommt und dieses etwas 
sind lauter binäre 0-en (oder immer der Code für das ASCII Zeichen '0', 
was auch ungewöhnlich wäre)

Oder steht im hTerm der Cursor still und nichts rührt sich?
Das ist nicht dasselbe. Im einen Fall kommt tatsächlich ein Empfang zu 
Stande, im anderen Fall aber nicht. Letzterer Fall könnte zb dadurch 
verursacht werden, dass das verwendete Kabel falsch rum gekreuzt ist.

Ich würde als erstes mal die grundsätzliche physikalische Verbindung 
testen.
Dazu nimmst du den µC aus seinem Sockel und brückst mit einem Stück 
Draht den Tx-Pin mit dem Rx-Pin direkt im µC-Sockel. Wenn du dann am PC 
auf der Tastatur klimperst, muss alles was du tippst auch am Monitor 
erscheinen. Gegentest: die Brücke rausnehmen und das Echo muss aufhören.
Wenn du diesen Zustand hast, dann ist damit abgeklärt, dass die 
physikalische Verbindung, inklusive Kabel, inklusive aller Jumper auf 
dem STK grundsätzlich funktionsfähig ist.

von Andrey B. (rrreey)


Lesenswert?

Vielen Dank erstmal für die Antworten!

Harald M., ja die Anschlüsse sind richtig verbunden.

Karl Heinz Buchegger,in HTerm sehe ich das ein Signal ankommt und diesel 
Signal wird anscheinend als Null interpretiert, d.h. es kommen laute 
binäre Nullen.
Die physikalische Verbindung werde ich dann wohl wieder nachprüfen und 
sobald ich es getan habe,hier bescheid geben.

von Andrey B. (rrreey)


Lesenswert?

Moment,die Verbindung besteht ja. Ich bekomme das Signal am PC und kann 
es auch mit einem Oszilloskop abgreifen.

von Hubert G. (hubertg)


Lesenswert?

Doch ein Initialisierungsfehler?

von Andrey B. (rrreey)


Angehängte Dateien:

Lesenswert?

Hier habe ich meinen Quelltext für das Programm. Weiß nicht,ob ich alles 
richtig gemacht habe. Vielleicht sieht ja jemand von euch den Fehler.

von Hubert G. (hubertg)


Lesenswert?

Ich nehme mal an du hast die Initialisierung aus dem Datenblatt 
abgeschrieben. Hast du im HTerm aber auch zwei Stoppbits eingestellt?

von Andrey B. (rrreey)


Lesenswert?

Ja, ich habe es mit unterschiedlicher Konfiguration ausprobiert, es 
kommen trotzdem immer nur Nullen an.

von Karl H. (kbuchegg)


Lesenswert?

Quelltext als PNG?
(Das ist das dümmste was du tun kannst. Wie soll ich mich denn jetzt mit 
Cut&Paste auf deinen Quelltext beziehen und daraus Passagen zitieren. 
Abgesehen davon hast du eine Menge Arbeit damit, das PNG herzustellen.
Quelltext postest du ganz einfach als .... tata .... Quelltext. Was für 
eine Überraschung! Das ist für dich am wenigsten Arbeit und wir können 
uns problemlos auf Passagen beziehen)


     USART_transmit( 0x01 );


lass dir zuerst mal etwas senden, was ein sichtbares Zeichen ergibt. Das 
Bitmuster für 0x01 zu senden und dann mit der Ausgabe kombinieren, dass 
beim Empfänger IMMER nur ein 0-Byte ankommt, das war nicht sehr 
hilfreich. Denn die USART braucht nur in der Takfrequenz ein klein wenig 
daneben sein und schon kommt das einzige 1 Bit im Gesendeten nicht zur 
richtigen Zeit beim Empfänger an. Und von 'IMMER' kann auch keine Rede 
sein.

    USART_transmit( 'A' );

und dann schaun wir mal, was da rauskommt.
Wahrscheinlich das übliche. Deine Taktfrequenz ist ein wenig daneben. 
Die F_CPU Angabe stinkt nach internem RC-Generator. Die geht so genau 
wie die Messung der Seehöhe durch Messung des Wasserstands in der Donau.

von Stefan E. (sternst)


Lesenswert?

1
USART_Init(BAUD);
Nö.

von Stefan E. (sternst)


Lesenswert?

Karl Heinz Buchegger schrieb:
> Das
> Bitmuster für 0x01 zu senden und dann mit der Ausgabe kombinieren, dass
> beim Empfänger IMMER nur ein 0-Byte ankommt, das war nicht sehr
> hilfreich. Denn die USART braucht nur in der Takfrequenz ein klein wenig
> daneben sein und schon kommt das einzige 1 Bit im Gesendeten nicht zur
> richtigen Zeit beim Empfänger an.

Damit bei 0x01 am Empfänger eine 0 ankommt, muss der Takt schon gewaltig 
daneben liegen. Hinweis: es wird LSB-first gesendet. ;-)

von Andrey B. (rrreey)


Lesenswert?

also hier der Quelltext nochmal:
1
#include <avr/io.h> 
2
#include <util/delay.h>
3
4
5
#ifndef F_CPU
6
#define F_CPU 1000000UL   // Systemtakt in Hz - Definition als unsigned long beachten 
7
                         // Ohne ergeben sich unten Fehler in der Berechnung
8
#endif
9
10
11
#define BAUD 9600UL      // Baudrate
12
#include <util/setbaud.h>
13
#define UBRR_VAL ((F_CPU)/(BAUD*16)-1)   // clever runden
14
#define BAUD_REAL (F_CPU/(16*(UBRR_VAL+1)))     // Reale Baudrate
15
#define BAUD_ERROR ((BAUD_REAL)/(BAUD)-1)*100 // Fehler in Promille, 1000 = kein Fehler.
16
17
18
#if ((BAUD_ERROR<99) || (BAUD_ERROR>101)) 
19
#endif 
20
#include <util/delay.h>
21
#include <inttypes.h>
22
23
24
25
void USART_Init(void){
26
   UBRRH = UBRR_VAL >> 8;
27
   UBRRL = UBRR_VAL & 0xFF;
28
  
29
  UCSRB = (1<<RXEN)|(1<<TXEN);
30
  UCSRC = (1<<URSEL)|(1<<USBS)|(3<<UCSZ0);
31
}
32
33
void USART_Transmit(unsigned char data){
34
  while(!(UCSRA)&(1<<UDRE));
35
  UDR = data;
36
}
37
38
void USART_TransmitC(unsigned char *s)
39
{
40
    while (*s)
41
    {   // so lange *s != '\0' also ungleich dem "String-Endezeichen(Terminator)" 
42
        USART_Transmit(*s);
43
        s++;
44
    }
45
}
46
47
48
49
int main(){
50
  
51
   // Ausgabe von 0123456789
52
   char c;
53
 
54
   USART_Init();
55
   
56
 /*
57
   for (uint8_t i=0; i<=9; ++i) {
58
      c = i + "0";
59
      USART_TransmitC(c);
60
61
   }
62
 */
63
   while (1) {
64
    DDRC = 0xff;
65
      PORTC = 0x00;
66
    _delay_ms(500);
67
    PORTC = 0xff;
68
    _delay_ms(500);
69
    USART_Transmit(0xFF);
70
  
71
   }
72
 
73
   return 0; // never reached 
74
 
75
  
76
}

von Andrey B. (rrreey)


Lesenswert?

hab das jetzt soweit,dass ich für
1
 USART_Transmitt(0x01);
eine "129"(dezimal) bekomme. Dementsprechend für
1
 USART_Transmitt(0x00);
 "128"
Jetzt weiß ich nicht wo mein Fehler liegt.

von Stefan E. (sternst)


Lesenswert?

Andrey B. schrieb:
> hab das jetzt soweit,dass ich für
1
 USART_Transmitt(0x01);
> eine "129"(dezimal) bekomme. Dementsprechend für
1
USART_Transmitt(0x00);
> "128"
> Jetzt weiß ich nicht wo mein Fehler liegt.

Das bedeutet, dass das Stopp-Bit zu früh kommt. Das dürfte jetzt das 
schon von Karl Heinz angesprochene "interner RC-Oszillator"-Problem 
sein.

von Andrey B. (rrreey)


Lesenswert?

Was muss ich denn jetzt genau machen,um dieses Problem zu lösen?

von Karl H. (kbuchegg)


Lesenswert?

Andrey B. schrieb:
> Was muss ich denn jetzt genau machen,um dieses Problem zu lösen?

Den Mega nicht mit dem internen RC-Oszllator laufen lassen, sondern 
einen Quarz oder Quarzoszillator aktivieren.

von Stefan E. (sternst)


Lesenswert?

Moment: bei 1 MHZ und 9600 Baud und ohne U2X ist der Fehler schon 
prinzipiell viel zu groß. Benutze U2X oder 4800 Baud.


PS:
1
#if ((BAUD_ERROR<99) || (BAUD_ERROR>101)) 
2
#endif
War wohl keine so gute Idee, die Zeile dazwischen zu löschen. ;-)

von Andrey B. (rrreey)


Lesenswert?

Vielen Dank.so hier der Code, der jetzt auch funktioniert.Das war 
tatsächlch die Baudrate. Hab die jetzt auf 4800 gestellt.:
1
#include <avr/io.h> 
2
#include <util/delay.h>
3
4
5
#ifndef F_CPU
6
#define F_CPU 1000000UL   // Systemtakt in Hz - Definition als unsigned long beachten 
7
                         // Ohne ergeben sich unten Fehler in der Berechnung
8
#endif
9
10
11
#define BAUD 4800UL      // Baudrate
12
#include <util/setbaud.h>
13
#define UBRR_VAL ((F_CPU)/(BAUD*16)-1)   // clever runden
14
#define BAUD_REAL (F_CPU/(16*(UBRR_VAL+1)))     // Reale Baudrate
15
#define BAUD_ERROR ((BAUD_REAL)/(BAUD)-1)*100 
16
17
18
#if ((BAUD_ERROR<99) || (BAUD_ERROR>101)) 
19
#endif 
20
#include <util/delay.h>
21
#include <inttypes.h>
22
23
24
25
void USART_Init(void){
26
   UBRRH = UBRR_VAL >> 8;
27
   UBRRL = UBRR_VAL & 0xFF;
28
  
29
  UCSRB = (1<<RXEN)|(1<<TXEN);
30
  UCSRC = (1<<URSEL)|(0<<USBS)|(3<<UCSZ0);
31
}
32
33
void USART_Transmit(unsigned char data){
34
  while(!(UCSRA)&(1<<UDRE));
35
  UDR = data;
36
}
37
38
void USART_TransmitC(unsigned char *s)
39
{
40
    while (*s)
41
    {   // so lange *s != '\0' also ungleich dem "String-Endezeichen(Terminator)" 
42
        USART_Transmit(*s);
43
        s++;
44
    }
45
}
46
47
48
49
int main(){
50
  
51
   // Ausgabe von 0123456789
52
   char c;
53
 
54
   USART_Init();
55
   
56
 /*
57
   for (uint8_t i=0; i<=9; ++i) {
58
      c = i + "0";
59
      USART_TransmitC(c);
60
61
   }
62
 */
63
   while (1) {
64
    DDRC = 0xff;
65
      PORTC = 0x00;
66
    _delay_ms(500);
67
    PORTC = 0xff;
68
    _delay_ms(500);
69
    USART_Transmit(0x00);
70
  
71
   }
72
 
73
   return 0; // never reached 
74
 
75
  
76
}

von Karl H. (kbuchegg)


Lesenswert?

Andrey B. schrieb:

> #if ((BAUD_ERROR<99) || (BAUD_ERROR>101))
> #endif


Ist natürlich auch eine Möglichkeit eine Fehlermeldung zu löschen, die 
einem gesagt hätte, dass sich das mit den Zahlenwerten nicht vernünftig 
ausgeht.

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.