Lieber Besucher, herzlich willkommen bei: RCLine Forum. Falls dies Ihr erster Besuch auf dieser Seite ist, lesen Sie sich bitte die Hilfe durch. Dort wird Ihnen die Bedienung dieser Seite näher erläutert. Darüber hinaus sollten Sie sich registrieren, um alle Funktionen dieser Seite nutzen zu können. Benutzen Sie das Registrierungsformular, um sich zu registrieren oder informieren Sie sich ausführlich über den Registrierungsvorgang. Falls Sie sich bereits zu einem früheren Zeitpunkt registriert haben, können Sie sich hier anmelden.

1

Freitag, 3. März 2006, 22:32

Formatierte Zahlenausgabe

Hallo an alle

Ich hab nun eine A/D Routine geschrieben.

Quellcode

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
#include <avr/io.h>
#include <stdlib.h>
#include "wintek2704.h"

void adc_init(void);
int get_adc (void);
void lcd_put_d(uint16_t dec);

int main (void)
{
	DDRC &=~ _BV(PC0);
	PINC &=~ _BV(PC0);
	
	uint8_t balken3, balken_leer, i, j;
	uint16_t ergebnis_display;
	uint16_t ergebnis_neu;
		
	adc_init();
	lcd_init(LCD_DISP_ON);
	lcd_puts("        ADC -- Test\n");
	ergebnis_neu = 0;
	
	while(1)
	{
		ergebnis_display = get_adc();
		
		if (ergebnis_neu > ergebnis_display || ergebnis_neu < ergebnis_display)
		{
		lcd_gotoxy(0,1);
		lcd_puts("    ");
		ergebnis_neu = ergebnis_display;
		}
		lcd_gotoxy(0,1);
		lcd_put_d(ergebnis_neu);
		
		balken3 = ergebnis_neu / 37;
		balken_leer = 27 - balken3;
		
		lcd_gotoxy(0,2);
		
		for(i = 0; i < balken3; i++)
			lcd_puts("=");
		for(j = 27; j > balken_leer; j--)
		lcd_puts(" ");
	}
	return(0);
}

void lcd_put_d(uint16_t dec)
{
	char buffer[6];
	itoa(dec, buffer, 10);
	lcd_puts(buffer);
}

	

void adc_init (void)
{
	ADCSR = (1 << ADEN) | (1 << ADPS1) | (1 << ADPS2);	//Prescaler = 64 TF = 125 kHz 
}

int get_adc (void)
{
	uint8_t i;
	uint16_t ergebnis_adc;
	
	ADMUX = 0; // Vreff = Vcc
	
	ADCSRA |= (1 << ADSC);
	
	while (!(ADCSRA & (1 << ADIF)));
	
	ergebnis_adc = 0;
	
	for(i = 0; i < 5; i++)
	{
		ADCSRA |= (1 << ADSC);
		while(!(ADCSRA & (1 << ADIF)));
		
		ergebnis_adc += ADC;
	}
	ergebnis_adc = ergebnis_adc / 5;
	
	return ergebnis_adc;
}


Jedoch überschreibe ich jetzt immer die Zahl vor der Aktualisierung mit 4 leerzeicnen (lcd_puts" "). Denn Wenn ich eine Zahl > 1000 anzeige, bleibt die letzte Stelle hängen wenn der Wert unter 1000 sinkt. Das gleiche bei 100. Deshalb die Überschreibung mit den Leerzeichen.

Gibt es in C ein Möglichkeit die Zahlen formatiert auszugeben zB 0125, 0058, 1024???

In BASCOM gibt es ja die Funktion FUSING. Gibt es sowas auch in C???

Danke im Voraus ;)

Gruß Robert
Gruß Robert

2

Freitag, 3. März 2006, 23:52

Hallo Robert,

ist schon ewig her, als ich in 'C' was gemacht habe, aber war das nicht sowas wie

Quellcode

1
printf("%.4f\n",123.123456); // Ausgabe 123.1234


Ich kann mich nur noch entfernt an das "%" erinnern und daß dann danach die Anzahl der Stellen angegeben wurde. Gab da auch was mit führenden Nullen.

Sorry, aber vielleicht hilft Dir das beim googeln ... genauer kriege ich es aus dem Gedächtnis nicht hin.

Gruß.
Rainer
Dieser Beitrag wurde schon 6322 mal editiert, zum letzten mal von Gwydion am 20.02.2007 00:00.

3

Samstag, 4. März 2006, 00:02

Hallo Rainer

Das kenne ich naürlich schon. Leider isr das aber auf die printf() Funktion bezogen. Ich möchte zB den Wert der Variable ergebnis_adc zB 125 in 0125 formatieren oder 55 in 0055.

Gruß Robert
Gruß Robert

Bubu3422

RCLine Neu User

Wohnort: D-71063 Sindelfingen

Beruf: Software-Entwickler

  • Nachricht senden

4

Samstag, 4. März 2006, 16:00

Hallo Robert,

wie waere es mit einer neuen Funktion, die ....
a) die Funktion itoa oder ltoa aus der avr-libc benutzt
b) den String nach rechts schiebt und vorne mit 0x30 auffuellt?

Die Doku zu den Funktionen ist unter http://www.nongnu.org/avr-libc/user-manu…vr__stdlib.html finden.

Gruss, Uwe.
Wie sagten schon die alten Engländer:
My home and my castle. Oder so ähnlich, ... . :-)

5

Samstag, 4. März 2006, 16:40

Am einfachsten wären natürlich printf() oder die schwester sprintf()
(Wenn man vier blanks statt tab bimmt, kann man die Formatierung noch sehen)

Quellcode

1
2
3
4
5
6
void lcd_put_d(uint16_t dec)
{
    char buffer[6];
    sprintf( buffer, "%5d", dec ); // oder mit führenden nullen: sprintf( buffer, "%05d", dec );
    lcd_puts( buffer );
}

Ansonsten bsp so:

Quellcode

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
void lcd_put_d(uint16_t dec)
{
    char buffer[6];
    uint16_t teiler = 10000;
    uint8_t i;
    for( i = 0; i < 5; i++ ) {
        uint8_t stelle = dec/teiler;
        if( stelle ) {
            buffer[i] = stelle + '0';
            dec -= stelle * teiler;
        } else {
            buffer[i] = '0';
        }
        teiler /= 10;
    }
    buffer[i] = '\0';
    lcd_puts( buffer );
}


Ist vermutlich die kleinste und schnellste Lösung. Hat aber führende Nullen. Die noch wegzubekommen oder wegzulassen sollte aber kein Problem sein, oder?


Grüße
Malte

Dieser Beitrag wurde bereits 7 mal editiert, zuletzt von »DrM« (4. März 2006, 18:53)


6

Samstag, 4. März 2006, 17:52

Hallo Malte

sprintf() ist natürlich super geht aber mit den Recourcen verschwenderisch um :(

Danke für dein Codeschnipsel :ok:

Was meinst du mit meiner Variablendeklaration??

Was hast du gemacht, damit bei deinem Code die Einrückungen vorhanden sind?

Gruß Robert
Gruß Robert

Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von »Robert« (4. März 2006, 17:54)


7

Samstag, 4. März 2006, 18:04

...Wenn man vier blanks statt tab bimmt, kann man die Formatierung noch sehen ;)

Jo, sprintf kostet natürlich Zeit und ~2k Speicher. Solange man damit keine Probleme hat, kann man es ja benutzen.

Habe gerade geschaut. Anscheinend ist inzwischen auch in C die "späte" Variablendeklaration erlaubt...

Grüße
Malte

Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von »DrM« (4. März 2006, 18:53)


8

Dienstag, 21. März 2006, 21:37

Zitat

Habe gerade geschaut. Anscheinend ist inzwischen auch in C die "späte" Variablendeklaration erlaubt...

Leute, lasst die Finger davon. Macht ein Programm absolut unleserlich und unpflegbar. Variablen am besten immer gleich am Anfang einer Funktion rein.

Ausnahme: Variablen die in einem Block lokal sind.
Also z.B.

Quellcode

1
2
3
4
5
6
7
if(irgendwas)
{
   int einelokalevariable;
   char nocheinelokalevariable[10];

   tu was...
}


sprintf geht leider wirklich verschwenderisch mit dem Speicher um. Eine auf den jeweiligen Fall zugeschnittene Funktion ist da immer sparsammer als so eine Eierlegendewollmilchsau.
Gruss
Thomas
🖖

Vielleicht ist Wissen doch nicht die Antwort auf alles

9

Mittwoch, 22. März 2006, 14:54

Einspruch! Das kann man so nicht sagen. Schlechter Stil, schlechte Namen und unendlich lange Funktionen machen den Code unleserlich.
Wozu soll ich eine lokale Variable ganz oben in einer Funktion definieren, wenn ich sie erst zwei Zeilen vor Ende der Funktion brauche? Früher musste man genau für soetwas einen "nackten" Block basteln, das war erst recht häßlich.
Bjarne wird sich etwas dabei gedacht haben, als er das für C++ eingeführt hat und die C-Gurus, als sie es dann für C übernommen haben.

Schwachsinniges Beispiel, das aber vllt. zeigt, was ich meine:

Quellcode

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
int berechne_unsinn( int a, int b )
{
    if( !b  ) // *)
        return 0;

    if( !a  )
        return 1;

    int resultat = a * b;

    if( resultat < 10 )
        return 2;

    return resultat;
}

Wozu hier das Resultat anlegen, wenn man noch gar nicht darüber nachdenkt, überhaupt eins zu berechnen?

Weiterer Punkt: Wenn Du eine Variable nicht nur deklarierst, sondern Ihr auch gleich einen Wert mitgibst, z.B. das Ergebnis eines Funktionsaufrufes, dann hast Du schon eine Mischung aus "aktivem" Code und Deklaration.

Quellcode

1
2
3
4
5
6
int a = Temperatur();
int b = Sonnenstand();
// oder soll das so geschrieben werden?
int a, b;
a = Temperatur();
b = Sonnenstand();

Wir sind doch nicht mehr bei Pascal!


Grüße
Malte
*) ich hatte statt 'if( !b )' aus Rücksicht auf die Anfänger zuerst 'if( b == 0 )' geschrieben, halte das aber für falsch, schließlich ist es C.
Muß auch jedesmal meckern, wenn einer meiner Kollegen 'if( bedingung == TRUE )' schreibt. Es heißt 'if( bedingung )'. sonst könnte man auch 'if( ( ( ( bedingung == TRUE ) == TRUE ) == TRUE.... )' schreiben!

Dieser Beitrag wurde bereits 7 mal editiert, zuletzt von »DrM« (22. März 2006, 15:13)


10

Mittwoch, 22. März 2006, 21:20

Ausnahmen bestaetigen die Regel.

Aber zu deinem zweiten Beispiel:

In einem kleinen Programm was evtl. nie wieder veraendert wird, stimme ich dir zu. Bei einem groesseren Programm was lebt kann so ein Code ganz schoen stoerend bei der Pflege sein. Ein paar der "alten" Ideen sind naemlich gar nicht so schlecht. Insb. wenn es um groessere "lebende" Funktionen geht.
Eine klare Aufteilung in Definition, Initialisierung und Verwendung von Variablen wird naemlich auch wunderbar duch Compiler unterstuetzt.
Wirfst du naemlich Verwendung und Initialisierung raus, warnt dich gleich der Compiler vor ungenutzten Variablen.
Initialisierst du gleich bei der Definition, merkst du nichts davon. Und produzierst noch dazu wie in deinem Beispiel durch die Funktionsaufrufe einen Overhead der nicht noetig ist.
Denk auch mal an Programme an denen im Laufe der Zeit nicht nur ein Entwickler arbeitet. Sei es in einem Projekt oder bei Freeware Programmen.

Gerade das mit einem "Dummy" Block ist manchmal ideal wenn du klar den Gueltigkeitsbereich einer Variablen definieren willst.
Gruss
Thomas
🖖

Vielleicht ist Wissen doch nicht die Antwort auf alles

11

Donnerstag, 23. März 2006, 18:55

Zitat

Eine klare Aufteilung in Definition, Initialisierung und Verwendung von Variablen wird naemlich auch wunderbar duch Compiler unterstuetzt.
Wirfst du naemlich Verwendung und Initialisierung raus, warnt dich gleich der Compiler vor ungenutzten Variablen.


Das ist (zumindetens beim gcc 3.3 bis 4.1) genau andersherum als Du glaubst :P

Quellcode

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#include <stdlib.h>

int main()
{
  {
    int a = atoi( "12" );
  }

  {
    int b;
    b = atoi( "12" );
  }
  return 1;
}

$ gcc -Wall test.c
test.c: In function `main':
test.c:6: warning: unused variable `a'

1:0 für die Initialisierung bei der Deklaration ;)

Ich verwende "Dummy-Blöcke" auch, aber eben nicht, um "späte" Variablen zu erzeugen, sondern nur, um den Scope festzulegen.

Grüße
Malte

Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von »DrM« (23. März 2006, 19:01)


12

Donnerstag, 23. März 2006, 20:51

Zitat

sondern nur, um den Scope festzulegen

Hab ich ja geschrieben. ;)

Ja, 1:0 fuer den gcc Compiler. Macht aber leider nicht jeder. Wir arbeiten in der Firma bei Anwendungsprogrammen derzeit auf 4 verschiedenen Plattformen. Leider auch unterschiedliche Compiler. Und da gewoehnt man sich an das "kleinste gemeinsame Vielfache." :D
Gruss
Thomas
🖖

Vielleicht ist Wissen doch nicht die Antwort auf alles

Dicker

RCLine User

Wohnort: Hamburch

Beruf: Ezialist

  • Nachricht senden

13

Freitag, 24. März 2006, 22:46

Du meinst die Fehler die alle auf die gleiche Art produzieren? ;)

Ich find es schoener (schoen wie Blumen, oder Bienen) wenn die Variablen oben deklariert werden. (um mal ein Unumstoessliches Argument einzubringen)

Gruss Julian
FollowMe

I :heart:Alex

Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von »Dicker« (24. März 2006, 22:48)


14

Montag, 27. März 2006, 16:32

Ihr seid doch alle Pascal-verseucht :D:D:D!

Oder noch schlimmer Modula-2

Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von »DrM« (27. März 2006, 16:33)


Dicker

RCLine User

Wohnort: Hamburch

Beruf: Ezialist

  • Nachricht senden

15

Montag, 27. März 2006, 16:38

Ich hab mit dem Schneider CPC angefangen, Basic. Dann Assembler auf dem Z80.
Dann kam C. Irgendwann spaeter in der 12. Klasse musste ich dann pascal "lernen"

Gruss Julian
FollowMe

I :heart:Alex