Forum: Mikrocontroller und Digitale Elektronik Ausgabe von Datentyp float fehlerhaft!


von Stephen (Gast)


Lesenswert?

Grüße,

ich habe ein kleines Problem mit der Ausgabe von Float-Werten.

Kurze Einleitung.
Ich habe eine Funktion die eine AD-Wandler Initialisiert:
1
/*** Initialisierung der Grundeinstellungen des AD-Wandlers **/
2
void AD_init(unsigned int Kanaele)
3
{  
4
  ADCF = Kanaele;            // Auswahl von Kanal X als analoger Eingangsport des AD-Wandlers
5
}
6
/************** Wandlung von Kanal des AD-Wandlers ************/
7
float AD_wandel(unsigned int Kanal)
8
{
9
  unsigned int ergebnis;        // Den Digitalwert nach Wandlung in Integer deklarieren
10
  float spg10;            // Variable in float deklarieren für die gemessene Spannung
11
  ADCON = 0x20;            // AD-Wandler einschalten
12
  ADCON = ADCON | Kanal;        // AD-Wandler aktivieren
13
  ADCON = ADCON | 0x08;        // Wandlung wird gestartet da Startbit ADDST auf 1 gesetzt ist
14
     while(!(ADCON & 0x10));       // Abfrage von Fertig-Bit: ADEOC; Warten bis Wandlung fertig
15
     ADCON = ADCON & 0xef;        // Fertig-Bit ADEOC löschen; ADEOC wird zurückgesetzt
16
     ergebnis = (ADDH<<2)+ADDL;      // Einlesen des 8Bit-Wertes aus dem Register ADDH; Verschiebung um 2Bits nach Links; Zuweisung an ergebnis  als Dezizahl
17
  spg10 = (2.50/1023.0)*ergebnis;  // Berechnet die Spannung aus Referenzspannung durch 10Bit mal Ergebnis des AD_Wandlers
18
  printf("%1.2f",spg10);
19
  return spg10;          // Rückgabe des Wertes an das Hauptprogramm
20
}
21
/*******************************************************************************************/

Dieser liefert mit ein Float-Wert zurück.

Dieser Wert habe ich nun in eine Globalen Float Variablen schreiben 
lassen.
1
SPG = AD_wandel(0x27);           //Speicherung in die Variable SPG (für Spannung) den Wert des AD-Wandlers(nach dem Wandeln)

Und will diesen Wert mit printf(""); ausgaben.

Dieses habe ich wie folgt gelöst
1
printf("Messwert: %1.2f V",SPG);

wenn ich jetzt dieses Programm mit in dem Hilfsprogramm "PuTTy" anschaue 
steht folgendes da:

Messwert: ?? V

jetzt zu meiner Frage. Warum kann ich keine Floatwerte mehr Ausgaben?


hier nochmal der Komplette Quelltext meines eigentlichen Programms.
1
/***********************************************************/
2
/* Autor: Stephen *********************************/
3
/* Programmname: MESSDATENSPEICHER *************************/                         
4
/* Erstelldatum: 16.09.2014 ********************************/
5
/* Berufsfeld: SYI / EIS ***********************************/
6
/* Lehrjahr: 4 *********************************************/                         
7
/* Geändert am: 16.09.2014 *********************************/                            
8
/* Geändert von: Stephen **************************/ 
9
/***********************************************************/
10
11
/*** Einbinden der Include und Define Dateien **************/                   
12
#include <stdio.h>        //einbinden der standart I/O
13
#include <at89c51cc03.h>    // Special-Function-Register
14
#include <absacc.h>        //einbinden der include datei
15
16
17
/***********************************************************/
18
19
/***********************************************************/   
20
/*** deklaration der globalen variabeln ********************/                            
21
/***********************************************************/
22
float SPG;
23
far float var[8100];
24
25
/***********************************************************/
26
27
/***********************************************************/
28
/*  Initialisierung seriellen Schnittstelle des CC03ers:   */
29
/*  9.600 Bd, 8 Datenbits, 1 Stopp-Bit, keine Parität      */                                                                           
30
/***********************************************************/                            
31
void init_seri(void)
32
{
33
    SCON=0x52;
34
    TMOD |=0x20;
35
    TH1=0xfd;
36
    TR1=1;
37
    TI=1;
38
}
39
/*************************************************************/
40
/*************************************************************/
41
42
/*** selbst erzeugte Wartezeit *************************************************************/                            
43
void _wait_ms(unsigned int multiplikator)
44
{
45
  unsigned int i,j;
46
  for(i=0;i<multiplikator;i++)  //Zählschleife
47
  {
48
    for(j=0;j<123;j++);       //verschachtelte Zählschleife
49
  }
50
}
51
52
53
/*******************************************************************************************/                 
54
/*** Funktionen für PuTTy ******************************************************************/                            
55
/*******************************************************************************************/   
56
/*** Bildschirm löschen PuTTy **************************************************************/
57
void clear_screen (void)
58
{
59
  printf( "\x1b[H\x1b[0J\x1b[H");                      
60
}
61
62
/*** Cursor setzen PuTTy *******************************************************************/
63
void cursor_set (unsigned int z, unsigned int s)
64
{
65
  printf("\x1b[%d;%dH", z,s);   
66
}
67
/*******************************************************************************************/
68
69
/*** Initialisierung der Grundeinstellungen des AD-Wandlers **/
70
void AD_init(unsigned int Kanaele)
71
{  
72
  ADCF = Kanaele;            // Auswahl von Kanal X als analoger Eingangsport des AD-Wandlers
73
}
74
/************** Wandlung von Kanal des AD-Wandlers ************/
75
float AD_wandel(unsigned int Kanal)
76
{
77
  unsigned int ergebnis;        // Den Digitalwert nach Wandlung in Integer deklarieren
78
  float spg10;            // Variable in float deklarieren für die gemessene Spannung
79
  ADCON = 0x20;            // AD-Wandler einschalten
80
  ADCON = ADCON | Kanal;        // AD-Wandler aktivieren
81
  ADCON = ADCON | 0x08;        // Wandlung wird gestartet da Startbit ADDST auf 1 gesetzt ist
82
     while(!(ADCON & 0x10));       // Abfrage von Fertig-Bit: ADEOC; Warten bis Wandlung fertig
83
     ADCON = ADCON & 0xef;        // Fertig-Bit ADEOC löschen; ADEOC wird zurückgesetzt
84
     ergebnis = (ADDH<<2)+ADDL;      // Einlesen des 8Bit-Wertes aus dem Register ADDH; Verschiebung um 2Bits nach Links; Zuweisung an ergebnis  als Dezizahl
85
  spg10 = (2.50/1023.0)*ergebnis;  // Berechnet die Spannung aus Referenzspannung durch 10Bit mal Ergebnis des AD_Wandlers
86
  printf("%1.2f",spg10);
87
  return spg10;          // Rückgabe des Wertes an das Hauptprogramm
88
}
89
/*******************************************************************************************/
90
91
void main (void)
92
{
93
  int i, Bereich_min, Bereich_max;
94
  init_seri();
95
  clear_screen();
96
  AD_init(0x80);                            //Initalisierung des AD-Wandlers auf den Kanal 7
97
  while(1)
98
  {
99
    printf("##################################  \n");  
100
    printf("##  ####    ####    ##    ##    ##  \n");
101
    printf("##  ##  ## ##  ##  ####  ####   ##  \n");
102
    printf("##  ##  ## ##  ## ##   ##   ##  ##  \n");
103
    printf("##  ####   ###### ##   ##   ##  ##  \n");
104
    printf("##  ##  ## ##  ## ##   ##   ##  ##  \n");
105
    printf("##  ##  ## ##  ## ##   ##   ##  ##  \n");
106
    printf("##  ##  ## ##  ## ##   ##   ##  ##  \n");  
107
    printf("##################################  \n");
108
    printf("Programm erstellt von\n");
109
    printf("\nSysteminformatiker 4. Lehrjahr");
110
    printf("\nVersion 0.1\n");
111
    printf("##################################  \n");
112
  
113
    
114
      printf("\n*Willkommen zur Messdatenspeicherung*\n");
115
      printf("\n Bitte geben Sie folgdene Daten ein:");
116
      printf("\n Welchen Speicherbereich wollen Sie verwenden? (0 - 8100)");
117
      printf("\n VON: ");
118
      scanf("%d",&Bereich_min);
119
      printf(" BIS: ");
120
      scanf("%d",&Bereich_max);
121
      while(Bereich_max < Bereich_min)
122
      {
123
        if(Bereich_max < Bereich_min)
124
        {
125
          printf("\n Der Bereich BIS, muss groesser sein als VON.");
126
          printf("\n Welchen Speicherbereich wollen Sie verwenden? (0 - 8100)");
127
          printf("\n VON: ");
128
          scanf("%d",&Bereich_min);
129
          printf(" BIS: ");
130
          scanf("%d",&Bereich_max);  
131
        }
132
      }
133
      for(i = Bereich_min; i<=Bereich_max; i++)
134
      {
135
        SPG = AD_wandel(0x27);           //Speicherung in die Variable SPG (für Spannung) den Wert des AD-Wandlers(nach dem Wandeln)
136
        var[i] = SPG;
137
        printf("\n gespeicherter Wert: %d",var[i]);
138
        printf("\n Wert der AD-Funktion %1.2f V",SPG);
139
        printf("\n Messwert im RAM %1.2f V",var[i]);
140
      }
141
      printf("\n##################################\n");
142
      printf("\n Messung beendet...");
143
      _wait_ms(3000);
144
      clear_screen();
145
  }
146
  
147
}

von Jim M. (turboj)


Lesenswert?

"-lm" beim Linken vergessen?

von Daniel H. (Firma: keine) (commander)


Lesenswert?

Stephen schrieb:
> printf("%1.2f",spg10);

Du reservierst also ein Zeichen für die Ausgabe und reservierst von 
diesem einen Zeichen zwei für die Nachkommastelle (+ eins für den 
Kommapunkt). Das passt irgendwie nicht.

Versuch mal
1
printf("%3.2f",spg10);
2
// oder
3
printf("%.2f",spg10);

Ansonsten könnte es auch sein, dass du eine Nicht-Floating-Pointversion 
der printf-Bibliothek verwendest:

http://www.mikrocontroller.net/articles/FAQ#Aktivieren_der_Floating_Point_Version_von_sprintf_bei_WinAVR_bzw_AVR-Studio

von (prx) A. K. (prx)


Lesenswert?

Jim Meba schrieb:
> "-lm" beim Linken vergessen?

Zunächst mal hat er den Compiler vergessen. Ohne den gehts nicht.
Den Prozessor hat er genannt, wenngleich als Suchspiel: at89c51cc03

: Bearbeitet durch User
von Stephen (Gast)


Angehängte Dateien:

Lesenswert?

Hallo danke für die schnelle Antwort.

@Jim das mit dem Linken hat nichts damit direkt zu tun weil andere 
Programme die auch mit der Keil Entwicklungsumgebung programmiert worden 
sind funktionierten einwandfrei.

@Daniel leider funktioniert diese Varianten auch nicht.

@ A. K. was meinst du direkt mit Compiler

PS:
habe mal ein Bild hinzugefügt wie es in Putty aussieht.

Grüße

von Karl H. (kbuchegg)


Lesenswert?

Stephen schrieb:
> Hallo danke für die schnelle Antwort.
>
> @Jim das mit dem Linken hat nichts damit direkt zu tun

Doch. Es hat (auch wenn ich Keil nicht kenne) ziemlich sicher mit dem 
Linken zu tun.

Der Punkt ist, dass Floating Point Dinge recht aufwändig sind und viel 
Speicher verbrauchen. Daher möchte man in 'normale' Programme die ganze 
Floating Point Library nicht mit drinnen haben, wenn es nicht unbedingt 
seinmuss. Konsequenterweise gibt es dann auch eine Version von printf, 
die mit double nicht umgehen kann.
Will man aber unbedingt die Floating Point Version haben, dann muss man 
das beim Linken explizit angeben. Wie das beim Keil funktioniert, steht 
in der Doku zum Compiler/Linker

von Marc V. (Firma: Vescomp) (logarithmus)


Lesenswert?

Stephen schrieb:
> @Jim das mit dem Linken hat nichts damit direkt zu tun weil andere
> Programme die auch mit der Keil Entwicklungsumgebung programmiert worden
> sind funktionierten einwandfrei.

 Vielleicht mal SPG casten (integer) und zusätzlich ausgeben ?

von Stephen (Gast)


Lesenswert?

@Karl Danke für die Hilfe und anscheind hattest du doch recht gehabt. da 
ich "far" verwende musste ich den Extended Linker aktivieren. Ich werde 
mal versuchen direkt die LIB für Float einzubinden.

@Marc Wenn dich die Funktion des AD-Wandlers einwenig umschreibe und mir 
als Rückgabewert ein INT zurück liefern lassen funktioniert alles 
wunderbar, außer das ich halt statts Float dann INT verwende.

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.