Forum: Mikrocontroller und Digitale Elektronik Atmega644 UART - Komische Ausgabe


von mcnanuk (Gast)


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
1
/*************************************************************************
2
Title:    example program for the Interrupt controlled UART library
3
Author:   Peter Fleury <pfleury@gmx.ch>   http://jump.to/fleury
4
File:     $Id: test_uart.c,v 1.4 2005/07/10 11:46:30 Peter Exp $
5
Software: AVR-GCC 3.3
6
Hardware: any AVR with built-in UART, tested on AT90S8515 at 4 Mhz
7
8
DESCRIPTION:
9
          This example shows how to use the UART library uart.c
10
11
*************************************************************************/
12
#include <stdlib.h>
13
#include <avr/io.h>
14
#include <avr/interrupt.h>
15
#include <avr/signal.h>
16
#include <avr/pgmspace.h>
17
18
#include "uart.h"
19
20
21
/* define CPU frequency in Mhz here if not defined in Makefile */
22
23
#define F_CPU 3686000UL
24
25
26
/* 9600 baud */
27
#define UART_BAUD_RATE 14400 
28
29
30
int main(void)
31
{
32
    unsigned int c;
33
    char buffer[7];
34
    int  num=134;
35
36
      
37
38
    /*
39
     *  Initialize UART library, pass baudrate and AVR cpu clock
40
     *  with the macro 
41
     *  UART_BAUD_SELECT() (normal speed mode )
42
     *  or 
43
     *  UART_BAUD_SELECT_DOUBLE_SPEED() ( double speed mode)
44
     */
45
    uart_init( UART_BAUD_SELECT(UART_BAUD_RATE,F_CPU) ); 
46
  uart_puts("hallo" );  
47
    
48
    /*
49
     * now enable interrupt, since UART library is interrupt controlled
50
     */
51
    sei();
52
    
53
    /*
54
     *  Transmit string to UART
55
     *  The string is buffered by the uart library in a circular buffer
56
     *  and one character at a time is transmitted to the UART using interrupts.
57
     *  uart_puts() blocks if it can not write the whole string to the circular 
58
     *  buffer
59
     */
60
    uart_puts("String stored in SRAM\n");
61
    
62
    /*
63
     * Transmit string from program memory to UART
64
     */
65
    uart_puts_P("String stored in FLASH\n");
66
    
67
        
68
    /* 
69
     * Use standard avr-libc functions to convert numbers into string
70
     * before transmitting via UART
71
     */     
72
    itoa( num, buffer, 10);   // convert interger into string (decimal format)         
73
    uart_puts(buffer);        // and transmit string to UART
74
75
    
76
    /*
77
     * Transmit single character to UART
78
     */
79
    uart_putc('\r');
80
    
81
    for(;;)
82
    {
83
        /*
84
         * Get received character from ringbuffer
85
         * uart_getc() returns in the lower byte the received character and 
86
         * in the higher byte (bitmask) the last receive error
87
         * UART_NO_DATA is returned when no data is available.
88
         *
89
         */
90
        c = uart_getc();
91
        if ( c & UART_NO_DATA )
92
        {
93
            /* 
94
             * no data available from UART 
95
             */
96
        }
97
        else
98
        {
99
            /*
100
             * new data available from UART
101
             * check for Frame or Overrun error
102
             */
103
            if ( c & UART_FRAME_ERROR )
104
            {
105
                /* Framing Error detected, i.e no stop bit detected */
106
                uart_puts_P("UART Frame Error: ");
107
            }
108
            if ( c & UART_OVERRUN_ERROR )
109
            {
110
                /* 
111
                 * Overrun, a character already present in the UART UDR register was 
112
                 * not read by the interrupt handler before the next character arrived,
113
                 * one or more received characters have been dropped
114
                 */
115
                uart_puts_P("UART Overrun Error: ");
116
            }
117
            if ( c & UART_BUFFER_OVERFLOW )
118
            {
119
                /* 
120
                 * We are not reading the receive buffer fast enough,
121
                 * one or more received character have been dropped 
122
                 */
123
                uart_puts_P("Buffer overflow error: ");
124
            }
125
            /* 
126
             * send received character back
127
             */
128
            uart_putc( (unsigned char)c );
129
        }
130
    }
131
    
132
}

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.

von Sohn von Gosar (Gast)


Lesenswert?

welches Terminal Programm benutzt du? Hast du auch dort die selbe 
Baud-Rate eingestellt?

von Sohn von Gosar (Gast)


Lesenswert?

wo ist übrigens die uart_init() ?

von Magnetus (Gast)


Lesenswert?

Sohn von Gosar schrieb:
> wo ist übrigens die uart_init() ?

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

von g457 (Gast)


Lesenswert?


von Sohn von Gosar (Gast)


Lesenswert?

Magnetus schrieb:
> In "uart.h" natürlich  ;o)

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

von mcnanuk (Gast)


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...

von Peter D. (pdiener) Benutzerseite


Lesenswert?

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

Grüße,

Peter

von Sohn von Gosar (Gast)


Lesenswert?

handshaking richtig konfiguriert? den eventuellen Frequenzteiler auch 
berücksichtigt?

Hterm verwende ich auch meist, hatte nie Probleme damit

von Karl H. (kbuchegg)


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?

von Sohn von Gosar (Gast)


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...

von mcnanuk (Gast)


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

von Peter D. (pdiener) Benutzerseite


Lesenswert?

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

Grüße,

Peter

von mcnanuk (Gast)


Lesenswert?

Das heisst ich brauche unbedingt einen Quarz ?

von Sohn von Gosar (Gast)


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...

von Peter D. (pdiener) Benutzerseite


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

von mcnanuk (Gast)


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.

von mcnanuk (Gast)


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

von Peter D. (pdiener) Benutzerseite


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/STK500-HW-Beschreibung.pdf
Das Wichtige steht auf Seite 28.

Grüße,

Peter

von mcnanuk (Gast)


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.

von mcnanuk (Gast)


Lesenswert?

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

von mcnanuk (Gast)


Lesenswert?

Ich hab noch eine Folgefrage:
1
unsigned int uart_getc    (     void          )     
2
Get received byte from ringbuffer.
3
4
Returns in the lower byte the received character and in the higher byte the last receive error. 
5
UART_NO_DATA is returned when no data is available.
6
7
Parameters:
8
      void   
9
10
Returns:
11
    lower byte: received byte from ringbuffer
12
13
    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 :)

von Karl H. (kbuchegg)


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.

von mcnanuk (Gast)


Lesenswert?

1
  if((unsigned char)c < 100)
2
  {
3
     lcd_clrscr();
4
     lcd_puts("Kleiner 100 \n");
5
           lcd_putc((unsigned char)c);
6
  } else {
7
     lcd_clrscr();
8
     lcd_puts("Größer 100 \n");
9
     lcd_putc((unsigned char)c);
10
  }
11
//  lcd_putc( (unsigned char)c);
12
        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 ?

von Sohn von Gosar (Gast)


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...

von mcnanuk (Gast)


Lesenswert?

1
#include <stdlib.h>
2
#include <avr/io.h>
3
#include <avr/interrupt.h>
4
#include <avr/signal.h>
5
#include <avr/pgmspace.h>
6
#include "lcd.h"
7
#include "uart.h"
8
9
10
/* define CPU frequency in Mhz here if not defined in Makefile */
11
12
#define F_CPU 3686000UL
13
14
15
/* 9600 baud */
16
#define UART_BAUD_RATE      9600      
17
18
19
int main(void)
20
{
21
    unsigned int c;
22
    char buffer[7];
23
    int  num=134;
24
25
   //  lcd_init(LCD_DISP_ON);
26
27
    /*
28
     *  Initialize UART library, pass baudrate and AVR cpu clock
29
     *  with the macro 
30
     *  UART_BAUD_SELECT() (normal speed mode )
31
     *  or 
32
     *  UART_BAUD_SELECT_DOUBLE_SPEED() ( double speed mode)
33
     */
34
    uart_init( UART_BAUD_SELECT(UART_BAUD_RATE,F_CPU) ); 
35
36
    /*
37
     * now enable interrupt, since UART library is interrupt controlled
38
     */
39
    sei();
40
    
41
    /*
42
     *  Transmit string to UART
43
     *  The string is buffered by the uart library in a circular buffer
44
     *  and one character at a time is transmitted to the UART using interrupts.
45
     *  uart_puts() blocks if it can not write the whole string to the circular 
46
     *  buffer
47
     */
48
    uart_puts("String stored in SRAM\n");
49
    
50
    /*
51
     * Transmit string from program memory to UART
52
     */
53
    uart_puts_P("String stored in FLASH\n");
54
    
55
        
56
    /* 
57
     * Use standard avr-libc functions to convert numbers into string
58
     * before transmitting via UART
59
     */     
60
    itoa( num, buffer, 10);   // convert interger into string (decimal format)         
61
    uart_puts(buffer);        // and transmit string to UART
62
63
    
64
    /*
65
     * Transmit single character to UART
66
     */
67
    uart_putc('\r');
68
    
69
    for(;;)
70
    {
71
        /*
72
         * Get received character from ringbuffer
73
         * uart_getc() returns in the lower byte the received character and 
74
         * in the higher byte (bitmask) the last receive error
75
         * UART_NO_DATA is returned when no data is available.
76
         *
77
         */
78
        c = uart_getc();
79
        if ( c & UART_NO_DATA )
80
        {
81
            /* 
82
             * no data available from UART 
83
             */
84
        }
85
        else
86
        {
87
            /*
88
             * new data available from UART
89
             * check for Frame or Overrun error
90
             */
91
            if ( c & UART_FRAME_ERROR )
92
            {
93
                /* Framing Error detected, i.e no stop bit detected */
94
                uart_puts_P("UART Frame Error: ");
95
            }
96
            if ( c & UART_OVERRUN_ERROR )
97
            {
98
                /* 
99
                 * Overrun, a character already present in the UART UDR register was 
100
                 * not read by the interrupt handler before the next character arrived,
101
                 * one or more received characters have been dropped
102
                 */
103
                uart_puts_P("UART Overrun Error: ");
104
            }
105
            if ( c & UART_BUFFER_OVERFLOW )
106
            {
107
                /* 
108
                 * We are not reading the receive buffer fast enough,
109
                 * one or more received character have been dropped 
110
                 */
111
                uart_puts_P("Buffer overflow error: ");
112
            }
113
            /* 
114
             * send received character back
115
             */
116
117
       /*
118
      
119
120
121
      switch (c)  {
122
123
            case '1':
124
                lcd_clrscr();
125
      lcd_puts("Ha \n");
126
                break;
127
128
            case '2':
129
               lcd_clrscr();
130
      lcd_puts("Hu \n");
131
                break;
132
           } */      
133
134
135
      if(c < 100)
136
      {
137
         lcd_clrscr();
138
         lcd_puts("Kleiner 100 \n");
139
               lcd_putc((unsigned char)c);
140
      } else {
141
         lcd_clrscr();
142
         lcd_puts("Größer 100 \n");
143
         lcd_putc((unsigned char)c);
144
      }
145
      
146
      lcd_putc( (unsigned char)c);
147
            uart_putc( (unsigned char)c );
148
        }
149
    }
150
    
151
}

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.

von holger (Gast)


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.

von Hc Z. (mizch)


Lesenswert?

1
    /*
2
     * Transmit string from program memory to UART
3
     */
4
    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.

von mcnanuk (Gast)


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.

von Peter D. (pdiener) Benutzerseite


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:
1
if( (c & 0x00ff) < 100 )  // ist das Zeichen ein ASCII-Code kleiner 100?
2
      {
3
         lcd_clrscr();
4
// usw...

Grüße,

Peter

von (prx) A. K. (prx)


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.

von mcnanuk (Gast)


Lesenswert?

Danke Peter,

leider bringt das auch keine Besserung...
1
if((c & 0x00ff) < 100)
2
      {
3
         lcd_clrscr();
4
         lcd_puts("Kleiner 100 \n");
5
     uart_puts(itoa((c & 0x00ff),buffer,10));
6
         lcd_puts(itoa((c & 0x00ff),buffer,10));
7
      } else {
8
         lcd_clrscr();
9
         lcd_puts("Größer 100 \n");
10
     uart_puts(itoa((c & 0x00ff),buffer,10));
11
         lcd_puts(itoa((c & 0x00ff),buffer,10));
12
      }

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.
1
#include <avr/io.h>
2
#include <stdio.h>
3
#include <string.h>
4
#include <util/delay.h>
5
#include <avr/interrupt.h>
6
#include "lcd.h"
7
8
9
int Flughoehe;
10
char buffer[7];
11
char Buffer[7];
12
char usartString[] = "";
13
14
// Sendet ein einzelnes Zeichen
15
void uart_putc( char c )
16
{
17
  // Warte bis die Sendeeinheit bereit ist
18
  while( !(UCSR0A & ( 1<<UDRIE0) ) )
19
    ;
20
  UDR0 = c;
21
}
22
23
// Sende einen C-String
24
void uart_puts( const char* str )
25
{
26
  while( *str ) {
27
    uart_putc( *str );
28
    str++;
29
  }
30
}
31
32
// Ausgabe mit printf über USART
33
static int uart_putchar(char c, FILE *stream);
34
static FILE mystdout = FDEV_SETUP_STREAM(uart_putchar, NULL,
35
                                            _FDEV_SETUP_WRITE);
36
37
static int
38
    uart_putchar(char c, FILE *stream)
39
    {
40
41
      if (c == '\n')
42
        uart_putchar('\r', stream);
43
      loop_until_bit_is_set(UCSR0A, UDRIE0);
44
      UDR0 = c;
45
      return 0;
46
    }
47
48
unsigned char USART_RX(void)
49
{
50
  while(!(UCSR0A&(1<<RXC0)))
51
    ;
52
  return UDR0;
53
}
54
55
void uart_gets( int* Input )
56
{
57
  char c = USART_RX();
58
  uart_putc( c );
59
  
60
  while( c != '\n' )
61
  {
62
    *Input = c;
63
    Input++;
64
    c = USART_RX();
65
    uart_putc( c );
66
  }
67
  *Input = '\0';
68
}
69
70
71
void uart_init(void)
72
{
73
  // Baudrate setzen
74
  UBRR0H = 0x00;  //0000 0000
75
  UBRR0L = 0x17;  // Wert 23 ^= 9600 bei 3,686 MHz
76
77
  // Empfänger und Sender aktivieren
78
  UCSR0A = 0x00;   //0000 0000
79
  UCSR0B = 0x18;  //0001 1000  
80
81
  /* Einstellungen: Asynchron, 8-Bit, keine Parität, 1 Stop bit */
82
  UCSR0C = 0x06;   //0000 0110
83
}
84
85
86
int main(void)
87
{
88
89
  // USART initialisieren
90
  uart_init();
91
  lcd_init(LCD_DISP_ON);
92
   sei();
93
94
  while(1)  // forever
95
  {
96
  
97
    uart_gets(Buffer);
98
99
    uart_puts( "Ihre Eingabe: " );
100
    uart_puts( Buffer );
101
    uart_putc( '\n' );
102
103
104
     usartString[0] = '\0';
105
106
     for (int i=0; i<7; i++) 
107
     { 
108
      Flughoehe = atoi(&Buffer[i]);
109
110
      if(Buffer[i] != 'x' )
111
      {
112
      
113
        strcat(usartString, itoa(Flughoehe, buffer, 10));    //Ergebnisstring basteln
114
      }else{
115
        break;
116
      }
117
    
118
     } 
119
     lcd_clrscr();
120
     lcd_puts(usartString); 
121
122
    
123
    uart_puts("Wert: ");
124
    uart_puts(usartString);
125
    uart_putc( '\n' );
126
127
    
128
    stdout = &mystdout;
129
    
130
131
132
  // Ende vom while
133
  }
134
// Ende der main
135
}

von Stefan E. (sternst)


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.

von mcnanuk (Gast)


Lesenswert?

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

1
  lcd_clrscr();
2
    uart_putc((c & 0x00ff));
3
  
4
    Add((c & 0x00ff));
5
        lcd_puts(Buffer);
6
    lcd_puts("\n");
7
    
8
    
9
    
10
  if(atoi(Buffer)< 100)
11
    {
12
  lcd_clrscr();
13
     lcd_puts("Kleiner 100");
14
    } else {
15
  lcd_clrscr();
16
        lcd_puts("Bigger 100");
17
    }

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.

von Sohn von Gosar (Gast)


Lesenswert?

poste mal die atoi() funktion

von mcnanuk (Gast)


Lesenswert?

http://www.cplusplus.com/reference/clibrary/cstdlib/atoi/

ist eine Bibliotheksfunktion... umkehrung von itoa

von mcnanuk (Gast)


Lesenswert?

1
uart_putc((c & 0x00ff));
2
  
3
    Add((c & 0x00ff));
4
5
    
6
    
7
    
8
  if(atoi(Buffer)< 100)
9
    {
10
  lcd_clrscr();
11
  lcd_puts(Buffer);
12
    lcd_puts("\n");
13
     lcd_puts("Kleiner 100");
14
    } else {
15
  lcd_clrscr();
16
  lcd_puts(Buffer);
17
    lcd_puts("\n");
18
        lcd_puts("Bigger 100");
19
    }

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

von Karl H. (kbuchegg)


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
1
if((c & 0x00ff) < 100)
2
      {
3
         lcd_clrscr();
4
         lcd_puts("Kleiner 100 \n");
5
     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.

von Karl H. (kbuchegg)


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.

von Karl H. (kbuchegg)


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_funktioniert_String-Verarbeitung_in_C.3F

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.