mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik Atmega644 UART - Komische Ausgabe


Autor: mcnanuk (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo zusammen,

mir raucht der Kopf und ich weiss nimmer weiter.
Ich verwende ein STK 500 mit dem internen Clock von 3,686 MHz, undmöchte 
gerne die Uart Libary von Peter Fleury verwenden.

ich habe mal das Beispiel hergenommen und versucht es zum Laufen zu 
bewegen.
Es tut, aber ich bekomme nur Murks Ausgaben zurück: Kästchen, 
Sonderzeichen, und so weiter.

Als Baudraten hab ich jetzt schon mehreres Versucht, wobei 9600 aber 
stimmen sollte. Auch 115200 und 14400 hb ich schon versucht.

hier mein Code
/*************************************************************************
Title:    example program for the Interrupt controlled UART library
Author:   Peter Fleury <pfleury@gmx.ch>   http://jump.to/fleury
File:     $Id: test_uart.c,v 1.4 2005/07/10 11:46:30 Peter Exp $
Software: AVR-GCC 3.3
Hardware: any AVR with built-in UART, tested on AT90S8515 at 4 Mhz

DESCRIPTION:
          This example shows how to use the UART library uart.c

*************************************************************************/
#include <stdlib.h>
#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/signal.h>
#include <avr/pgmspace.h>

#include "uart.h"


/* define CPU frequency in Mhz here if not defined in Makefile */

#define F_CPU 3686000UL


/* 9600 baud */
#define UART_BAUD_RATE 14400 


int main(void)
{
    unsigned int c;
    char buffer[7];
    int  num=134;

      

    /*
     *  Initialize UART library, pass baudrate and AVR cpu clock
     *  with the macro 
     *  UART_BAUD_SELECT() (normal speed mode )
     *  or 
     *  UART_BAUD_SELECT_DOUBLE_SPEED() ( double speed mode)
     */
    uart_init( UART_BAUD_SELECT(UART_BAUD_RATE,F_CPU) ); 
  uart_puts("hallo" );  
    
    /*
     * now enable interrupt, since UART library is interrupt controlled
     */
    sei();
    
    /*
     *  Transmit string to UART
     *  The string is buffered by the uart library in a circular buffer
     *  and one character at a time is transmitted to the UART using interrupts.
     *  uart_puts() blocks if it can not write the whole string to the circular 
     *  buffer
     */
    uart_puts("String stored in SRAM\n");
    
    /*
     * Transmit string from program memory to UART
     */
    uart_puts_P("String stored in FLASH\n");
    
        
    /* 
     * Use standard avr-libc functions to convert numbers into string
     * before transmitting via UART
     */     
    itoa( num, buffer, 10);   // convert interger into string (decimal format)         
    uart_puts(buffer);        // and transmit string to UART

    
    /*
     * Transmit single character to UART
     */
    uart_putc('\r');
    
    for(;;)
    {
        /*
         * Get received character from ringbuffer
         * uart_getc() returns in the lower byte the received character and 
         * in the higher byte (bitmask) the last receive error
         * UART_NO_DATA is returned when no data is available.
         *
         */
        c = uart_getc();
        if ( c & UART_NO_DATA )
        {
            /* 
             * no data available from UART 
             */
        }
        else
        {
            /*
             * new data available from UART
             * check for Frame or Overrun error
             */
            if ( c & UART_FRAME_ERROR )
            {
                /* Framing Error detected, i.e no stop bit detected */
                uart_puts_P("UART Frame Error: ");
            }
            if ( c & UART_OVERRUN_ERROR )
            {
                /* 
                 * Overrun, a character already present in the UART UDR register was 
                 * not read by the interrupt handler before the next character arrived,
                 * one or more received characters have been dropped
                 */
                uart_puts_P("UART Overrun Error: ");
            }
            if ( c & UART_BUFFER_OVERFLOW )
            {
                /* 
                 * We are not reading the receive buffer fast enough,
                 * one or more received character have been dropped 
                 */
                uart_puts_P("Buffer overflow error: ");
            }
            /* 
             * send received character back
             */
            uart_putc( (unsigned char)c );
        }
    }
    
}

Hoffentlich kann mir einer helfen. Was kann ich noch tun, bzw wo soll 
ich schauen ?

Als Terminal habe ich 4 verschiedene versucht. Bei allen das Gleiche.

Autor: Sohn von Gosar (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
welches Terminal Programm benutzt du? Hast du auch dort die selbe 
Baud-Rate eingestellt?

Autor: Sohn von Gosar (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
wo ist übrigens die uart_init() ?

Autor: Magnetus (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Sohn von Gosar schrieb:
> wo ist übrigens die uart_init() ?

In "uart.h" natürlich  ;o)

Autor: g457 (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert

Autor: Sohn von Gosar (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Magnetus schrieb:
> In "uart.h" natürlich  ;o)

jo, hab ich überlesen. Wird ja immer früher heut nacht :)

Autor: mcnanuk (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Erscheinen im Terminalprogramm kryptische Zeichen anstatt ordentlichen 
Buchstaben (z. B. ü statt A), liegt das zu 99,9% an einer falsch 
eingestellten/erzeugten Baudrate im Mikrocontroller.

Jop soweit war ich schon in der Checkliste.

Der Rest kann es fast nicht sein. Die Baudraten stimmen überein.

Ich verwende aktuell Hterm und Br@yTerminal
AVRTerminal hab ich heute mittag versucht...

Autor: Peter Diener (pdiener) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Sind die Fuses (CLK_div8 usw.) im Controller richtg gesetzt, so dass er 
wirklich auf der gewollten Frequenz arbeitet?

Grüße,

Peter

Autor: Sohn von Gosar (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
handshaking richtig konfiguriert? den eventuellen Frequenzteiler auch 
berücksichtigt?

Hterm verwende ich auch meist, hatte nie Probleme damit

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

Bewertung
0 lesenswert
nicht lesenswert
mcnanuk schrieb:
> Erscheinen im Terminalprogramm kryptische Zeichen anstatt ordentlichen
> Buchstaben (z. B. ü statt A), liegt das zu 99,9% an einer falsch
> eingestellten/erzeugten Baudrate im Mikrocontroller.
>
> Jop soweit war ich schon in der Checkliste.

Die Betonung liegt auf 'erzeugt'

Und damit die richtig erzeugt wird muss die Taktfrequenz des Controllers 
stimmen.
Das hier
> mit dem internen Clock von 3,686 MHz

bestärkt mich im meiner Vermutung, dass dein µC eben nicht mit 3.686 Mhz 
sondern mit den fabrikmässigen 1.0Mhz arbeitet.

einen internen Clock mit dieser Frequenz gibt es nicht. Wenn überhaupt, 
dann hast du einen Quarz mit dieser Frequenz am µC hängen. Die Frage ist 
allerdings: Ist der aktiv? Hast du das kontrolliert?

Autor: Sohn von Gosar (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
ich kenn die Library nicht aber hier steht:

> /* define CPU frequency in Mhz here if not defined in Makefile */
>
> #define F_CPU 3686000UL

du gibts die Frequenz aber in Hertz und nicht MHz an...

Autor: mcnanuk (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Reading fuses address 0 to 2.. 0xC2, 0xDD, 0xFF .. OK!

CLK_div8 ist nicht gesetzt
Int. RC Osc.; Start-up time: 6 CK + 65 ms habe ich gewählt bei den Fuses

ich dachte damit und der richtigen Jumper Setzung "On-Board software 
clock signal connected" läuft das Board mit Standardmässigen 3,686 Mhz

Allerdings verwirrt mich das thema Fuses noch ein wenig

Autor: Peter Diener (pdiener) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Int. RC Osc. ist falsch.
Da muss die gewünschte externe Taktquelle stehen (das ist normal ein 
Quartz).

Grüße,

Peter

Autor: mcnanuk (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Das heisst ich brauche unbedingt einen Quarz ?

Autor: Sohn von Gosar (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
fa

mcnanuk schrieb:
> Das heisst ich brauche unbedingt einen Quarz ?

ne, wenn du mit 1MHz auskommt, die der interne Oszilator zu Verfügung 
stellt, dann nicht. Allerdings ist dieser nicht sonderlich stabil und 
besonders temperaturabhängig...

Autor: Peter Diener (pdiener) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>Das heisst ich brauche unbedingt einen Quarz ?

Du hast doch oben geschrieben, dass du einen 3,686 Mhz Takt hast. Ob der 
von einem angeschlossenen Quarz oder einem externen oszillator kommt, 
weiß ich nicht. Ich kenne ja deinen Aufbau nicht.

Das ist jedenfalls das entscheidende, was man mit den Fuses auswählt:
* Externer oszillator oder
* Externes Quartz oder
* Interner RC-Oszillator (ungenau)

Testweise kannst du die Fuseeinstellungen ja mal so lassen wie oben und 
im Code 1 MHz als Takt angeben. Mal sehen, was dann passiert...

Grüße,

Peter

Autor: mcnanuk (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Also vielleicht um ein Wort was ich vorhabe:

ich will nur ein Int übergeben über das Uart...

ich habe keine Ahnung, ob der Interne Clock ausreichend ist. Ich dachte 
bisher dass mein interner Clock 3,686 MHz ... wiso der jetzt nur 1 MHz 
ist, versteh ich nicht.

Autor: mcnanuk (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Peter Diener schrieb:
> Testweise kannst du die Fuseeinstellungen ja mal so lassen wie oben und
> im Code 1 MHz als Takt angeben. Mal sehen, was dann passiert...

Habs getestet, aber es ändert sich nicht viel, ausser dass andere 
Zeichen geplottet werden

Autor: Peter Diener (pdiener) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
So, ich hab das mal eben im Handbuch nachgelesen.
Das STK500 hat eine programmierbare Takterzeugung, bei der 
Taktfrequenzen zwischen 0 und 3,68 MHz eingestellt werden können.

Per Jumperkonfiguration kann man diesen Takt auf den Zielprozessor 
routen.

Die Fuses müssen dann für "external Clock" konfiguriert sein.

Hier gibt's ein Handbuch als Übersetzung:
http://www.mikrocontroller.net/attachment/42741/ST...
Das Wichtige steht auf Seite 28.

Grüße,

Peter

Autor: mcnanuk (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wenn der XTAL1-Jumper gesetzt ist, liefert die STK500-interne 
Takt-quelle den Takt für den AVR. Die interne Taktquelle kann entweder 
durch einen Quarz oder durch einen Software-Taktgenerator vom 
Bord-Controller betrieben werden. Der Software-Taktgenerator kann von 0 
bis 3,68 MHz eingestellt werden. 3,68 MHz ist die Standardeinstellung. 
Kapi-tel xy auf Seite xy erklärt wie die Taktfrequenz mit AVR Studio 
eingestellt wird.

Wenn das vom Bord-Controller generierte Taktsignal genutzt wird, müs-sen 
die Fuse-Bits des AVR auf „external clock“ als Taktquelle konfiguriert 
werden.


Das ist mal ein Auzug aus dem STK 500 Handbuch.... Besonders der letzte 
Satz ...

Args... das hat mich jetzt einen Tag gekostet :) Aber jetzt tut es... 
ich danke für die vielen hilfreichen Hinweise nochmals auf bestimmte 
Dinge zu schauen. Ich hab den Fehler woanders vermutet.

Autor: mcnanuk (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Danke Peter... ich hatte leider das handbuch nimmer, und habs hier im 
Forum als übersetzung gefunden :)

Autor: mcnanuk (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich hab noch eine Folgefrage:
unsigned int uart_getc    (     void          )     
Get received byte from ringbuffer.

Returns in the lower byte the received character and in the higher byte the last receive error. 
UART_NO_DATA is returned when no data is available.

Parameters:
      void   

Returns:
    lower byte: received byte from ringbuffer

    higher byte: last receive status

Das ist der Auszug aus dem Manual. Meine Frage ist nun, wie ich mittels 
C-Code nun an das lower byte rankomme. Soweit ich es verstanden habe, 
ist das die Information die geschickt worden ist.

Wie schon geschrieben, möchte ich eine Zahl vom PC empfangen und diese 
dann in mein µC Programm einbinden. Da ich eigentlich nur Java wirklich 
gut kann, stehe ich jetzt hier etwas auf dem Schlauch. Ich speichere das 
ergebnis von uart_getc in einem unsigned int c.
Das sollte doch die 16 bit haben, die man benötigt um die 2 Byte zu 
speichern.

Ich hoffe mir kann einer helfen :)

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

Bewertung
0 lesenswert
nicht lesenswert
mcnanuk schrieb:

> Das ist der Auszug aus dem Manual. Meine Frage ist nun, wie ich mittels
> C-Code nun an das lower byte rankomme. Soweit ich es verstanden habe,
> ist das die Information die geschickt worden ist.

Ähm.
Peter Fleury hat dir ein wunderschönes Demo-Beispiel gebaut.
Dort kannst du dir das alles ansehen.

Beitrag "Atmega644 UART - Komische Ausgabe"


> Da ich eigentlich nur Java wirklich
> gut kann, stehe ich jetzt hier etwas auf dem Schlauch.

Das sioll dich aber nicht daran hindern, mit einer Library mitgelieferte 
Demos zu studieren.

Autor: mcnanuk (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
  if((unsigned char)c < 100)
  {
     lcd_clrscr();
     lcd_puts("Kleiner 100 \n");
           lcd_putc((unsigned char)c);
  } else {
     lcd_clrscr();
     lcd_puts("Größer 100 \n");
     lcd_putc((unsigned char)c);
  }
//  lcd_putc( (unsigned char)c);
        uart_putc( (unsigned char)c );

Dieser Code funktioriert aber nicht so wie ich das erwarte: Unter der 
IfElse Abfrage habe ich ich ein lcd_putc auskommentiert. Wenn nur dieses 
dort steht, ohne die Schleife, dann wird genau das wiedergeben, was ich 
gesendet habe. Allerdings innerhalb der Schleife, wird nur eine 
einstellige Zahl wiedergegeben, genauer die letzte Stelle der Eingabe.

Was also mache ich falsch ? Und warum verhällt sich die Methode 
innerhalb der Abfrage anders ?

Autor: Sohn von Gosar (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
eine Frage, warum benutzt du die Library überhaupt? Der Uart ist im 
Grunde sehr einfach zu konfigurieren, in dieser Zeit hättest du das 
locker selbst geschafft.

außerdem wärs sicherlich hilfreich, wenn du mal den kompletten Code 
posten würdest...

Autor: mcnanuk (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
#include <stdlib.h>
#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/signal.h>
#include <avr/pgmspace.h>
#include "lcd.h"
#include "uart.h"


/* define CPU frequency in Mhz here if not defined in Makefile */

#define F_CPU 3686000UL


/* 9600 baud */
#define UART_BAUD_RATE      9600      


int main(void)
{
    unsigned int c;
    char buffer[7];
    int  num=134;

   //  lcd_init(LCD_DISP_ON);

    /*
     *  Initialize UART library, pass baudrate and AVR cpu clock
     *  with the macro 
     *  UART_BAUD_SELECT() (normal speed mode )
     *  or 
     *  UART_BAUD_SELECT_DOUBLE_SPEED() ( double speed mode)
     */
    uart_init( UART_BAUD_SELECT(UART_BAUD_RATE,F_CPU) ); 

    /*
     * now enable interrupt, since UART library is interrupt controlled
     */
    sei();
    
    /*
     *  Transmit string to UART
     *  The string is buffered by the uart library in a circular buffer
     *  and one character at a time is transmitted to the UART using interrupts.
     *  uart_puts() blocks if it can not write the whole string to the circular 
     *  buffer
     */
    uart_puts("String stored in SRAM\n");
    
    /*
     * Transmit string from program memory to UART
     */
    uart_puts_P("String stored in FLASH\n");
    
        
    /* 
     * Use standard avr-libc functions to convert numbers into string
     * before transmitting via UART
     */     
    itoa( num, buffer, 10);   // convert interger into string (decimal format)         
    uart_puts(buffer);        // and transmit string to UART

    
    /*
     * Transmit single character to UART
     */
    uart_putc('\r');
    
    for(;;)
    {
        /*
         * Get received character from ringbuffer
         * uart_getc() returns in the lower byte the received character and 
         * in the higher byte (bitmask) the last receive error
         * UART_NO_DATA is returned when no data is available.
         *
         */
        c = uart_getc();
        if ( c & UART_NO_DATA )
        {
            /* 
             * no data available from UART 
             */
        }
        else
        {
            /*
             * new data available from UART
             * check for Frame or Overrun error
             */
            if ( c & UART_FRAME_ERROR )
            {
                /* Framing Error detected, i.e no stop bit detected */
                uart_puts_P("UART Frame Error: ");
            }
            if ( c & UART_OVERRUN_ERROR )
            {
                /* 
                 * Overrun, a character already present in the UART UDR register was 
                 * not read by the interrupt handler before the next character arrived,
                 * one or more received characters have been dropped
                 */
                uart_puts_P("UART Overrun Error: ");
            }
            if ( c & UART_BUFFER_OVERFLOW )
            {
                /* 
                 * We are not reading the receive buffer fast enough,
                 * one or more received character have been dropped 
                 */
                uart_puts_P("Buffer overflow error: ");
            }
            /* 
             * send received character back
             */

       /*
      


      switch (c)  {

            case '1':
                lcd_clrscr();
      lcd_puts("Ha \n");
                break;

            case '2':
               lcd_clrscr();
      lcd_puts("Hu \n");
                break;
           } */      


      if(c < 100)
      {
         lcd_clrscr();
         lcd_puts("Kleiner 100 \n");
               lcd_putc((unsigned char)c);
      } else {
         lcd_clrscr();
         lcd_puts("Größer 100 \n");
         lcd_putc((unsigned char)c);
      }
      
      lcd_putc( (unsigned char)c);
            uart_putc( (unsigned char)c );
        }
    }
    
}


Mein Ziel ist es den vom PC empfangenen Wert in meinem Programm später 
weiterzuverwenden. Ich versuche nun mit den Datentypen klar zu kommen. 
Und eben hier verwirrt mich das Verhalten von meinem Code. Lasse ich den 
IfElse Teil weg, dann wird der korrekte Wert am LCD ausgegeben. Schalte 
ich ihn dazwischen, wird bloß die letzte Ziffer ausgegeben. Ich verstehe 
einfach nicht warum.
Das c ist ist ein unsigned int.
Wenn ich das richtig verstehe, wird mit (unsigned char)c der LCD Routine 
dieses int als Chararray übergeben, und char für char auf dem LCD 
ausgegeben.

Aber hier verwirrt es mich nun völlig.

Autor: holger (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>Das c ist ist ein unsigned int.
>Wenn ich das richtig verstehe, wird mit (unsigned char)c der LCD Routine
>dieses int als Chararray übergeben, und char für char auf dem LCD
>ausgegeben.

So einfach ist das nun auch nicht;)
Lies mal was zu itoa();

Und kauf dir ein C-Buch.

Autor: Hc Zimmerer (mizch)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
    /*
     * Transmit string from program memory to UART
     */
    uart_puts_P("String stored in FLASH\n");
    

Das ist verkehrt, genauso wie alle nachfolgenden Aufrufe von 
uart_puts_P.  Denn es reicht nicht aus, dass der String behauptet, im 
Flash zu sein, sondern er muss auch dorthin gebracht werden.  Schau Dir 
mal in der Dokumentation zu <avr/pgmspace.h> an, was z.B. der Macro 
PSTR() tut.

Autor: mcnanuk (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Holger, itoa hilft mir doch nicht wirklich weiter oder? Diese 
Methode wandelt mir doch ein Integer in einen String um. In der 
variablen c steckt doch mehr als nur der Wert der gesendet wurde.


@ Hc Zimmerer: Der Code ist nicht von mir, es ist das Beispiel aus der 
Fleury Libary. Ich könnte diese Zeilen auch löschen, da sie ja nur beim 
Einschalten ausgeführt werden, und keine Funktion für mich haben. Ob es 
nun richtig ist oder nicht kann ich nicht beurteilen, aber ich vertraue 
mal darauf, dass Herr Fleury mehr davon versteht als ich im Moment noch.

Autor: Peter Diener (pdiener) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>In der variablen c steckt doch mehr als nur der Wert der gesendet wurde.

Ja, das obere Byte ist der Fehlercode und das untere sind die Nutzdaten.

Nutzdaten = c & 0x00ff;
Fehlercode = c & 0xff00;

Korrekt müsste es also heißen:
if( (c & 0x00ff) < 100 )  // ist das Zeichen ein ASCII-Code kleiner 100?
      {
         lcd_clrscr();
// usw...

Grüße,

Peter

Autor: A. K. (prx)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
mcnanuk schrieb:

> Wenn der XTAL1-Jumper gesetzt ist, liefert die STK500-interne
> Takt-quelle den Takt für den AVR.

Wenn du für die Taktquelle des STK500 den Begriff "intern" vermeidest 
und durch "STK500-eigenen Takt" ersetzt, reduzierst du die 
perspektivische Verwirrung. Um zu vermeiden, dass der interne Takt des 
Einen der externe Takt des Anderen ist.

Autor: mcnanuk (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Danke Peter,

leider bringt das auch keine Besserung...
if((c & 0x00ff) < 100)
      {
         lcd_clrscr();
         lcd_puts("Kleiner 100 \n");
     uart_puts(itoa((c & 0x00ff),buffer,10));
         lcd_puts(itoa((c & 0x00ff),buffer,10));
      } else {
         lcd_clrscr();
         lcd_puts("Größer 100 \n");
     uart_puts(itoa((c & 0x00ff),buffer,10));
         lcd_puts(itoa((c & 0x00ff),buffer,10));
      }

Das terminal empfängt jetzt bei einer Eingabe von 255: 505353
Im LCD lese ich immer Kleiner als 100 und die letzten 2 Stellen der 
Terminal Rückgabe hier als 53 werden zurückgegeben.

Hätte nicht gedacht, dass das so ne Nuss wird. Ich habe schon einen 
manuellen versuch unternommen, aber auch dort passieren Dinge die sich 
mir nicht erschliessen.


Ich häng den Code mal an: Vielleicht will es ja mal jemand checken, ich 
finde den Fehler nicht.

Wenn ich 222 Transmitte, bekomme ich 20202000 wieder zurück. Es 
schleicht sich irgendwo eine 0 dazwischen.

#include <avr/io.h>
#include <stdio.h>
#include <string.h>
#include <util/delay.h>
#include <avr/interrupt.h>
#include "lcd.h"


int Flughoehe;
char buffer[7];
char Buffer[7];
char usartString[] = "";

// Sendet ein einzelnes Zeichen
void uart_putc( char c )
{
  // Warte bis die Sendeeinheit bereit ist
  while( !(UCSR0A & ( 1<<UDRIE0) ) )
    ;
  UDR0 = c;
}

// Sende einen C-String
void uart_puts( const char* str )
{
  while( *str ) {
    uart_putc( *str );
    str++;
  }
}

// Ausgabe mit printf über USART
static int uart_putchar(char c, FILE *stream);
static FILE mystdout = FDEV_SETUP_STREAM(uart_putchar, NULL,
                                            _FDEV_SETUP_WRITE);

static int
    uart_putchar(char c, FILE *stream)
    {

      if (c == '\n')
        uart_putchar('\r', stream);
      loop_until_bit_is_set(UCSR0A, UDRIE0);
      UDR0 = c;
      return 0;
    }

unsigned char USART_RX(void)
{
  while(!(UCSR0A&(1<<RXC0)))
    ;
  return UDR0;
}

void uart_gets( int* Input )
{
  char c = USART_RX();
  uart_putc( c );
  
  while( c != '\n' )
  {
    *Input = c;
    Input++;
    c = USART_RX();
    uart_putc( c );
  }
  *Input = '\0';
}


void uart_init(void)
{
  // Baudrate setzen
  UBRR0H = 0x00;  //0000 0000
  UBRR0L = 0x17;  // Wert 23 ^= 9600 bei 3,686 MHz

  // Empfänger und Sender aktivieren
  UCSR0A = 0x00;   //0000 0000
  UCSR0B = 0x18;  //0001 1000  

  /* Einstellungen: Asynchron, 8-Bit, keine Parität, 1 Stop bit */
  UCSR0C = 0x06;   //0000 0110
}


int main(void)
{

  // USART initialisieren
  uart_init();
  lcd_init(LCD_DISP_ON);
   sei();

  while(1)  // forever
  {
  
    uart_gets(Buffer);

    uart_puts( "Ihre Eingabe: " );
    uart_puts( Buffer );
    uart_putc( '\n' );


     usartString[0] = '\0';

     for (int i=0; i<7; i++) 
     { 
      Flughoehe = atoi(&Buffer[i]);

      if(Buffer[i] != 'x' )
      {
      
        strcat(usartString, itoa(Flughoehe, buffer, 10));    //Ergebnisstring basteln
      }else{
        break;
      }
    
     } 
     lcd_clrscr();
     lcd_puts(usartString); 

    
    uart_puts("Wert: ");
    uart_puts(usartString);
    uart_putc( '\n' );

    
    stdout = &mystdout;
    


  // Ende vom while
  }
// Ende der main
}




Autor: Stefan Ernst (sternst)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hc Zimmerer schrieb:
> Das ist verkehrt, genauso wie alle nachfolgenden Aufrufe von
> uart_puts_P.  Denn es reicht nicht aus, dass der String behauptet, im
> Flash zu sein, sondern er muss auch dorthin gebracht werden.

Nö, das passt schon so. Das uart_puts_P der Fleury-Lib ist ein Makro, 
das den String selber ins Flash packt.

Autor: mcnanuk (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
hat noch irgendjemand einen Tipp für mich. Irgendwie kann es nicht so 
schwer sein, aber ich bekomms einfach nicht hin.
char Buffer[16];
  unsigned char LastCharInBuffer;
        
void Add( char Neu )
{
  Buffer[LastCharInBuffer++] = Neu;
  Buffer[LastCharInBuffer] = '\0';
}



  lcd_clrscr();
    uart_putc((c & 0x00ff));
  
    Add((c & 0x00ff));
        lcd_puts(Buffer);
    lcd_puts("\n");
    
    
    
  if(atoi(Buffer)< 100)
    {
  lcd_clrscr();
     lcd_puts("Kleiner 100");
    } else {
  lcd_clrscr();
        lcd_puts("Bigger 100");
    }

Sowohl im Terminal als auch auf dem LCD hab ich die gewünschten 
Anzeigen, aber für meine IfElse Abfrage... da klappts nicht

Also wenn noch irgendwer nen Tipp hat, oder mir sagen kann, dass ich 
völlig auf dem Holzweg bin, dann würde ich mich arg freuen.

Autor: Sohn von Gosar (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
poste mal die atoi() funktion

Autor: mcnanuk (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
http://www.cplusplus.com/reference/clibrary/cstdlib/atoi/

ist eine Bibliotheksfunktion... umkehrung von itoa

Autor: mcnanuk (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
uart_putc((c & 0x00ff));
  
    Add((c & 0x00ff));

    
    
    
  if(atoi(Buffer)< 100)
    {
  lcd_clrscr();
  lcd_puts(Buffer);
    lcd_puts("\n");
     lcd_puts("Kleiner 100");
    } else {
  lcd_clrscr();
  lcd_puts(Buffer);
    lcd_puts("\n");
        lcd_puts("Bigger 100");
    }

Ich bin einen Schritt weiter: Das Problem jetzt, ich schreibe in meinen 
Buffer die Zahlen. Allerdings würde ich gerne mit einem Enterdruck im 
Terminal den Buffer danach wieder zurücksetzen, da sonst ja die weiteren 
Einträge immer weiter in den Buffer geschrieben werden, bis dieser voll 
ist.

Am liebsten würde ich den Buffer von Hinten befüllen. Das heisst alles 
mit 0 besetzen, und dann meine terminaleingaben rechtbündig eintragen. 
Somit hätte ich immer den ganzen Buffer voll, und beim Cast ins int 
würden die führenden Nullen nicht stören.

oder eben irgendanders den Buffer resetten. Aber keinen Plan wie.

Buffer[0] = '\0'; klappt nicht

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

Bewertung
0 lesenswert
nicht lesenswert
mcnanuk schrieb:

> leider bringt das auch keine Besserung...

Kein Wunder.
Du hast ein massives Verständnisproblem.

Übertragen werden Zeichen. Genauer gesagt: Die ASCII Codes der Zeichen!


> Das terminal empfängt jetzt bei einer Eingabe von 255: 505353

Du tippst auf deiner Tatstatur: 255

Über die SChnittstelle wird übertragen:
  Der ASCII Code für  '2'
  der ASCII Code für  '5'
  der ASCII Code für  '5'

Und jetzt holst du dir aus dem Web eine ASCII Tabelle und siehst nach, 
welche Codes das sind.

'2'   hat den ASCII Code 0x32  oder dezimal 50
'5'   hat den ASCII Code 0x35  oder dezimal 53

Hier
if((c & 0x00ff) < 100)
      {
         lcd_clrscr();
         lcd_puts("Kleiner 100 \n");
     uart_puts(itoa((c & 0x00ff),buffer,10));

machst du nichts anderes als den ASCII Code des empfangenen Zeichens 
auszugeben. Schlauerweise in dezimal und schlauerweise ohne Leerzeichen 
dazwischen, damit man nicht weiß wo ein Code aufhört und der nächste 
anfängt :-)


Du musst die einzelnen Zeichen, die du empfängst zuerst einmal zu einem 
String zusammensetzen, ehe du dann atoi auf diesen String loslassen 
kannst, der dir aus dem String "255" die Zahl 255 generiert.

Und noch was:
Leg dir eine char Variable zurecht. Wenn du von der UART ein gültigfes 
Nutzbyte bekommst (erkennbar daran, dass dir die Fleury Lib im HighByte 
keinen Fehlercode oder kein 'No Data' mitteilt), dann extrahierst du dir 
das Zeichen in diese char Variable. Das ist doch Unsinn in weiterer 
Folge ständig mit diesem & 0x00FF weiter zu operieren.

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

Bewertung
0 lesenswert
nicht lesenswert
mcnanuk schrieb:

> oder eben irgendanders den Buffer resetten. Aber keinen Plan wie.
>
> Buffer[0] = '\0'; klappt nicht

Logisch.
Deiner Add Funktion ist es sowas von egal, wo das '\0' Zeichen ist. Die 
interessiert sich ausschliesslich dafür, welchen Inhalt LastCharInBuffer 
hat. Dort kommt das nächste Zeichen hin.


> Am liebsten würde ich den Buffer von Hinten befüllen. Das heisst
> alles mit 0 besetzen, und dann meine terminaleingaben rechtbündig
> eintragen.

Das willst du mit einiger Sicherheit nicht.
Denn das verkompliziert alles nur ohne das es dir etwas bringt.

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

Bewertung
0 lesenswert
nicht lesenswert
mcnanuk schrieb:

> Also wenn noch irgendwer nen Tipp hat,

Der wichtigste Tipp überhaupt:
Kauf dir ein C-Buch.

Bis du das hast, kannst du auch hier erst mal das wichtigste zur 
String-Verarbeitung in C nachlesen. Sozusagen die Kurzfassung mit nur 
den allerwichtigsten Sachen:
http://www.mikrocontroller.net/articles/FAQ#Wie_fu...

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.