Forum: Mikrocontroller und Digitale Elektronik UART Datenaustausch Verständnisfragen


von Dido (Gast)


Lesenswert?

Hallo liebe Gemeinde,

ich bin relative neu was die Programmierung vom Mikrocontrollern angeht 
und brauche daher noch immer wieder Denkanstöße, um auf die Lösung zu 
kommen.
Momentan möchte ich Daten an den Controller schicken, welcher diese dann 
an den PC zurückgibt bzw. auf dem PORTA auslegt.
Das Programm verstehe ich soweit, dass Strings gesammelt und in einem 
Puffer gesammelt werden, bis eine max. Anzahl von Strings erreicht bzw. 
das Terminatorzeichen eingegeben wird.
Was mir aber noch unklar ist:
1. Welche Variable beinhaltet die konkreten, über die Tastatur 
eingegebenen Werte? Ich vermute es ist nextChar?!

2. Wie kann ich mir diesen UDR-Puffer vorstellen? Werden dort sämtliche 
Zeichen gesammelt oder nur einzelne Strings gespeichert?
Ist es in 2 Register unterteilt (also TX und Receive)? Wenn ja, wie 
unterscheidet man beim Zugriff die beiden Register?

3. Wie modifiziere ich das Programm, dass es die gwünschten Funktionen 
erfüllt? Ich habe ja ein schlechtes Gewissen, dass ich keinen richtigen 
Code anbieten kann, aber ich tappe ziemlich im Dunkeln und die 
bisherigen Versuche waren auch nur Müll...

Ich bedanke mich schonmal im Voraus!
1
#include <avr/io.h>
2
#include <avr/interrupt.h>
3
#define F_CPU 8000000UL
4
#define BAUD 9600UL
5
6
// Berechnungen
7
#define UBRR_VAL ((F_CPU+BAUD*8)/(BAUD*16)-1)   // clever runden
8
#define BAUD_REAL (F_CPU/(16*(UBRR_VAL+1)))     // Reale Baudrate
9
#define BAUD_ERROR ((BAUD_REAL*1000)/BAUD) // Fehler in Promille, 1000 = kein Fehler.
10
11
#if ((BAUD_ERROR<990) || (BAUD_ERROR>1010))
12
#error Systematischer Fehler der Baudrate grösser 1% und damit zu hoch!
13
#endif
14
15
16
#define UART_MAXSTRLEN 8
17
18
volatile uint8_t uart_str_complete = 0;     // 1 .. String komplett empfangen
19
volatile uint8_t uart_str_count = 0;
20
volatile char uart_stringlength[UART_MAXSTRLEN + 1] = "";
21
unsigned char nextChar;
22
23
void Init (void)
24
{
25
  UCSR0B|= (1<<TXEN0) |(1<<RXEN0) | (1<<RXCIE0) | (TXCIE0) | (UDRIE0); //Enable Transmitter/Receiver and concerning Interrputs
26
  UCSR0B|= (1<<UCSZ00) | (UCSZ01);
27
}
28
29
int uart_putc(unsigned char c)
30
{
31
  while (!(UCSR0A & (1<<UDRE0))) 
32
  {
33
  }
34
  
35
  UDR0 = c;                    
36
  return 0;
37
}
38
39
40
void uart_puts (char *s)
41
{
42
  while (*s != '\0')
43
  {  
44
    uart_putc(*s);
45
    s++;
46
  }
47
}
48
49
int main(void)
50
{   DDRC= 0xFF;
51
  Init();
52
  
53
  sei();
54
  
55
    while(1)
56
    {
57
        
58
    }
59
}
60
61
ISR(USART0_RX_vect)
62
 {
63
  
64
  // Daten aus dem Puffer lesen
65
  nextChar = UDR0;
66
67
  if( uart_str_complete == 0 ) // wenn uart_string gerade in Verwendung, neues Zeichen verwerfen
68
  {  
69
    
70
    // Daten werden erst in uart_string geschrieben, wenn nicht String-Ende/max Zeichenlänge erreicht ist/string gerade verarbeitet wird
71
    if( nextChar != '\n' && nextChar != '\r' && uart_str_count < UART_MAXSTRLEN )
72
    {
73
      uart_stringlength[uart_str_count] = nextChar;
74
      uart_str_count++;
75
    }
76
    else
77
    {
78
      uart_stringlength[uart_str_count] = '\0';
79
      uart_str_count = 0;
80
      uart_str_complete = 1;
81
      uart_putc(nextChar);
82
      
83
        
84
    }
85
86
  }
87
  }

P.S. Das Senden von Daten an den PC klappte bereits gut mit meinem 
ATmega8.

von spess53 (Gast)


Lesenswert?

Hi

>UCSR0B|= (1<<TXEN0) |(1<<RXEN0) | (1<<RXCIE0) | (TXCIE0) | (UDRIE0)
                                                 ^^^^^^^^   ^^^^^^^^

Das solltest du dringend ändern. Allerdings fehlen die zugehörigen ISRs.

MfG Spess

von Dido (Gast)


Lesenswert?

spess53 schrieb :
> Hi
>
>>UCSR0B|= (1<<TXEN0) |(1<<RXEN0) | (1<<RXCIE0) | (TXCIE0) | (UDRIE0)
>                                                  ^^^^^^^^   ^^^^^^^^
>
> Das solltest du dringend ändern. Allerdings fehlen die zugehörigen ISRs.
>
Upss Flüchtigkeitsfehler. Jap die ISRs fehlen, hab ich aber erstmal 
aktiviert, für den Fall das ich sie doch brauche :)

von Karl H. (kbuchegg)


Lesenswert?

Dido schrieb:

> Das Programm verstehe ich soweit, dass Strings gesammelt

genauer gesagt: 1 String (in Worten: einer)

> und in einem
> Puffer gesammelt werden, bis eine max. Anzahl von Strings erreicht bzw.
> das Terminatorzeichen eingegeben wird.
> Was mir aber noch unklar ist:


Was dir unklar ist, das ist der Unterschied zwischen einem einzelnen 
Zeichen und einem String. Ein String ist kein Zeichen. Ein String 
besteht aus mehreren Zeichen.

Ein Zeichen, das ist zb 'A' oder 'B' oder 'Z' oder auch '0' oder '/'. 
Drückst du im Terminal auf eine Taste, dann schickt das Terminal ein 
einzelnes Zeichen auf die Reise.

Erst die Zusammensetzung mehrerer Zeichen nennt man dann einen String.
"Hello World" ist ein String. Oder auch "01234" ist ein String. Oder 
"08/15" ist ein String. Bestehend aus mehreren Zeichen.

> 1. Welche Variable beinhaltet die konkreten, über die Tastatur
> eingegebenen Werte? Ich vermute es ist nextChar?!

Nein.
Es ist ein Stufenprozess.
Jedes Zeichwn wird einzeln übertragen. Zunächst landet das Zeichen in 
nextChar. Von dort wird es dann an den String in uart_stringlength 
angehängt. (Wer hat sich denn den Variablennamen ausgedacht? Ich wars 
nicht, auch wenn ich den Code als meinen wiedererkenne)

> 2. Wie kann ich mir diesen UDR-Puffer vorstellen? Werden dort sämtliche
> Zeichen gesammelt oder nur einzelne Strings gespeichert?

Dort wird 1 Zeichen gespeichert. Nämlich das nächste Zeichen, welches 
über die UART reinkommt.

> Ist es in 2 Register unterteilt (also TX und Receive)? Wenn ja, wie
> unterscheidet man beim Zugriff die beiden Register?

Ganz einfach: das eine wird gelesen, das andere wird geschrieben.

> 3. Wie modifiziere ich das Programm, dass es die gwünschten Funktionen
> erfüllt? Ich habe ja ein schlechtes Gewissen

Das solltest du auch haben. Aber weniger deswegen, sondern weil du kein 
C Buch hast, in dem du die Grundlagen der STringverarbeitung gelesen, 
geübt und gelernt hättest.

von Karl H. (kbuchegg)


Lesenswert?

Dido schrieb:
> spess53 schrieb :
>> Hi
>>
>>>UCSR0B|= (1<<TXEN0) |(1<<RXEN0) | (1<<RXCIE0) | (TXCIE0) | (UDRIE0)
>>                                                  ^^^^^^^^   ^^^^^^^^
>>
>> Das solltest du dringend ändern. Allerdings fehlen die zugehörigen ISRs.
>>
> Upss Flüchtigkeitsfehler. Jap die ISRs fehlen, hab ich aber erstmal
> aktiviert, für den Fall das ich sie doch brauche :)

Schlechte Idee.

Gibst du einen Interrupt frei, für den es keine ISR gibt, und tritt die 
Interruptsituation auf, dann wird das mit einem Prozessorreset bestraft.

Ausserdem. Sieh erst mal zu, dass du so klar kommst. Interrupts kommen 
später. Irgendwann. Vielleicht nächstes Jahr. Bis dahin hast du noch 
tausende andere Themen, die wichtiger sind. Wie zb: Wie funktionieren 
eigentlich Strings in C?

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.