Forum: Compiler & IDEs uart senden und empfangen im atmega8


von henry (Gast)


Lesenswert?

Hallo,

ich weiß, dass dieses Thema schon reichlich beackert wurde, aber ich bin 
neue und habe zu meinem Problem tatsächlich noch keine passende Lösung 
gefunden.

Ich möchte per USART Nach empfang von Zeichen eine Led anmachen leider 
fünktioniert nicht.

Ich habe ausprobiert die empfangene Zeichen wieder zu senden, und alles 
klappt super, senden auch nurdass es tut nichst wenn er entweder 0 oder 
1 empfängt.

hier unten den Code
1
#ifndef F_CPU
2
/* In the new version of the WinAVR/Mfile Makefile guideline One can defined F_CPU in the Makefile, a repeated definition here would lead to a compiler warning . therefore "prevention" through    #ifndef/#endif This "Prevention" can lead to Debugger, if AVRStudio use a another, not the hardware fitting Clock rate:  Then the    following definition doesn't use, but instead the default value (1 MHz?) of AVRStudio - hence the Output of a warning if F_CPU yet does not define:*/
3
#warning "F_CPU was not defined yet, now make up with 3686400"
4
#define F_CPU 3686400L   // Systemtakt in Hz - 
5
#endif
6
7
8
#define BAUD 9600L
9
#define UBRR_VAL ((F_CPU+BAUD * 8)/(BAUD*16)-1)     //clever round
10
#define BAUD_REAL (F_CPU/(16*(UBRR_VAL+1)))         //real baud rate
11
#define BAUD_ERROR ((BAUD_REAL*1000)/BAUD-1000)     //Error per thousand
12
13
14
#if ((BAUD_ERROR>10)||(BAUD_ERROR<-10))
15
#error Systematic error in the baud rate more than 1% and thus too high!
16
#endif
17
18
#include <stdint.h>
19
#include <avr/io.h>
20
#include <util/delay.h>
21
22
23
void USART_Init()
24
{
25
    // Set baud rate
26
    UBRRH = (unsigned char)(UBRR_VAL>>8);
27
    UBRRL = (unsigned char)UBRR_VAL;
28
    // Enable Receiver and Transmitter
29
    UCSRB = (1<<RXEN)|(1<<TXEN);
30
    // Set frame format: 8data, 1stop bit
31
    UCSRC = (1<<URSEL) | (1<<UCSZ1)|(1<<UCSZ0);  
32
}
33
34
void USART_Transmit( unsigned char data )
35
{
36
    // Wait for empty transmit buffer
37
    while ( !( UCSRA & (1<<UDRE)) ){
38
    }
39
    // Put data into buffer, sends the data
40
    UDR = data;
41
}
42
43
void UART_Puts (char *string)
44
{
45
    while( *string != '\0' )  //as long as *string != '\0' 
46
        USART_Transmit(*string);
47
        string++;
48
    }
49
}//end USART_Puts()
50
51
unsigned char USART_Receive( void )
52
{
53
    // Wait for data to be received 
54
    while ( !(UCSRA & (1<<RXC)) );
55
    // Get and return received data from buffer 
56
    return UDR;
57
}
58
59
int main(void){
60
    USART_Init(); 
61
    DDRB = 0xFF;
62
    PORTB = 0x00;
63
    unsigned char test;
64
    while(1){
65
  test = USART_Receive();
66
  UART_Puts("\r\n");
67
  //USART_Transmit(test);  
68
69
        if(test == 1){
70
            PORTB = 4;
71
      _delay_ms(10);
72
        }
73
        else if(test == 0){
74
            PORTB = 8;
75
      _delay_ms(10);
76
        }
77
        //PORTB = 1;
78
    }
79
}

vielen Dank für euere Hilfe
merci

von Karl H. (kbuchegg)


Lesenswert?

> Ich habe ausprobiert die empfangene Zeichen wieder zu senden, und alles
> klappt super, senden auch nurdass es tut nichst wenn er entweder 0 oder
> 1 empfängt.

Du empfängst nicht 0 oder 1.
Du empfängst '0' oder '1'. Das ist etwas anderes. Das sind Zeichen, so 
wie 'a', 'b' oder 'c'. Nur dass sie eben Ziffern-Zeichen sind.

von henry (Gast)


Lesenswert?

vielen Dank
so einfach war es.

von henry (Gast)


Lesenswert?

jetzt möchte ich ein String empfangen. Leider funktioniert nicht.
code siehe unten:
1
unsigned char UART_Gets (void)
2
{
3
  uint8_t i;
4
    char c;
5
    char* s;
6
  char string[length+1];
7
8
  while(1)
9
  {     
10
      s=string;
11
      i=0;
12
      do
13
      {
14
        c=UART_Getc();    
15
        if (c!='\r') 
16
         {
17
            *s=c;    
18
          s++;
19
          i++;
20
         }       
21
      }
22
      while( i!=length && c!='\r');  
23
      *s=0;
24
  }
25
  return *s;
26
}//end USART_Gets()

Aufruf:
1
int main()
2
{
3
...
4
while(1)
5
  {
6
  test = UART_Gets();
7
  UART_Puts( "\r\n" );
8
    UART_Puts( "eingegebender Text: " );
9
    UART_Puts( test );
10
        UART_Puts( "\r\n" );
11
  PORTB = 0x01;
12
....  
13
14
        
15
}

von Karl H. (kbuchegg)


Lesenswert?

henry schrieb:

>       do
>       {
>         c=UART_Getc();

An dieser Stelle ist es IMMER gut, das empfangene Zeichen auch wieder 
zurück zu senden, damit man im Terminal kontrollieren kann, was der µC 
empfangen hat.

>         if (c!='\r')

Bist du sicher, dass dein Terminal einen \r schickt, wenn du auf Return 
drückst?
In vielen Terminals kann man das einstellen, ob es dann \n, \r oder 
beides schicken soll

>       *s=0;

schreib das so:

       *s = '\0';

ist zwar genau das gleiche. Aber man sieht besser, dass es sich hier um 
eine Zuweisung eines Zeichens handelt.

von Karl H. (kbuchegg)


Lesenswert?

LOL

Deine UART_gets wird hier

  while(1)
  {

Schwierigkeiten haben, jemals die Funktion zu verlassen.

von Stefan E. (sternst)


Lesenswert?

Und eine UART_gets Funktion, die nur ein einzelnes Zeichen zurück gibt 
(und auch immer '\0'), scheint mir auch nicht sehr sinnvoll. ;-)

von henry (Gast)


Lesenswert?

danke für die Hilfe
leider geht nicht.

Das code unten habe ich direckt in main geschrieben und es ging.
Warum gibt meine Funktion dann kein string zurück?

Habe ich mir gedacht, dass meinem String nicht gespeichert würde, dann
Habe ich string als Static initialisiert leider ging immer nicht.
Kannst du mir etwas empfehlen?!
1
uint8_t i;
2
    char c;
3
    char* s;
4
  char string[length+1];
5
6
  while(1)
7
  {     
8
      s=string;
9
      i=0;
10
      do
11
      {
12
        c=UART_Getc();    
13
        if (c!='\r') 
14
         {
15
            *s=c; 
16
      UART_Putc( c );   
17
          s++;
18
          i++;
19
         }       
20
      }
21
      while( i!=length && c!='\r');  
22
      *s=0;

merci

von Karl H. (kbuchegg)


Lesenswert?

Womit sich dann natürlich die Frage erhebt, wie eigentlich test 
definiert ist

 while(1)
  {
  test = UART_Gets();
  UART_Puts( "\r\n" );
    UART_Puts( "eingegebender Text: " );
    UART_Puts( test );
        UART_Puts( "\r\n" );

Da müsste der Compiler eigentlich einen Haufen Warnings und Errors 
ausgeben.

von Karl H. (kbuchegg)


Lesenswert?

henry schrieb:
> danke für die Hilfe
> leider geht nicht.

Deine ganze Funktion ist falsch aufgebaut.

Strings sind in C immer ein Problem.
Am besten ist immer noch die Methode, wenn man der Funktion ein 
char-Array als Argument mitgibt (zusammen mit der Größe des Arrays) und 
die Funktion dort ihre Ergüsse hineinstellt.


> Das code unten habe ich direckt in main geschrieben und es ging.
> Warum gibt meine Funktion dann kein string zurück?

Weil der return Wert deiner Funktion nun mal unsigned char ist. Und das 
ist kein String, sondern nur ein einzelnes Zeichen.

von henry (Gast)


Lesenswert?

Karl heinz Buchegger schrieb:

>Strings sind in C immer ein Problem.
>Am besten ist immer noch die Methode, wenn man der Funktion ein
>char-Array als Argument mitgibt (zusammen mit der Größe des Arrays) und
>die Funktion dort ihre Ergüsse hineinstellt.

Danke für die Anweisung.
hier unten den Code umgeschrieben, und jetzt kriege ich keine 
Fehlermeldungen und Warnungen leider funktioniert immer noch nicht.

Bitte um Hilfe
1
#ifndef F_CPU
2
/* In the new version of the WinAVR/Mfile Makefile guideline One can defined F_CPU in the Makefile, a repeated 
3
   definition here would lead to a compiler warning . therefore "prevention" through    #ifndef/#endif
4
5
   This "Prevention" can lead to Debugger, if AVRStudio use a another, not the hardware fitting Clock rate: 
6
   Then the    following definition doesn't use, but instead the default value (1 MHz?) of AVRStudio - hence 
7
   the Output of a warning if F_CPU yet does not define:*/
8
#warning "F_CPU was not defined yet, now make up with 3686400"
9
#define F_CPU 4000000 //3686400L                 // Systemtakt in Hz - define as  long>> Without errors in the computation 
10
#endif
11
12
13
#define BAUD 9600L
14
#define UBRR_VAL ((F_CPU+BAUD * 8)/(BAUD*16)-1)     //clever round
15
#define BAUD_REAL (F_CPU/(16*(UBRR_VAL+1)))         //real baud rate
16
#define BAUD_ERROR ((BAUD_REAL*1000)/BAUD-1000)     //Error per thousand
17
18
19
#if ((BAUD_ERROR>10)||(BAUD_ERROR<-10))
20
#error Systematic error in the baud rate more than 1% and thus too high!
21
#endif
22
23
#include <stdio.h>
24
#include <stdint.h>
25
#include <string.h>
26
#include <avr/io.h>
27
#include <util/delay.h>
28
29
30
#define LENGTH 10  //Textlänge ab welcher Empfangen beendet wird
31
32
void UART_Init()
33
{
34
    // Set baud rate
35
    UBRRH = (unsigned char)(UBRR_VAL>>8);
36
    UBRRL = (unsigned char)UBRR_VAL;
37
    // Enable Receiver and Transmitter
38
    UCSRB = (1<<RXEN)|(1<<TXEN);
39
    // Set frame format: 8data, 1stop bit
40
    UCSRC = (1<<URSEL) | (1<<UCSZ1)|(1<<UCSZ0);  
41
}
42
43
void UART_Putc( unsigned char data )
44
{
45
    // Wait for empty transmit buffer
46
    while ( !( UCSRA & (1<<UDRE)) ){
47
    }
48
    // Put data into buffer, sends the data
49
    UDR = data;
50
}
51
52
void UART_Puts (char *string)
53
{
54
    while( *string != '\0' )  //as long as *string != '\0' so unlike the "stringer end-character"
55
    {  
56
        UART_Putc(*string);
57
        string++;
58
    }
59
}//end USART_Puts()
60
61
unsigned char UART_Getc( void )
62
{
63
    // Wait for data to be received 
64
    while ( !(UCSRA & (1<<RXC)) );
65
    // Get and return received data from buffer 
66
    return UDR;
67
}
68
69
void UART_Gets (char* s, unsigned int Length)
70
{
71
  uint8_t i;
72
    char c;
73
    //char* s;
74
  char string[Length+1];
75
76
  while(1)
77
  {     
78
      s=string;
79
      i=0;
80
      do
81
      {
82
        c=UART_Getc();    
83
        if (c!='\r') 
84
         {
85
            *s=c;    
86
          s++;
87
          i++;
88
         }       
89
      }
90
      while( i!=Length && c!='\r');  
91
      *s = '\0';
92
  }
93
94
}
95
96
97
int main(void)
98
{
99
    UART_Init();
100
    DDRB = 0xFF;
101
    PORTB = 0x00;
102
103
    char test[LENGTH+1];
104
105
    while(1)
106
  {     
107
      
108
  UART_Gets( test, LENGTH );
109
  UART_Puts( "\r\n" );
110
    UART_Puts( "eingegebender Text: " );  
111
  UART_Puts( test );
112
  PORTB = 0x01;
113
  
114
115
  return 0;
116
}

von Stefan E. (sternst)


Lesenswert?

Du schreibst ja auch nicht in den zur Verfügung gestellten Puffer, 
sondern immer noch in einen lokalen.

PS: Und das while(1) ist auch immer noch drin.

von henry (Gast)


Lesenswert?

Danke.
Ich war sogar Blind
jetzt klappt.
1
void UART_Gets (char* string, unsigned int Length)
2
{
3
  uint8_t i;
4
    char c;
5
    char* s;
6
  //char string[Length+1];
7
8
  
9
    s=string;
10
    i=0;
11
    do
12
    {
13
      c=UART_Getc();    
14
      if (c!='\r') 
15
       {
16
          *s=c;    
17
        s++;
18
        i++;
19
       }       
20
    }
21
    while( i!=Length && c!='\r');  
22
    *s = '\0';
23
  
24
  //strncpy( string, s, Length );
25
}//end UART_Gets

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.