Korrektes auslesen des USARTs

OP #3390106
Lesenswert?

Hallo zusammen,

habe ein Problem mit folgendem Quellcode:
1
#ifndef _UART_H_
2
#define _UART_H_
3

4
#include <avr/io.h>
5

6
extern void uart_init(void);
7

8

9

10
static inline int
11
uart_putc (const uint8_t c)
12
{
13
  // Warten, bis UDR bereit ist für einen neuen Wert
14
  while (!(UCSRA & (1 << UDRE)))
15
  ;
16

17
  // UDR Schreiben startet die Übertragung
18
  UDR = c;
19

20
  return 1;
21
}
22

23
static inline uint8_t
24
uart_getc_wait(void)
25
{
26
  // Warten, bis etwas empfangen wird
27
  while (!(UCSRA & (1 << RXC)))
28
  ;
29

30
  // Das empfangene Zeichen zurückliefern
31
  return UDR;
32
}
33

34
static inline int
35
uart_getc_nowait(void)
36
{
37
  // Liefer das empfangene Zeichen, falls etwas empfangen wurde; -1 sonst
38
  return (UCSRA & (1 << RXC)) ? (int) UDR : -1;
39
}
40

41
#endif /* _UART_H_  */
42

43
#include <avr/io.h>
44
#include <avr/interrupt.h>
45
#include <util/delay.h>
46

47

48

49
#define BAUDRATE 38400UL 
50

51
//int a;
52
volatile unsigned char a = 0x00;
53

54
void uart_init()
55
{
56
  uint16_t ubrr = (uint16_t) ((uint32_t) F_CPU/(16*BAUDRATE) - 1);
57
  
58
  UBRRH = (uint8_t) (ubrr>>8);
59
  UBRRL = (uint8_t) (ubrr);
60
  
61
  // UART Receiver und Transmitter anschalten
62
  // Data mode 8N1, asynchron
63
  UCSRA = (1 << RXC);
64
  UCSRB = (1 << RXEN) | (1<<RXCIE);
65
  UCSRC = (1 << URSEL) | (1 << UCSZ1) | (1 << UCSZ0);
66

67
  // Receive-Buffer leeren 
68
  do
69
  {
70
    UDR;
71
  }
72
  while (UCSRA & (1 << RXC));
73

74
  DDRD |= (1<<PD6);    // PortD als Ausgang deklarieren
75
  //PORTD = 0x00;   // Ports auf LOW schalten
76

77
}
78

79

80
// Einen 0-terminierten String übertragen.
81

82
void uart_puts (const char *s)
83
{
84
  do
85
  {
86
    uart_putc (*s);
87
  }
88
  while (*s++);
89
}
90

91

92

93
// Interupt wartet, bis Empfangsbit gesetzt wird und führt dann Routine aus
94

95
ISR(USART_RXC_vect) 
96
{
97
  a = UDR;
98
  //PORTD ^=(1<<PD6);
99
  if (a == 1) 
100
  {
101
    PORTD |= (1<<PD6);
102
  }
103
  else
104
  {
105
    PORTD &=~(1<<PD6);
106
  }
107

108
}
109

110

111

112

113

114
int main(void)
115
{
116
  
117
  uart_init();
118
  sei();
119
  
120
  
121

122

123
  while (1) {
124
    
125
    while (!(UCSRA & (1 << RXC)));
126

127
  }
128

129

130

131
  return 0;
132
}

Und zwar sende ich Zeichen mittels VB über die serielle Schnittstelle an 
meinen ATmega8.
In VB befinden sich zwei Buttons, der eine Sendet "1", der andere "0" 
(SerialPort1.Write ("1" & vbCr).
Leider bekomme ich es nicht auf die Reihen, dass PD6 auf High schaltet, 
wenn ich "1" sende und auf Low bei der "0".
Togglen des PD6 funktioniert, sprich die Interrupt Routine wird auch 
ausgeführt.
Mit BASIC läuft es ohne Probleme, nur mit C bekomm ich es einfach nicht 
auf die Reihe.

Für eure Hilfe bedanke ich mich schon mal im Voraus.
mfg
c63
#3390291
Lesenswert?

Problem Ungelöst schrieb:
> Baudrate ist identisch

Das heißt noch lange nicht, dass die Übertragungsrate korrekt ist. Denn 
die hängt auch von der Taktrate des AVR ab.

Daher wird auch generell gerne der Tipp gegeben.
Bevor du dich an die Übertragung vom PC zum AVR machst, mach erst mal 
die Gegenrichtung: vom AVR zum PC, wobei auf dem PC ein Terminalprogramm 
läuft.
Denn das hat den Vorteil, dass du im Terminalprogramm siehst, was 
eigentlich ankommt, wenn der AVR zb eine ASCII-1 wegschickt. Und das ist 
wiederrum besser, als die umgekehrte Richtung, in der du nur indirekt 
erschliessen kannst, was am AVR ankommt wenn der PC was wegschickt.

Dein erstes Testprogramm sollte also zb lauten ...
1
int main(void)
2
{
3
  uart_init();
4

5
  while (1) {
6
    uart_putc( 'x' );
7
  }
8
  return 0;
9
}
... und solange in deinem Terminalprogramm da nicht lauter 'x' 
auftauchen, brauchst du die Gegenrichtung erst gar nicht versuchen.

Erst dann, wenn das klappt, kannst du soweit sicher sein, dass zumindest 
die technische Komponente der UART Übertragung korrekt abläuft.
Wenn das dann klappt, dann ist dein nächster Milestone, dass du im AVR 
dir einen Empfangscode machst, und dem händisch vom Terminal aus 
"ansteuerst". Wenn dieses dann klappt, dann machst du das ganze von VB 
aus.

Grundprinzip ist es immer: habe so wenig unbekannte Teilsysteme im 
System wie möglich.
Du stehst im Moment mit einem VB Programm da, von dem du nicht weißt ob 
es korrekt ist; mit einem AVR Programm da, von dem du nicht weißt ob es 
korrekt ist; mit einer UART Übertragung, von der du nicht weißt ob sie 
korrekt ist.
Das sind zu viele 'ich weiß nicht, ob das korrekt ist'. Also heißt es 
Teilsysteme eliminieren und erst mal durch 'Von dem und dem Teilsystem 
weiß ich mit Sicherheit dass es korrekt ist' ersetzen.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren