Arduino / Atmel UART Fehler

OP #4195828
Lesenswert?

Hallo,

ich hab nach diesem Tutorial versucht, über UART etwas zu senden:

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

jetzt sagt mir Atmel-Studio aber:
1
Error  1  'UCSRA' was not declared in this scope
2
Error  2  'UDRE' was not declared in this scope
3
Error  3  'UDR' was not declared in this scope

1
#define F_CPU 16000000L //16 MHz
2

3
#define BAUD 9600UL
4
#define UBRR_VAL ((F_CPU+BAUD*8)/(BAUD*16)-1)
5

6
#include <avr/io.h>
7
#include <stdlib.h>
8
#include <util/setbaud.h>
9

10
int uart_putc(unsigned char c)
11
{
12
  while (!(UCSRA & (1<<UDRE)))  /* warten bis Senden moeglich */
13
  {
14
  }
15
  UDR = c;                      /* sende Zeichen */
16
  return 0;
17
}
18

19
void uart_puts (char *s)
20
{
21
  while (*s)
22
  {   /* so lange *s != '\0' also ungleich dem "String-Endezeichen(Terminator)" */
23
    uart_putc(*s);
24
    s++;
25
  }
26
}
27

28
void uart_init(void)
29
{
30
  UBRR0 = UBRR_VAL;
31
  UCSR0B |= (1<<TXEN0);
32
  // Frame Format: Asynchron 8N1
33
  UCSR0C = (1<<UCSZ01)|(1<<UCSZ00);
34
}
35

36
int main(void)
37
{
38
  char s[7];
39
  int16_t i = -12345;
40
  
41
  uart_init();
42
  
43
  itoa( i, s, 10 );
44
  uart_puts( s );
45
  
46
  uart_puts( itoa( i, s, 10 ) );
47
  
48
  while (1) {
49
  }
50
  return 0;
51
}
OP #4195841
Lesenswert?

spess53 schrieb:
> Was sagt das Datenblatt?

Danke, ich habs!
1
#define F_CPU 16000000L //16 MHz
2

3
#define BAUD 9600UL
4
#define UBRR_VAL ((F_CPU+BAUD*8)/(BAUD*16)-1)
5

6
#include <avr/io.h>
7
#include <stdlib.h>
8
#include <util/setbaud.h>
9

10
int uart_putc(unsigned char c)
11
{
12
  while (!(UCSR0A & (1<<UDRE0)))  /* warten bis Senden moeglich */
13
  {
14
  }
15
  UDR0 = c;                      /* sende Zeichen */
16
  return 0;
17
}
18

19
void uart_puts (char *s)
20
{
21
  while (*s)
22
  {
23
    uart_putc(*s);
24
    s++;
25
  }
26
}
27

28
void uart_init(void)
29
{
30
  UBRR0 = UBRR_VAL;
31
  UCSR0B |= (1<<TXEN0);
32
  UCSR0C = (1<<UCSZ01)|(1<<UCSZ00);
33
}
34

35
int main(void)
36
{
37
  char s[7];
38
  int16_t i = 1337;
39
  
40
  uart_init();
41
  
42
  itoa( i, s, 10 );
43
  uart_puts( s );
44
  
45
  uart_puts( itoa( i, s, 10 ) );
46
  
47
  while (1) {
48
  }
49
  return 0;
50
}
#4195849
Lesenswert?

Max M. schrieb:
> Ich verwende einen Arduino mit ATMega328P

dann schau halt nach:
http://www.atmel.com/images/doc8161.pdf

und mache dir deine eigenen #defines
1
#ifndef _PINS_H_
2
#define _PINS_H_
3

4

5
#if defined(__AVR_ATmega328P__)
6
  #define   TIMSKx              TIMSK1
7
  #define   OCIExA              OCIE1A
8
  #define   TIMERx_COMPA_vect   TIMER1_COMPA_vect  // ATmega
9
  #define   TCCRxA              TCCR1A
10
  #define   COMxA0              COM1A0
11
  #define   OCRxA               OCR1A
12
  #define   TCCRxB              TCCR1B
13
  #define   WGMx2               WGM12
14
  #define   CSx0                CS10
15

16

17
// D13(SCK)       PB5 (LED)
18
  #define LED_ARDUINO      5                          // D13 LED Arduino
19
  #define LED_ARDUINO_DDR  DDRB
20
  #define LED_ARDUINO_PORT PORTB
21
  #define LED_ARDUINO_ON   LED_ARDUINO_PORT|=(1<<LED_ARDUINO)
22
  #define LED_ARDUINO_OFF  LED_ARDUINO_PORT&=~(1<<LED_ARDUINO)
23

24
#elif defined(__AVR_ATmega1284P__) // -------------------------------------- m1284p -------------------------------------------------------
25
  #define   TIMSKx              TIMSK3
26
  #define   OCIExA              OCIE3A
27
  #define   TIMERx_COMPA_vect   TIMER3_COMPA_vect  // ATmega
28
  #define   TCCRxA              TCCR3A
29
  #define   COMxA0              COM3A0
30
  #define   OCRxA               OCR3A
31
  #define   TCCRxB              TCCR3B
32
  #define   WGMx2               WGM32
33
  #define   CSx0                CS30
34

35
//#elif defined(__AVR_ATmega1284P__)
36
  #define LED_ARDUINO       7                          // D7 LED Arduino
37
  #define LED_ARDUINO_PORT  PORTB
38
  #define LED_ARDUINO_DDR   DDRB
39
  #define LED_ARDUINO_ON       LED_ARDUINO_PORT  |= (1<<LED_ARDUINO)
40
  #define LED_ARDUINO_OFF      LED_ARDUINO_PORT &= ~(1<<LED_ARDUINO)
41

42
#else
43
 #error "board_wahl_falsch.h"
44
#endif // defined(__AVR_ATmega1284P__)
45

46
#endif // #ifndef _PINS_H_
Gast #4195922
Lesenswert?

spess53 schrieb:
> Was sagt das Datenblatt?

Was hat das Datenblatt damit zu tun? Die Bezeichnungen für die Register 
werden einzig und alleine in den devicespezifischen Headerfiles des 
Compilers festgelegt. Wenn die - mehr oder weniger zufällig - mit den 
Bezeichnungen im Datenblatt übereinstimmen, ist das glückliche Fügung 
und dient einzig der Arbeitserleichterung ;-)
Gast #4195928
Lesenswert?

Thomas W. schrieb:
> Was hat das Datenblatt damit zu tun? Die Bezeichnungen für die Register
> werden einzig und alleine in den devicespezifischen Headerfiles des
> Compilers festgelegt. Wenn die - mehr oder weniger zufällig - mit den
> Bezeichnungen im Datenblatt übereinstimmen, ist das glückliche Fügung
> und dient einzig der Arbeitserleichterung ;-)

Und der Ersteller der Library wäre ein Idiot.
OP #4201845
Lesenswert?

Ein weiteres Problem. Ich versuche über UART auszulesen und dann das 
empfangene Ergebnis wieder zu schreiben aber es passiert nichts:
1
#define F_CPU 16000000L //16MHz
2
#define BAUD 9600UL
3
#define UBRR_VAL ((F_CPU+BAUD*8) / (BAUD*16) - 1)
4
#define sbi(var,mask) ((var) |=(uint8_t)(1<<mask))
5
#define cbi(var,mask) ((var)&=(uint8_t)~(1<<mask))
6

7
#include <avr/io.h>
8
#include <util/setbaud.h>
9
#include <util/delay.h>
10
#include <stdlib.h>
11
#include <string.h>
12

13
uint8_t uart_getc(void){
14
  while(!(UCSR0A & (1<<RXC0))){
15
  }
16
  return UDR0;
17
}
18

19
void uart_puts (char *s){
20
  while(*s){ //stop sign of string is '\0'
21
    if(UCSR0A & (1<<UDRE0))
22
    UDR0 = *s++; //increment RAM adress
23
  }
24
}
25

26
void uart_init (void){
27
  UBRR0 = UBRR_VAL;
28
  UCSR0B |= (1<<TXEN0);
29
  UCSR0C = (1<<UCSZ01) | (1<<UCSZ00);
30
}
31

32
int main(void){
33
  uart_init();
34
  while(1){
35
    uint8_t val = uart_getc();
36
    char str[16];
37
    itoa(val,str,10);
38
    uart_puts(str);
39
    _delay_ms(100);
40
  }
41
}

Kann mir da jemand auf die Sprünge helfen?
OP #4202388
Lesenswert?

Hm, funktioniert irgendwie trotzdem nicht:
1
#define F_CPU 16000000L //16MHz
2
#define BAUD 9600UL
3
#define UBRR_VAL ((F_CPU+BAUD*8) / (BAUD*16) - 1)
4

5
#include <avr/io.h>
6
#include <util/setbaud.h>
7
#include <util/delay.h>
8
#include <stdlib.h>
9
#include <string.h>
10

11
uint8_t uart_getc(void){
12
  while(!(UCSR0A & (1<<RXC0))){
13
  }
14
  return UDR0;
15
}
16

17
void uart_puts (char *s){
18
  while(*s){ //stop sign of string is '\0'
19
    if(UCSR0A & (1<<UDRE0))
20
    UDR0 = *s++; //increment RAM adress
21
  }
22
}
23

24
void uart_init (void){
25
  UBRR0 = UBRR_VAL >> 8;
26
  UBRR0L = UBRR_VAL & 0xFF;
27

28
  UCSR0B |= (1<<RXEN0);
29
  UCSR0A |= (1<<TXEN0);
30
  UCSR0C = (1<<UCSZ01) | (1<<UCSZ00);
31
}
32

33
int main(void){
34
  uart_init();
35
  while(1){
36
    if(UCSR0A & (1<<RXC0)){
37
      uint8_t val = uart_getc();
38
      char str[16];
39
      itoa(val,str,10);
40
      uart_puts(str);
41
      _delay_ms(100);
42
    }
43
  }
44
}

Die Daten werden von einem C#-Programm an COM5 gesendet, an dem der µC 
hängt:
1
            SerialPort sp = new SerialPort("COM5");
2
            sp.Open();
3
            while (true)
4
            {
5
                sp.Write(new byte[] { 1 }, 0, 1);
6
                Console.WriteLine(sp.ReadLine());
7
            }
Gast #4202411
Lesenswert?

..PALMFACE..



Also hier funktioniert's nicht..
1
void uart_init (void){
2
  UBRR0 = UBRR_VAL >> 8;
3
  UBRR0L = UBRR_VAL & 0xFF;
4

5
  UCSR0B |= (1<<RXEN0);
6
  UCSR0A |= (1<<TXEN0);
7
  UCSR0C = (1<<UCSZ01) | (1<<UCSZ00);
8
}

..und hier hast's gehabt (das Senden)..
1
void uart_init(void)
2
{
3
  UBRR0 = UBRR_VAL;
4
  UCSR0B |= (1<<TXEN0);
5
  UCSR0C = (1<<UCSZ01)|(1<<UCSZ00);
6
}

Nun, wenn Du mit dem Tutorial hier nicht zurechtkommst, nimm halt die 
Beispiele aus dem ATmega48A..328P Datenblatt.
Gast #4202459
Lesenswert?

BirgerT schrieb:

> .. nimm halt die Beispiele aus dem ATmega48A..328P Datenblatt.

http://www.atmel.com/images/atmel-8271-8-bit-avr-microcontroller-atmega48a-48pa-88a-88pa-168a-168pa-328-328p_datasheet_complete.pdf

Runterladen, lesen, Beispiele (richtig) abtippen..
- Baudratenteilerregister richtig beschreiben
- Sender und(!) Empfänger einschalten
- UCSR0C Zuweisung haste richtig für 8bit und no Parity
OP #4202470
Lesenswert?

BirgerT schrieb:
> Baudratenteilerregister richtig beschreiben
1
#define UBRR_VAL F_CPU/16/BAUD-1

BirgerT schrieb:
> - Sender und(!) Empfänger einschalten
> - UCSR0C Zuweisung haste richtig für 8bit und no Parity
1
void uart_init(void)
2
{
3
  UBRR0H = (unsigned char)(UBRR_VAL>>8);
4
  UBRR0L = (unsigned char)UBRR_VAL;
5
  UCSR0A = (1<<TXEN0);
6
  UCSR0A = (1<<RXEN0);
7
  UCSR0C = (1<<USBS0)|(3<<UCSZ00);
8
}
Gast #4202519
Lesenswert?

Max M. schrieb:
> BirgerT schrieb:
>> Baudratenteilerregister richtig beschreiben
> #define UBRR_VAL F_CPU/16/BAUD-1
> BirgerT schrieb:
>> - Sender und(!) Empfänger einschalten
>> - UCSR0C Zuweisung haste richtig für 8bit und no Parity
 void uart_init(void)
 {
   UBRR0H = (unsigned char)(UBRR_VAL>>8);  // oK
   UBRR0L = (unsigned char)UBRR_VAL;       // oK
   UCSR0A = (1<<TXEN0);   // falsches Register
   UCSR0A = (1<<RXEN0);   // 2x falsch: Register, Sender wieder aus
          // 2 Stopbits   8 Bit/Zeichen
   UCSR0C = (1<<USBS0)  |(3<<UCSZ00);        // oK
 }

Und wie ist die Serielle am PC eingestellt?
9600 Baud, 8 Bit, no Parity, 2 Stopbits (9600,8n2)?!
OP #4202523
Lesenswert?

BirgerT schrieb:
> 9600 Baud, 8 Bit, no Parity, 2 Stopbits (9600,8n2)?!

Ja, ist so eingestellt

weder so:
1
void uart_init(void)
2
{
3
  UBRR0H = (unsigned char)(UBRR_VAL>>8);
4
  UBRR0L = (unsigned char)UBRR_VAL;
5
  UCSR0B = (1<<TXEN0);
6
  UCSR0B = (1<<RXEN0);
7
  UCSR0C = (1<<USBS0)|(3<<UCSZ00);
8
}

noch so:
1
void uart_init(void)
2
{
3
  UBRR0H = (unsigned char)(UBRR_VAL>>8);
4
  UBRR0L = (unsigned char)UBRR_VAL;
5
  UCSR0B = (1<<TXEN0);
6
  UCSR0A = (1<<RXEN0);
7
  UCSR0C = (1<<USBS0)|(3<<UCSZ00);
8
}

funktionierts :(
#4202549
Lesenswert?

STK500-Besitzer schrieb:
> Und der Ersteller der Library wäre ein Idiot.

ähm, so würde ich das nicht sagen, weil sich die Namen öfter mal 
geändert haben ist es oft nicht möglich irgendeine Lib zu nehmen die 
genau nicht für alle AVR passt.

Ich habe in meinem Beispiel zwar 2 -Punkte gesammelt ändert aber nix.

Ich benutze heute lieber Pseudo Defines in "StandardLIBs" und setze die 
echten Namen aus dem Datenblatt ein, zumal es ja wie schon geschieben 
heute UART0 und UART1 gibt, die Interrupt- Bits -register auch gerne mal 
wechseln.
Gast #4202583
Lesenswert?

Geduldsfaden Ende erreicht..

..mach's halt richtig, so wie's im Datenblatt (für Schreibfaule) steht:

void USART_Init( unsigned int ubrr)
{
/*Set baud rate */
UBRR0H = (unsigned char)(ubrr>>8);
UBRR0L = (unsigned char)ubrr;

Enable receiver and transmitter */
// *****************************************************
UCSR0B = (1<<RXEN0)|(1<<TXEN0); // <<-- DING DING DING *
// *****************************************************

/* Set frame format: 8data, 2stop bit */
UCSR0C = (1<<USBS0)|(3<<UCSZ00);
}

aber so nicht
  UCSR0B = (1<<TXEN0); // Im Controlregister wir nur Bit TXEN0 gesetzt
  UCSR0B = (1<<RXEN0); // Im Controlregister wir nur Bit RXEN0 gesetzt,
                       // TXEN0 und alle anderen Bits werden auf 0 
gesetzt

  UCSR0B |= (1<<RXEN0); // so werden einzelne Bits gesetzt, ohne die 
anderen wieder auf 0 zu löschen..

Jetzt aber..
OP #4202607
Lesenswert?

BirgerT schrieb:
> Jetzt aber..

Ne, leider nicht:
1
#define F_CPU 16000000L //16 MHz
2

3
#define BAUD 9600UL
4
#define UBRR_VAL ((F_CPU+BAUD*8)/(BAUD*16)-1)
5

6
#include <avr/io.h>
7
#include <stdlib.h>
8
#include <util/setbaud.h>
9
#include <util/delay.h>
10

11
void uart_putc(unsigned char c)
12
{
13
  while (!(UCSR0A & (1<<UDRE0)))  /* warten bis Senden moeglich */
14
  {
15
  }
16
  UDR0 = c;                      /* sende Zeichen */
17
}
18

19
void uart_puts (char *s)
20
{
21
  while (*s)
22
  {
23
    uart_putc(*s);
24
    s++;
25
  }
26
}
27

28
uint8_t uart_getc(void){
29
  while(!(UCSR0A & (1<<RXC0))){
30
  }
31
  return UDR0;
32
}
33

34
void uart_init()
35
{
36
  UBRR0H = (unsigned char)(UBRR_VAL>>8);
37
  UBRR0L = (unsigned char)UBRR_VAL;
38
  UCSR0B = (1<<RXEN0)|(1<<TXEN0);
39
  UCSR0C = (1<<USBS0)|(3<<UCSZ00);
40
}
41

42
int main(void){
43
  uart_init();
44
  while(1){
45
    uint8_t val = uart_getc();
46
    char str[16];
47
    itoa(val,str,10);
48
    uart_puts(str);
49
    _delay_ms(100);
50
  }
51
}
Gast #4202654
Lesenswert?

Kai M. schrieb:
> BirgerT schrieb:

> Nur mal als kurzer Hinweis: Wenn Du weder LUST noch GEDULD aufbringst,
> etwas zu erklären, dann LASS ES EINFACH.

Mach ich auch..

Meine Philosophie ist "Hilfe zur Selbsthilfe" und "Beratungsresistenz 
ignorieren".

Bei der Problematik hier handelt es sich um eine der vielen gut 
dokumentierten Aufgabenstellungen. Also habe ich erst versucht, den OT 
selber eine Lösung finden und das Erfolgserlebnis haben zu lassen..

..um dann doch die Katze aus dem Sack zu lassen.

Also Max_MMM probier bitte nochmal folgendes:
1
void uart_putc(unsigned char c)
2
{
3
  while (!(UCSR0A & (1<<UDRE0)))  /* warten bis Senden moeglich */
4
  { ; // hier noch ein Semikolon einfügen
5
  }
6
  UDR0 = c;                      /* sende Zeichen */
7
}
8

9
uint8_t uart_getc(void){
10
  while(!(UCSR0A & (1<<RXC0))){
11
    ; // und hier auch eine "leere Anweisung" 
12
  }
13
  return UDR0;
14
}

Wenn das auch noch nicht geht, probier nochmal das Senden:
1
char str[] = "Hallo Max_MMM\n-";
2

3
int main(void){
4
  uart_init();
5

6
  _delay_ms(100);
7
  uart_puts(str);
8

9
  while(1){
10
    uint8_t val = uart_getc();
11
   itoa(val,str,10);
12
    uart_puts(str);
13
    _delay_ms(100);
14
  }
15
}

und wenn's dann noch immer nicht klappt - bin ich zugegebenermaßen 
erstmal ratlos. Liegt es vielleicht an dem C# Programm?
Versuch doch mal ein normales Terminalprogramm (puTTYtel, Hterm..)
OP #4202662
Lesenswert?

Yeah, es geht :)
1
#define F_CPU 16000000L //16 MHz
2

3
#define BAUD 9600UL
4
#define UBRR_VAL ((F_CPU+BAUD*8)/(BAUD*16)-1)
5

6
#include <avr/io.h>
7
#include <stdlib.h>
8
#include <util/setbaud.h>
9
#include <util/delay.h>
10

11
uint8_t uart_getc(){
12
  while(!(UCSR0A & (1<<RXC0))){
13
    ;
14
  }
15
  return UDR0;
16
}
17

18
void uart_puts (char *s)
19
{
20
  while (*s)
21
    if(UCSR0A & (1<<UDRE0))
22
      UDR0 = *s++;
23
}
24

25
void uart_init(void)
26
{
27
  UBRR0 = UBRR_VAL;
28
  UCSR0B |= (1<<TXEN0);
29
  UCSR0C = (1<<UCSZ01)|(1<<UCSZ00);
30
}
31

32
int main(void){
33
  uart_init();
34
  while(1){
35
    uint8_t val = uart_getc();
36
    char str[2];
37
    itoa(val,str,10);
38
    uart_puts(str);
39
    _delay_ms(100);
40
  }
41
}

Danke!

P.S. Warum 49 als Ergebnis ausgegeben wird obwohl ich "1" sende, 
verstehe ich aber nicht...

Edit: okay, anscheinend braucht man C#-Programm ein Ende-Zeichen, so 
gehts:
1
int main(void){
2
  uart_init();
3
  while(1){
4
    uint8_t val = uart_getc();
5
    char str[3];
6
    itoa(val,str,10);
7
    strcat(str,"\n");
8
    uart_puts(str);
9
    _delay_ms(100);
10
  }
11
}
Gast #4202666
Lesenswert?

BirgerT schrieb:

> und wenn's dann noch immer nicht klappt - bin ich zugegebenermaßen
> erstmal ratlos. Liegt es vielleicht an dem C# Programm?

Augenscheinlich liegt es am C# Programm..
                Console.WriteLine(sp.ReadLine());
..heisst bestimmt, dass der empfangene String ebenfalls mit einem 
"return" abgeschlossen sein muss.

> Versuch doch mal ein normales Terminalprogramm (puTTYtel, Hterm..)
1
char str[] = "Hallo Max_MMM\r\n";
2

3
int main(void){
4
  uart_init();
5

6
  _delay_ms(100);
7
  uart_puts(str);
8

9
  while(1){
10
    uint8_t val = uart_getc();
11
   itoa(val,str,10);
12
    uart_puts(str);
13
    uart_putc('\r');
14
    uart_putc('\n');
15
    _delay_ms(100);
16
  }
17
}
Gast #4202673
Lesenswert?

Max M. schrieb:
> Yeah, es geht :)
das ist schön..

> P.S. Warum 49 als Ergebnis ausgegeben wird obwohl ich "1" sende,
> verstehe ich aber nicht...
Weil Du das Zeichen mit itoa in einen Zahlstring konvtertierst, der dem 
Zeichencode in dez entspricht. Nimmste als Radix 16, wird hex 31 
zurückgegeben.. 'A' ist 65 dez und 41 hex
>
> Edit: okay, anscheinend braucht man C#-Programm ein Ende-Zeichen, so
> gehts:
Da haben sich unsere Posts überschnitten..

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