Forum: Compiler & IDEs dtostrf- Problem


von Kunki_86 (Gast)


Lesenswert?

allo Zusammen,

ich habe vor kurzem angefangen mein Atmel in C zu programmieren (vorher
immer in Basic). Nun habe ich ein Problem und weiß nicht wo mein
Denkfehler oder Leichtsinnsfehler liegt. Ich möchte eine Kommazahl über
ein Uart senden. Ich verwende die dtostrf- Funktion. Leider geht das
aber nicht. Mein Terminalprogramm empfängt jediglich nur ein "H".
Wär echt klasse, wenn ihr mir helfen könntet.
Mein Code:

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


#define SYSCLK    8000000L
#define BAUD    9600L
#define UBRR_BAUD  ((SYSCLK/(16*BAUD))-1)

/* INT Deklarationen */
int init(void);
int uart_out(char sende_daten[8]);


int main()
{

     char s[8];
     float f = -12.345;

        init();

     dtostrf( f, 6, 3, s );

  while (1)
  {
  _delay_ms(1000);

  uart_out(s);

  }

}


int uart_out(char sende_daten[8])

{

  while (!(UCSRA & (1<<UDRE)));
        UDR = sende_daten;
  return(0);

}



int init(void)
{
  /* Baudrate einstellen ( Normaler Modus ) */
  UBRRH =  (unsigned char)(UBRR_BAUD>>8);
  UBRRL = (unsigned char)UBRR_BAUD;

  UCSRB = (1<<RXCIE)|(1<<RXEN)|(1<<TXEN);

  /* Einstellen des Datenformats: 8 Datenbits, 1 Stoppbit */
  UCSRC = (1<<URSEL)|(1<<UCSZ1)|(1<<UCSZ0);

  return(0);
}

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Du machst einen großen und einen kleinen Fehler.

Erst einmal der kleine Fehler: 1000 ms lassen sich mit _delay_ms() bei
gewöhnlichem AVR-Takt nicht erreichen.  10 ms ist ein sicherer Wert,
der selbst bei den derzeit schnellsten AVRs (20 MHz) immer
funktioniert.  Normalerweise nimmt man für lange Verzögerungen ja
sowieso einen Timer, für den einfachen Test kannst du die Funktion ja
100mal aufrufen.

Der große Fehler: du willst einen String ausgeben, gibst aber nur das
niedrige Byte der Adresse des Strings (die in "sende_daten" steht)
aus.  Bau die Funktion so um:
1
static void
2
uart_out_char(char c)
3
{
4
  while (!(UCSRA & (1<<UDRE)));
5
        UDR = c;
6
}
7
8
int uart_out(char *sende_daten)
9
{
10
  char c;
11
12
  while ((c = *sende_daten++) != '\0')
13
    uart_out_char(c);
14
15
  // Vielleicht willst du ja das hier noch?
16
  uart_out_char('\r');
17
  uart_out_char('\n');
18
19
  return 0;
20
}

von Kunki_86 (Gast)


Lesenswert?

Hallo,
danke für Deine Antwort. Jedoch gehts bei mir irgendwie immer noch
nicht. Wär genial, wenn mir nochmal helfen könntest. Ich zweifel grad
echt an meiner Intelligenz:). Vielleicht könntest Du den Code
verbessern. Weil bei mir kommt nämlich gar nichts.


/* INT Deklarationen */
int init(void);
static void uart_out_char(char c);
int uart_out(char *sende_daten);

int main()
{
    char s;
    float f = -12.345;

    init();

    dtostrf( f, 6, 3, s );

  while(1)
  {
  _delay_ms(10);

  uart_out(s);
  }
}

int uart_out(char *sende_daten)

{

  char c;
  while ((c = *sende_daten++) != '\0')
  uart_out_char(c);
  return 0;

}

static void uart_out_char(char c)
{
  while (!(UCSRA & (1<<UDRE)));
  UDR = c;
}

von johnny.m (Gast)


Lesenswert?

Wenn Du einen float in einen Character-String umwandeln willst, dann
musst Du für den String auch ausreichend Speicherplatz zur Verfügung
stellen. "c" ist aber nur ein einfacher char, da passt nur eine
einzige Stelle (ASCII-Zeichen) rein. Du brauchst aber 7 Stellen (6
Stellen für die Zahl an sich, wenn Du als "width" 6 angibst und ein
Zeichen für den Nullterminator). Dazu muss c mindestens als Array mit 7
Elementen deklariert werden, also "char s[7];". Allerdings hat die im
Beispiel angegebene Zahl "-12.345" bereits 7 Stellen, da sich der
Parameter "width" auf die Gesamtlänge der Ausgabe bezieht, also auf
alle Ziffern zzgl. Dezimalpunkt und Vorzeichen. Du wirst diese Zahl
also so nicht darstellen können. Da muss also ein Array mit 8 Elementen
her, also "char s[8];". Damit sollte es funktionieren.

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.