Forum: Mikrocontroller und Digitale Elektronik UART Empfangen/Senden mit Atmega1284


von A. R. (and)


Lesenswert?

Guten Tag,

ich bin noch relativ neu in der µC Programmierung.
Nach mehreren Tagen Google und vielen Beispielen habe ich immer noch 
nichts Brauchbares gefunden, bzw. auch noch nicht alles verstanden: 
Warum, Wieso, Weshalb.....
Habe bereits ein Beispiel versucht nach zu programmieren, jedoch nur mit 
einer Menge Fehlern. "AVR-GCC-Tutorial/Der UART"


Ich möchte gerne folgendes Umsetzten:
Regelmäßig den UART abfragen ob Werte ankommen (z.B. Zeichenkette vom 
Typ char „OK“).
Wenn ein entsprechender Wert angekommen ist, möchte ich mehrere 
Variablen des Typ „uint16_t“ per UART Senden.

Beim Senden ist mein bisheriges Programm definnitiv ganz falsch.


Meine Hardware:
Atmega 1284P;   Quarz mit 14,7456MHZ;   UART: TXD an PD1 / RXD an PD0


Antworten bitte Anfängerfreundlich.


Mein aktuelleer Quelltext:
1
#define F_CPU 14745600UL     // CPU Taktfrequenz
2
#include <util/delay.h>       //
3
#include <avr/io.h>               //
4
5
6
#define BAUD 9600UL      // Baudrate
7
8
//Berechnung der Baudrate
9
#define UBRR_VAL ((F_CPU+BAUD*8)/(BAUD*16)-1)   // clever runden
10
#define BAUD_REAL (F_CPU/(16*(UBRR_VAL+1)))     // Reale Baudrate
11
#define BAUD_ERROR ((BAUD_REAL*1000)/BAUD)    // Fehler in Promille, 1000 = kein Fehler.
12
13
14
UCSRB |= (1<<TXEN);
15
UCSRB |= (1<<RXEN); 
16
17
18
19
// ------------------------------------------------------------
20
// UART initalisieren
21
22
  void uart_init(void) {
23
      UBRRH = UBRR_VAL >> 8;
24
      UBRRL = UBRR_VAL & 0xFF;
25
 
26
      UCSRB |= (1<<TXEN);  // UART TX einschalten
27
     UCSRC = (1<<URSEL)|(1<<UCSZ1)|(1<<UCSZ0);  // Asynchron 8N1 
28
  }
29
30
31
// ------------------------------------------------------------
32
// UART Empfangen
33
34
  uint8_t uart_getc(void) {
35
    while (!(UCSRA & (1<<RXC)));   // warten bis Zeichen verfuegbar
36
        
37
    return UDR;                   // Zeichen aus UDR an Aufrufer zurueckgeben
38
  }
39
 
40
41
  void uart_gets( char* Buffer, uint8_t MaxLen ) {
42
      uint8_t NextChar;
43
      uint8_t StringLen = 0;
44
 
45
      NextChar = uart_getc();         // Warte auf und empfange das nächste Zeichen
46
 
47
                                    // Sammle solange Zeichen, bis:
48
                                    // * entweder das String Ende Zeichen kam
49
                                    // * oder das aufnehmende Array voll ist
50
    while( NextChar != '\n' && StringLen < MaxLen - 1 ) {
51
      *Buffer++ = NextChar;
52
      StringLen++;
53
      NextChar = uart_getc();
54
    }  
55
 
56
                                    // Noch ein '\0' anhängen um einen Standard
57
                                    // C-String daraus zu machen
58
    *Buffer = '\0';
59
  }
60
61
62
// ------------------------------------------------------------
63
// UART Senden
64
65
  int uart_putc(unsigned char c) {
66
      while (!(UCSRA & (1<<UDRE)))  /* warten bis Senden moeglich */
67
      {
68
      }                             
69
 
70
    UDR = c;                      /* sende Zeichen */
71
    return 0;
72
  }
73
 
74
 
75
/* puts ist unabhaengig vom Controllertyp */
76
  void uart_puts (char *s) {
77
      while (*s) {         /* so lange *s != '\0' also ungleich dem "String-Endezeichen(Terminator)" */
78
        uart_putc(*s);
79
        s++;
80
      }
81
  }
82
83
84
85
// ------------------------------------------------------------
86
// ------------------------------------------------------------
87
88
int main (void) {        
89
 
90
    DDRC  = 0xFF;                 // Digitale Ausgänge
91
   
92
  uint16_t x1, x2, x3, x4;     // Variable
93
  
94
     
95
   while(1) 
96
   {      
97
   
98
99
//-----------UART Werte senden-----------// !!!ÜBERTRAGEN von x1-x4!!!
100
  
101
  char s[7];    
102
     int16_t i = -12345;
103
 
104
     uart_init();
105
 
106
     itoa( i, s, 10 ); // 10 fuer radix -> Dezimalsystem
107
     uart_puts( s );
108
 
109
     // da itoa einen Zeiger auf den Beginn von s zurueckgibt verkuerzt auch:
110
     uart_puts( itoa( i, s, 10 ) );
111
112
//-------------------------------------//
113
114
   }                         
115
 
116
117
   return 0;                
118
}

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

Andi R. schrieb:
> Beim Senden ist mein bisheriges Programm definnitiv ganz falsch.
Dann würde ich da mal anfangen.
Wie stellst du fest, dass dein Programm falsch ist?
Was passiert, wenn du mal
uart_puts("Hallo!");
schreibst?
Stimmt deine Taktfrequenz (die CKDIV8 Fuse)?

von A. R. (and)


Lesenswert?

Ich wollte jetzt erst mal veruschen das Tutorial nach zu programmieren 
und dann zu ändern wenn das Falsch wäre.

Wenn ich einen anderen Wert als OK bekomme, soll erstmal nicht 
passieren.
Die Struktur werde ich dann mit eienr IF Bedinung auswerten und dann 
darin die entsprechenden Werte senden.

Die Fuses habe ich laut www.engbedded.com/fusecalc eingestellt:
Low: 0x7F   / High:0x99   / Extended: 0xFF

von Karl H. (kbuchegg)


Lesenswert?

Andi R. schrieb:

> Antworten bitte Anfängerfreundlich.

ok.
anfängerfreundlich.

Kauf dir ein C Buch und arbeite das zunächst mal in den ersten Kapiteln 
durch.

Dort erfährst du dann zum Beispiel, dass in C ausführbare Anweisungen 
immer innerhalb von Funktionen stecken. Das heisst, dass hier


> UCSRB |= (1<<TXEN);
> UCSRB |= (1<<RXEN);

ist so nicht möglich, weil diese Anweisungen nicht in einer Funktion 
stecken.

Ganz abgesehen davon, dass sie hier auch keinen irgendwie gearteten Sinn 
ergeben, denn die Aktivierung der UART findet sowieso in der Funktion 
uart_init statt.
1
void uart_init(void) {
2
      UBRRH = UBRR_VAL >> 8;
3
      UBRRL = UBRR_VAL & 0xFF;
4
 
5
6
// ***** hier steckt die Aktivierung des Transmitters
7
      UCSRB |= (1<<TXEN);  // UART TX einschalten
8
// *****
9
     UCSRC = (1<<URSEL)|(1<<UCSZ1)|(1<<UCSZ0);  // Asynchron 8N1 
10
  }

Wie gesagt: kauf dir ein C-Buch.
Es hat keinen Sinn zu glauben, man könne seine erste Programmiersprache 
dadurch lernen, dass man sich im Web Dinge zusammenkopiert. Das geht mit 
Sicherheit schief, da programmieren mehr ist, als nur einfach irgendwas 
hinzuschreiben und der Compiler wird sich dann schon seinen Reim darauf 
machen.

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.