mikrocontroller.net

Forum: Compiler & IDEs uart senden und empfangen im atmega8


Autor: henry (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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
#ifndef F_CPU
/* 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:*/
#warning "F_CPU was not defined yet, now make up with 3686400"
#define F_CPU 3686400L   // Systemtakt in Hz - 
#endif


#define BAUD 9600L
#define UBRR_VAL ((F_CPU+BAUD * 8)/(BAUD*16)-1)     //clever round
#define BAUD_REAL (F_CPU/(16*(UBRR_VAL+1)))         //real baud rate
#define BAUD_ERROR ((BAUD_REAL*1000)/BAUD-1000)     //Error per thousand


#if ((BAUD_ERROR>10)||(BAUD_ERROR<-10))
#error Systematic error in the baud rate more than 1% and thus too high!
#endif

#include <stdint.h>
#include <avr/io.h>
#include <util/delay.h>


void USART_Init()
{
    // Set baud rate
    UBRRH = (unsigned char)(UBRR_VAL>>8);
    UBRRL = (unsigned char)UBRR_VAL;
    // Enable Receiver and Transmitter
    UCSRB = (1<<RXEN)|(1<<TXEN);
    // Set frame format: 8data, 1stop bit
    UCSRC = (1<<URSEL) | (1<<UCSZ1)|(1<<UCSZ0);  
}

void USART_Transmit( unsigned char data )
{
    // Wait for empty transmit buffer
    while ( !( UCSRA & (1<<UDRE)) ){
    }
    // Put data into buffer, sends the data
    UDR = data;
}

void UART_Puts (char *string)
{
    while( *string != '\0' )  //as long as *string != '\0' 
        USART_Transmit(*string);
        string++;
    }
}//end USART_Puts()

unsigned char USART_Receive( void )
{
    // Wait for data to be received 
    while ( !(UCSRA & (1<<RXC)) );
    // Get and return received data from buffer 
    return UDR;
}

int main(void){
    USART_Init(); 
    DDRB = 0xFF;
    PORTB = 0x00;
    unsigned char test;
    while(1){
  test = USART_Receive();
  UART_Puts("\r\n");
  //USART_Transmit(test);  

        if(test == 1){
            PORTB = 4;
      _delay_ms(10);
        }
        else if(test == 0){
            PORTB = 8;
      _delay_ms(10);
        }
        //PORTB = 1;
    }
}

vielen Dank für euere Hilfe
merci

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: henry (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
vielen Dank
so einfach war es.

Autor: henry (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
jetzt möchte ich ein String empfangen. Leider funktioniert nicht.
code siehe unten:
unsigned char UART_Gets (void)
{
  uint8_t i;
    char c;
    char* s;
  char string[length+1];

  while(1)
  {     
      s=string;
      i=0;
      do
      {
        c=UART_Getc();    
        if (c!='\r') 
         {
            *s=c;    
          s++;
          i++;
         }       
      }
      while( i!=length && c!='\r');  
      *s=0;
  }
  return *s;
}//end USART_Gets()

Aufruf:
int main()
{
...
while(1)
  {
  test = UART_Gets();
  UART_Puts( "\r\n" );
    UART_Puts( "eingegebender Text: " );
    UART_Puts( test );
        UART_Puts( "\r\n" );
  PORTB = 0x01;
....  

        
}

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
LOL

Deine UART_gets wird hier

  while(1)
  {

Schwierigkeiten haben, jemals die Funktion zu verlassen.

Autor: Stefan Ernst (sternst)
Datum:

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

Autor: henry (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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?!
uint8_t i;
    char c;
    char* s;
  char string[length+1];

  while(1)
  {     
      s=string;
      i=0;
      do
      {
        c=UART_Getc();    
        if (c!='\r') 
         {
            *s=c; 
      UART_Putc( c );   
          s++;
          i++;
         }       
      }
      while( i!=length && c!='\r');  
      *s=0;

merci

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: henry (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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
#ifndef F_CPU
/* 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:*/
#warning "F_CPU was not defined yet, now make up with 3686400"
#define F_CPU 4000000 //3686400L                 // Systemtakt in Hz - define as  long>> Without errors in the computation 
#endif


#define BAUD 9600L
#define UBRR_VAL ((F_CPU+BAUD * 8)/(BAUD*16)-1)     //clever round
#define BAUD_REAL (F_CPU/(16*(UBRR_VAL+1)))         //real baud rate
#define BAUD_ERROR ((BAUD_REAL*1000)/BAUD-1000)     //Error per thousand


#if ((BAUD_ERROR>10)||(BAUD_ERROR<-10))
#error Systematic error in the baud rate more than 1% and thus too high!
#endif

#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <avr/io.h>
#include <util/delay.h>


#define LENGTH 10  //Textlänge ab welcher Empfangen beendet wird

void UART_Init()
{
    // Set baud rate
    UBRRH = (unsigned char)(UBRR_VAL>>8);
    UBRRL = (unsigned char)UBRR_VAL;
    // Enable Receiver and Transmitter
    UCSRB = (1<<RXEN)|(1<<TXEN);
    // Set frame format: 8data, 1stop bit
    UCSRC = (1<<URSEL) | (1<<UCSZ1)|(1<<UCSZ0);  
}

void UART_Putc( unsigned char data )
{
    // Wait for empty transmit buffer
    while ( !( UCSRA & (1<<UDRE)) ){
    }
    // Put data into buffer, sends the data
    UDR = data;
}

void UART_Puts (char *string)
{
    while( *string != '\0' )  //as long as *string != '\0' so unlike the "stringer end-character"
    {  
        UART_Putc(*string);
        string++;
    }
}//end USART_Puts()

unsigned char UART_Getc( void )
{
    // Wait for data to be received 
    while ( !(UCSRA & (1<<RXC)) );
    // Get and return received data from buffer 
    return UDR;
}

void UART_Gets (char* s, unsigned int Length)
{
  uint8_t i;
    char c;
    //char* s;
  char string[Length+1];

  while(1)
  {     
      s=string;
      i=0;
      do
      {
        c=UART_Getc();    
        if (c!='\r') 
         {
            *s=c;    
          s++;
          i++;
         }       
      }
      while( i!=Length && c!='\r');  
      *s = '\0';
  }

}


int main(void)
{
    UART_Init();
    DDRB = 0xFF;
    PORTB = 0x00;

    char test[LENGTH+1];

    while(1)
  {     
      
  UART_Gets( test, LENGTH );
  UART_Puts( "\r\n" );
    UART_Puts( "eingegebender Text: " );  
  UART_Puts( test );
  PORTB = 0x01;
  

  return 0;
}

Autor: Stefan Ernst (sternst)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: henry (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Danke.
Ich war sogar Blind
jetzt klappt.
void UART_Gets (char* string, unsigned int Length)
{
  uint8_t i;
    char c;
    char* s;
  //char string[Length+1];

  
    s=string;
    i=0;
    do
    {
      c=UART_Getc();    
      if (c!='\r') 
       {
          *s=c;    
        s++;
        i++;
       }       
    }
    while( i!=Length && c!='\r');  
    *s = '\0';
  
  //strncpy( string, s, Length );
}//end UART_Gets

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.