Forum: Mikrocontroller und Digitale Elektronik UART gibt zu viele Zeichen aus


von Dominik (Gast)


Lesenswert?

Hallo,
Ich bin gerade dabei ein kleines Programm zu schreiben welches einfach 
nur das über UART empfangene Byte wieder zurückschickt. Das ist mein 
erstes C Projekt, hab davor aber schon in ASM programmiert und versteh 
eig alles. Das Problem ist jetzt, wenn ich eine "1" sende, bekomm ich 
eine "1" zurück, hintendran aber noch 5-10 andere Zeichen, die immer 
anders sind und keinen Sinn ergeben. Z.B. sende ich "1" und bekomme 
"1MÞÞß" zurück.. was läuft da falsch?
1
#include <avr/io.h>
2
#include <avr/interrupt.h>
3
#include <stdint.h>
4
#include <string.h>
5
6
#define F_CPU 16000000L
7
#define BAUD 9600L
8
#define UBRR_VAL ((F_CPU/(BAUD*16))-1)
9
10
void UART_init()
11
{
12
   UBRRH = UBRR_VAL >> 8;
13
    UBRRL = UBRR_VAL & 0xFF;
14
    UCSRB = (1<<TXEN)|(1<<RXEN)|(1<<RXCIE);
15
   UCSRC = (1<<URSEL)|(1<<UCSZ1)|(1<<UCSZ0);
16
}
17
   
18
int main (void) {
19
      
20
    DDRC = 0xFF;
21
   
22
   UART_init();   
23
24
    sei();
25
26
   bytecount=1;
27
28
29
   while(1)
30
   ;
31
}
32
33
SIGNAL(SIG_UART_RECV)
34
{
35
    unsigned char buffer;
36
37
    buffer = UDR;
38
39
    while ( !( UCSRA & (1<<UDRE)) )
40
        ;
41
    UDR = buffer;
42
}

von Falk B. (falk)


Lesenswert?

@ Dominik (Gast)

>nur das über UART empfangene Byte wieder zurückschickt. Das ist mein

Mach es so, ohne diverse Änderungen

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

MfG
Falk

von Dominik (Gast)


Lesenswert?

Hallo,
mein Ziel ist nicht dass das programm später mal ein Byte empfängt und 
wieder zurückschickt.. Ich hab das nur als Test geplant und wie ich sehe 
funtkioniert das nicht. Ich hab den Code schon fast 1:1 aus dem Inet 
übernommen, mit dem selben ergebnis. Hat jemand ne Idee?

von Daniel Goßmann (Gast)


Lesenswert?

Evtl.
1
#define F_CPU 16000000L
 als UL deklarieren?

Gruß
Daniel

von Otto (Gast)


Lesenswert?

Wie sieht denn die Hardware aus - evtl. fängt da etwas an zu schwingen

Gruss Otto

von Dominik (Gast)


Lesenswert?

Soo.. ich war mal wieder etwas dumm.. passiert mir irgwie öfters.. Ich 
hatte vergessen die 5V vom Max232 anzuschließen. Jetzt kommt genau das 
zum PC zurück was kommen soll.. Nächstes Problem ist aber schon da. Ich 
hab eine variable, die bis 80 zählen muss, aber komischerweiße bricht 
sie bei 75 ab und fängt bei 0 oder irgendeiner anderen Zahl an. Ich find 
den Fehler aber irgendwie nicht. Kann mir einer von euch helfen?
1
#include <avr/io.h>
2
#include <avr/interrupt.h>
3
#include <stdint.h>
4
5
//#define F_CPU 16000000
6
#define BAUD 19200L
7
#define UBRR_VAL ((F_CPU/(BAUD*16))-1)
8
9
uint8_t spalten[16][5];
10
uint8_t bytecount;
11
12
void schieb ()
13
{  
14
  PORTC|=(1<<PC2);
15
  PORTC&=~(1<<PC2);
16
  return;
17
}
18
void setdata ()
19
{
20
  PORTC|=(1<<PC1);
21
  PORTC&=~(1<<PC1);
22
  return;
23
}
24
void clrreg()
25
{
26
  PORTC = 0x00;
27
28
  
29
  uint8_t i;
30
  for (i=1; i <= 56; ++i)
31
  {
32
    schieb();
33
  }
34
  setdata();
35
  return;
36
}
37
void UART_init()
38
{
39
  UBRRH = UBRR_VAL >> 8;
40
    UBRRL = UBRR_VAL & 0xFF;
41
    UCSRB = (1<<TXEN)|(1<<RXEN)|(1<<RXCIE);
42
  UCSRC = (1<<URSEL)|(1<<UCSZ1)|(1<<UCSZ0);
43
}
44
void UART_send(unsigned char c)
45
{
46
  while ( !( UCSRA & (1<<UDRE)) )
47
        ;
48
  UDR = c;
49
  return;
50
}  
51
int main (void) {
52
      
53
    DDRC = 0xFF;
54
  
55
  UART_init();
56
  clrreg();   
57
58
    sei();
59
60
  bytecount=1;
61
62
63
  while(1)
64
  ;
65
}
66
67
ISR(USART_RXC_vect)
68
{
69
    uint8_t data;
70
71
    data = UDR;
72
73
  if(bytecount<=5)
74
  {
75
    spalten[1][bytecount] = data;
76
  }
77
  else if((bytecount>5) && (bytecount<=10))
78
  {
79
    spalten[2][bytecount-5] = data;
80
  }
81
  else if((bytecount>10) && (bytecount<=15))
82
  {
83
    spalten[3][bytecount-10] = data;
84
  }
85
  else if((bytecount>15) && (bytecount<=20))
86
  {
87
    spalten[4][bytecount-15] = data;
88
  }
89
  else if((bytecount>20) && (bytecount<=25))
90
  {
91
    spalten[5][bytecount-20] = data;
92
  }
93
  else if((bytecount>25) && (bytecount<=30))
94
  {
95
    spalten[6][bytecount-25] = data;
96
  }
97
  else if((bytecount>30) && (bytecount<=35))
98
  {
99
    spalten[7][bytecount-30] = data;
100
  }
101
  else if((bytecount>35) && (bytecount<=40))
102
  {
103
    spalten[8][bytecount-35] = data;
104
  }
105
  else if((bytecount>40) && (bytecount<=45))
106
  {
107
    spalten[9][bytecount-40] = data;
108
  }
109
  else if((bytecount>45) && (bytecount<=50))
110
  {
111
    spalten[10][bytecount-45] = data;
112
  }
113
  else if((bytecount>50) && (bytecount<=55))
114
  {
115
    spalten[11][bytecount-50] = data;
116
  }
117
  else if((bytecount>55) && (bytecount<=60))
118
  {
119
    spalten[12][bytecount-55] = data;
120
  }
121
  else if((bytecount>60) && (bytecount<=65))
122
  {
123
    spalten[13][bytecount-60] = data;
124
  }
125
  else if((bytecount>65) && (bytecount<=70))
126
  {
127
    spalten[14][bytecount-65] = data;
128
  }
129
  else if((bytecount>70) && (bytecount<=75))
130
  {
131
    spalten[15][bytecount-70] = data;
132
  }
133
  else if((bytecount>75) && (bytecount<=80))
134
  {
135
    spalten[16][bytecount-75] = data;
136
  }
137
  
138
  if (bytecount>=80)
139
  {                          
140
    bytecount = 0;
141
    UART_send('F');
142
  }
143
  UART_send(bytecount);
144
  bytecount++;
145
  return;
146
}

von Dominik (Gast)


Lesenswert?

Soo.. hab auch den Fehler gefunden.. eher gesagt mein Vater.. Problem 
war ein Speicherüberlauf.. Spalte ist als Array [16][5] definiert und da 
das ja bei 0 anfängt bin ich eins zu weit und der hat dafür mein 
bytecount gekillt.. Jetzt funktioniert das.. Danke an alle!

von David M. (md2k7)


Lesenswert?

das, was du in der ISR machst, lässt sich wesentlich eleganter lösen. 
Ein Beispiel:
1
ISR(USART_RXC_vect)
2
{
3
  uint8_t data = UDR;
4
5
  spalten[bytecount / 5][bytecount % 5] = data;
6
  
7
  if (bytecount >= 79)
8
  {                          
9
    bytecount = 0;
10
    UART_send('F');
11
  }
12
  UART_send(bytecount);
13
  bytecount++;
14
  return;
15
}

ACHTUNG: Dein bytecount beginnt ebenfalls bei 0! Wenn du bis 80 zählen 
willst, muss die Bedingung im if so sein, wie ich das da oben 
geschrieben habe.

Und noch was:
1
if(bytecount<=5)
2
  {
3
    spalten[1][bytecount] = data;
4
  }

Hierbei kann auch versucht werden, auf spalten[1][5] zuzugreifen, was zu 
einem Speicherzugriffsfehler führen wird, den du nicht einmal merkst - 
erst, wenn das Programm sporadisch komische Sachen macht.


EDIT: bytecount sollte bei 0 beginnen mein ich :o)

von 6632 (Gast)


Lesenswert?

Eine Division in einer ISR ? Hilfe......

von David M. (md2k7)


Lesenswert?

@ 6632: Wenn der OP meint, er muss in der ISR mit einer Endlosschleife
warten, bis der UART das Zeichen gesendet hat, macht eine Division da
nicht mehr viel Unterschied.

Außerdem braucht die Division nur so um die 80 Zyklen.

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.