Hallo,
ich habe Probleme mit folgenden Code. Und zwar versuche ich an die
Funktion MesseFeuchte ein Array zu übergeben. Dies mach ich über einen
Pointer auf das Array aus der main-funktion. In der Funktion
MesseFeuchte verändere ich den Wert des Pointers, also das array.
funktioniert aber nicht. Ich bekomme dann folgende Warnung für den code
in Zeile 106 und 107, also überall wo *str steht.
../LCD_Test.c:107: warning: passing argument 4 of 'dtostrf' makes
pointer from integer without a cast
Ich muss wohl irgendeine Typenkonvertierung durchführen. Jedenfalls
steht auf meinen LCD immernoch "Test", das Array wurde also nicht
verändert. Ich bitte um Hilfe.
1
2
#include<avr/io.h>
3
#include<avr/interrupt.h>
4
#include"lcd-routines.h"
5
#include<util/delay.h>
6
#include<stdlib.h>
7
#include"i2cmaster.h"
8
#ifndef F_CPU
9
#define F_CPU 1000000
10
#endif
11
#ifndef TRUE
12
#define TRUE 1
13
#define FALSE 0
14
#endif
15
16
volatileunsignedcharNrOverflows=0;// Anzahl der Timer Overflows die während
17
// der Messung passiert sind
18
volatileunsignedintStartTime=0;// ICR-Wert bei 1.High-Flanke speichern
19
volatileunsignedintEndTime=0;// ICR-Wert bei 2.High-Flanke speichern
20
volatileunsignedcharMessung;// Job Flag
21
22
ISR(TIMER1_CAPT_vect)
23
{
24
staticunsignedcharErsteFlanke=TRUE;
25
if(Messung)// Die Ergebnissen der vorhergehenden wurden noch nicht ausgegeben
26
return;// Messung noch nicht upgedated. Die naechste Messung
27
// verzögern, bis die Start und EndTime Variablen wieder
28
// gefahrlos beschrieben werden koennen
29
30
// Bei der ersten Flanke beginnt die Messung, es wird der momentane
31
// Timer beim Input Capture als Startwert gesichert
32
if(ErsteFlanke)
33
{
34
StartTime=ICR1;
35
NrOverflows=0;
36
ErsteFlanke=FALSE;// Die naechste Flanke ist das Ende der Messung
37
}
38
39
// das ist die zweite Flanke im Messzyklus. Die Messung wird gestoppt
40
else
41
{
42
EndTime=ICR1;
43
Messung=TRUE;// Eine vollständige Messung. Sie kann ausgewertet werden
44
ErsteFlanke=TRUE;// Bei der naechsten Flanke beginnt der naechste Messzyklus
45
}
46
}
47
48
49
ISR(TIMER1_OVF_vect)
50
{
51
NrOverflows++;
52
}
53
54
55
voidMesseFeuchte(char*str)
56
{
57
58
shorti=0;
59
doublefreq=0.0;
60
doublezwe=0.0;
61
doublesens=0.0;
62
doublesensmsb=0.0;
63
doublesenslsb=0.0;
64
doubleoffset=0.0;
65
doubleoffmsb=0.0;
66
doubleofflsb=0.0;
67
doublerh=0.0;
68
69
i2c_init();
70
i2c_start(0xA2);
71
i2c_write(0x0A);
72
i2c_start(0xA3);
73
sensmsb=i2c_readAck();
74
senslsb=i2c_readAck();
75
offmsb=i2c_readAck();
76
offlsb=i2c_readNak();
77
i2c_stop();
78
offmsb=offmsb*16*16;
79
offset=offmsb+offlsb;
80
sensmsb=sensmsb*16*16;
81
sens=sensmsb+senslsb;
82
83
84
if(Messung)
85
{
86
//
87
// Die Zeitdauer zwischen den Flanken bestimmen
88
// Da EndTime und StartTime unsigned sind, braucht nicht
89
// darauf Ruecksicht genommen werden, dass EndTime auch
90
// kleiner als StartTime sein kann. Es kommt trotzdem
91
// das richtige Ergebnis raus.
92
// Allerdings muss die Anzahl der Overflows in der Messperiode
93
// beruecksichtigt werden
94
//
95
// Die Zeitdauer wird als Anzahl der Taktzyklen zwischen den
96
// beiden gemessenen Flanken berechnet ...
97
freq=(NrOverflows*65536)+EndTime-StartTime;
98
// ... mit der bekannten Taktfrequenz ergibt sich dann die Signalfrequenz
Mit folgenden Text passt die Ausgabe auf dem LCD mit "Feuchte: 40.45".
Ich möchte die main allerdings etwas übersichtlich halten und versuche
deswegen eine Funktion für das Messen der Feuchte zu erstellen.
1
#include<avr/io.h>
2
#include<avr/interrupt.h>
3
#include"lcd-routines.h"
4
#include<util/delay.h>
5
#include<stdlib.h>
6
#include"i2cmaster.h"
7
#ifndef F_CPU
8
#define F_CPU 1000000
9
#endif
10
#ifndef TRUE
11
#define TRUE 1
12
#define FALSE 0
13
#endif
14
15
volatileunsignedcharNrOverflows=0;// Anzahl der Timer Overflows die während
16
// der Messung passiert sind
17
volatileunsignedintStartTime=0;// ICR-Wert bei 1.High-Flanke speichern
18
volatileunsignedintEndTime=0;// ICR-Wert bei 2.High-Flanke speichern
19
volatileunsignedcharMessung;// Job Flag
20
21
ISR(TIMER1_CAPT_vect)
22
{
23
staticunsignedcharErsteFlanke=TRUE;
24
if(Messung)// Die Ergebnissen der vorhergehenden wurden noch nicht ausgegeben
25
return;// Messung noch nicht upgedated. Die naechste Messung
26
// verzögern, bis die Start und EndTime Variablen wieder
27
// gefahrlos beschrieben werden koennen
28
29
// Bei der ersten Flanke beginnt die Messung, es wird der momentane
30
// Timer beim Input Capture als Startwert gesichert
31
if(ErsteFlanke)
32
{
33
StartTime=ICR1;
34
NrOverflows=0;
35
ErsteFlanke=FALSE;// Die naechste Flanke ist das Ende der Messung
36
}
37
38
// das ist die zweite Flanke im Messzyklus. Die Messung wird gestoppt
39
else
40
{
41
EndTime=ICR1;
42
Messung=TRUE;// Eine vollständige Messung. Sie kann ausgewertet werden
43
ErsteFlanke=TRUE;// Bei der naechsten Flanke beginnt der naechste Messzyklus
44
}
45
}
46
47
48
ISR(TIMER1_OVF_vect)
49
{
50
NrOverflows++;
51
}
52
53
54
intmain(void)
55
{
56
charstr[8];
57
shorti=0;
58
doublefreq=0.0;
59
doublezwe=0.0;
60
doublesens=0.0;
61
doublesensmsb=0.0;
62
doublesenslsb=0.0;
63
doubleoffset=0.0;
64
doubleoffmsb=0.0;
65
doubleofflsb=0.0;
66
doublerh=0.0;
67
68
i2c_init();
69
i2c_start(0xA2);
70
i2c_write(0x0A);
71
i2c_start(0xA3);
72
sensmsb=i2c_readAck();
73
senslsb=i2c_readAck();
74
offmsb=i2c_readAck();
75
offlsb=i2c_readNak();
76
i2c_stop();
77
offmsb=offmsb*16*16;
78
offset=offmsb+offlsb;
79
sensmsb=sensmsb*16*16;
80
sens=sensmsb+senslsb;
81
82
TCCR1B=(1<<ICES1)|(1<<CS10);
83
TIMSK=(1<<TICIE1)|(1<<TOIE1);
84
sei();
85
DDRB=0b11111110;
86
87
88
// Initialisierung des LCD
89
_delay_ms(2000);
90
lcd_init();
91
92
93
while(1)
94
{
95
if(Messung)
96
{
97
//
98
// Die Zeitdauer zwischen den Flanken bestimmen
99
// Da EndTime und StartTime unsigned sind, braucht nicht
100
// darauf Ruecksicht genommen werden, dass EndTime auch
101
// kleiner als StartTime sein kann. Es kommt trotzdem
102
// das richtige Ergebnis raus.
103
// Allerdings muss die Anzahl der Overflows in der Messperiode
104
// beruecksichtigt werden
105
//
106
// Die Zeitdauer wird als Anzahl der Taktzyklen zwischen den
107
// beiden gemessenen Flanken berechnet ...
108
freq=(NrOverflows*65536)+EndTime-StartTime;
109
// ... mit der bekannten Taktfrequenz ergibt sich dann die Signalfrequenz
Floh schrieb:> Probiers mal ohne Stern. dtostrf erwartet glaub ich einen Pointer.
Kann ja nicht sein, weil der Quellcode der läuft erhält als char array
und da funktioniert es ohne Warnung. Hab es aber auch schon in der
Quellcode ganz oben so versucht wie du sagst. Dann gibts eine Warnung
und es funktioniert auch nicht :(
Das ist ganz definitiv falsch und der Compiler gibt an dieser Stelle
auch eine Fehlermeldung aus.
dtostrf erwartet als letzten Parameter einen Pointer auf char, und
nicht einen char. Den aber erzeugst Du durch die Dereferenzierung des
Pointers.
Allerdings rufst Du die Funktion MesseFeuchte in Deinem ersten
Codebeispiel überhaupt nicht auf, von daher ist es kein Wunder, daß der
falsche Aufruf von dtostrf keine besondere Auswirkung hat.
Dein zweites Codebeispiel ruft dtostrf auch vollkommen korrekt ohne
Dereferenzierung auf.
youth schrieb:> Floh schrieb:>> Probiers mal ohne Stern. dtostrf erwartet glaub ich einen Pointer.>> Kann ja nicht sein,
Doch.
Das kann nicht nur sein, das ist auch so.
dotostrf erwartet an dieser Stelle einen Pointer. Dein str ist ein
Pointer. Passt also perfekt
> weil der Quellcode der läuft erhält als char array> und da funktioniert es ohne Warnung.
Logisch. Weil der Name eines Arrays an dieser Stelle ohne eine
Dereferenzierung automatisch als Pointer auf den Anfang der Daten
fungiert.
Oder banal ausgedrückt: Ein Array wird immer übergeben, indem der
Empfänger einen Pointer auf die Daten bekommt. Wenn die empfangende
Funktion ihrerseits wieder eine andere Funktion aufruft, der sie das
Array 'weitergeben' möchte, dann übergibt sie ganz einfach den Pointer.
Eine empfangende Funktion kann nicht feststellen, ob der Pointer den sie
bekommt die Startadresse eines Arrays ist oder nicht. Sie bekommt
einfach nur einen Pointer.
Rufus Τ. Firefly schrieb:> Allerdings rufst Du die Funktion MesseFeuchte in Deinem ersten> Codebeispiel überhaupt nicht auf, von daher ist es kein Wunder, daß der> falsche Aufruf von dtostrf keine besondere Auswirkung hat.
Sorry die is tmit drin. Oben nur vergessen.
1
2
while(1)
3
{
4
MesseFeuchte(feu);
5
lcd_setcursor(0,1);
6
//lcd_string("Feuchte: ");
7
//lcd_setcursor( 9, 1 );
8
9
lcd_string(feu);
10
}
Ok, aber auch wenn ich die *str in str ändere. Dann gibt mir das LCD
immer nur Test aus. Das heißt die Messung funktioniert nicht oder das
array wird nicht bearbeitet.
Du hast das dtostrf hinter 3 if-Anweisungen gepackt.
Wobei die letzte if(i>500) immer scheitert, da du in MessFeuchte keine
Schleife hast.
Das i ist lokal und nicht static.
Hallo DirkB,
da hast du vollkommen Recht. i wird so bei jedem Funktionsaufruf auf 0
zurück gesetzt. Jetzt hab ich die Variablen global gemacht und damit
erreicht man auch die innerste if bedingung. Dennoch steht jetzt
schätzungsweise 1 Minute auf dem LCD "Test" da und dann gibt er erst
einen Messwert aus, der auch schätzungsweise nur einmal pro Minute
aktualisiert. Wo ist das Problem? Wenn ich den Code nicht in eine
Funktion auslagere, dann aktualisiert er wesentlich schneller und jetzt
sehr sehr sehr träge. Kann mir vielleicht jemand den Code meines 2.
Beitrag so ausgliedern in eine Funktion, dass es auch funktioniert. Mein
aktueller Code ist:
1
#include<avr/io.h>
2
#include<avr/interrupt.h>
3
#include"lcd-routines.h"
4
#include<util/delay.h>
5
#include<stdlib.h>
6
#include"i2cmaster.h"
7
#ifndef F_CPU
8
#define F_CPU 1000000
9
#endif
10
#ifndef TRUE
11
#define TRUE 1
12
#define FALSE 0
13
#endif
14
15
volatileunsignedcharNrOverflows=0;// Anzahl der Timer Overflows die während
16
// der Messung passiert sind
17
volatileunsignedintStartTime=0;// ICR-Wert bei 1.High-Flanke speichern
18
volatileunsignedintEndTime=0;// ICR-Wert bei 2.High-Flanke speichern
19
volatileunsignedcharMessung;// Job Flag
20
21
ISR(TIMER1_CAPT_vect)
22
{
23
staticunsignedcharErsteFlanke=TRUE;
24
if(Messung)// Die Ergebnissen der vorhergehenden wurden noch nicht ausgegeben
25
return;// Messung noch nicht upgedated. Die naechste Messung
26
// verzögern, bis die Start und EndTime Variablen wieder
27
// gefahrlos beschrieben werden koennen
28
29
// Bei der ersten Flanke beginnt die Messung, es wird der momentane
30
// Timer beim Input Capture als Startwert gesichert
31
if(ErsteFlanke)
32
{
33
StartTime=ICR1;
34
NrOverflows=0;
35
ErsteFlanke=FALSE;// Die naechste Flanke ist das Ende der Messung
36
}
37
38
// das ist die zweite Flanke im Messzyklus. Die Messung wird gestoppt
39
else
40
{
41
EndTime=ICR1;
42
Messung=TRUE;// Eine vollständige Messung. Sie kann ausgewertet werden
43
ErsteFlanke=TRUE;// Bei der naechsten Flanke beginnt der naechste Messzyklus
44
}
45
}
46
47
ISR(TIMER1_OVF_vect)
48
{
49
NrOverflows++;
50
}
51
shorti=0;
52
doublefreq=0.0;
53
doublezwe=0.0;
54
doublesens=0.0;
55
doublesensmsb=0.0;
56
doublesenslsb=0.0;
57
doubleoffset=0.0;
58
doubleoffmsb=0.0;
59
doubleofflsb=0.0;
60
doublerh=0.0;
61
62
voidMesseFeuchte(char*str)
63
{
64
i2c_init();
65
i2c_start(0xA2);
66
i2c_write(0x0A);
67
i2c_start(0xA3);
68
sensmsb=i2c_readAck();
69
senslsb=i2c_readAck();
70
offmsb=i2c_readAck();
71
offlsb=i2c_readNak();
72
i2c_stop();
73
offmsb=offmsb*16*16;
74
offset=offmsb+offlsb;
75
sensmsb=sensmsb*16*16;
76
sens=sensmsb+senslsb;
77
78
79
if(Messung)
80
{
81
//
82
// Die Zeitdauer zwischen den Flanken bestimmen
83
// Da EndTime und StartTime unsigned sind, braucht nicht
84
// darauf Ruecksicht genommen werden, dass EndTime auch
85
// kleiner als StartTime sein kann. Es kommt trotzdem
86
// das richtige Ergebnis raus.
87
// Allerdings muss die Anzahl der Overflows in der Messperiode
88
// beruecksichtigt werden
89
//
90
// Die Zeitdauer wird als Anzahl der Taktzyklen zwischen den
91
// beiden gemessenen Flanken berechnet ...
92
freq=(NrOverflows*65536)+EndTime-StartTime;
93
// ... mit der bekannten Taktfrequenz ergibt sich dann die Signalfrequenz
Muss das sein?
Vorher has du das einmal beim Programmstart gemacht.
youth schrieb:> Jetzt hab ich die Variablen global gemacht
static hätte gereicht.
Besser ist es den Wert in einer Funktion zu berechnen und in einer
anderen auszugeben.
DirkB schrieb:> Muss das sein?> Vorher has du das einmal beim Programmstart gemacht.
Eigentlich nicht, damit werden nur Koeffizienten ausgelesen. Würde glaub
ich auch einmalig reichen.
DirkB schrieb:> Besser ist es den Wert in einer Funktion zu berechnen und in einer> anderen auszugeben.
Das möchte ich ja versuchen. Ich wollte eine Funktion in der die Feuchte
komplett gemessen wird. Der Wert soll dann an main zurückgegeben werden
um die dann auszugeben. Nur leider scheitere ich ja gerade daran wie du
siehst.
DirkB schrieb:> Muss das sein?> Vorher has du das einmal beim Programmstart gemacht.
Aber du hast Recht, damit ist das Problem für die träge Messung
beseitigt. Wahrscheinlich hat das Auslesen der Koeffizienten zu viel
Zeit beansprucht um das dauerhaft zu machen.
Dann hab ich den Code zwar in der main Funktion mit drin, aber das ist
besser so. Danke dir.
Das andere ist, dass du ständig auf das LCD malst, selbst dann, wenn
sich die Anzeige gar nicht verändert, weil du noch gar keine Messung
gemacht hast. Du musst auf dem LCD nur dann updaten, wenn tatsächlich in
Messung auch ein neuer Wert bestimmt wird (und eigentlich auch nur dann,
wenn sich dieser Wert vom gerade angezeigten Wert unterscheidet. Aber
das lassen wir jetzt erst mal).
Wann immer dein µC in einer der LCD-Routinen rumtrödelt, dauert es seine
Zeit, biser dann wieder zu der Stelle kommt an der er nachsieht ob eine
neue Messung vorliegt. Auch das kostet Zeit.
youth schrieb:> DirkB schrieb:>> Muss das sein?>> Vorher has du das einmal beim Programmstart gemacht.>> Aber du hast Recht, damit ist das Problem für die träge Messung> beseitigt. Wahrscheinlich hat das Auslesen der Koeffizienten zu viel> Zeit beansprucht um das dauerhaft zu machen.>> Dann hab ich den Code zwar in der main Funktion mit drin, aber das ist> besser so.
Nein. Ist es nicht.
Was hindert dich daran, eine Funktion: GetCoefficients() zu machen, in
die du diese Sequenz verbannst? Dann hast du sie auch aus der main()
draussen.
rh=((offset-(zwe/i))*sens/4096);// Relative Luftfeuchtigkeit mit entsprechender Formel berechnen
29
dtostrf((zwe/i),5,2,str);// Das Ergebnis fuer die Anzeige aufbereiten ...
30
dtostrf(rh,5,2,str);
31
32
i=0;// Variablen zurücksetzen
33
zwe=0.0;//
34
freq=0.0;//
35
}
36
}
37
}
38
39
intmain(void)
40
{
41
charfeu[8]="Test";
42
43
TCCR1B=(1<<ICES1)|(1<<CS10);
44
TIMSK=(1<<TICIE1)|(1<<TOIE1);
45
sei();
46
DDRB=0b11111110;
47
48
// Initialisierung des LCD
49
_delay_ms(2000);
50
51
lcd_init();
52
GetCoefficients();
53
54
while(1)
55
{
56
if(Messung)
57
{
58
MesseFeuchte(feu);
59
lcd_setcursor(0,1);
60
lcd_string(feu);
61
62
Messung=FALSE;
63
}
64
}
65
return0;
66
}
PS: i ist ein ganz schlechter Name füt einen Zaehler der die Anzahl der
Messungen zählt. Genauso wie zwe
Warum nennst du die Dinge nicht nach dem was sie bedeuten.
anzMessungen bzw. sumMessungen
sind doch noch ganz handhabbare Bezeichnungen.
Jetzt ist es ein bischen besser, weil das i lokal in der Funktion ist.
Aber eine globale Variable namens i ist ein definitives "ask for
trouble". Das fordert Fehler geradezu heraus.
Karl Heinz Buchegger schrieb:> Was hindert dich daran, eine Funktion: GetCoefficients() zu machen, in> die du diese Sequenz verbannst?
Nichts, nur dann muss ich die ganzen Variablen immer an die Funktion
übergeben oder teilweise zurückholen und in dem Zusammenhang wohl auch
mit mehreren Pointern arbeiten. Bin ich nicht so geübt drin.
Das mit dem LCD stimmt natürlich, wie würdest du das denn umgehen? Den
Char Array in einen zweiten Kopieren und immer mit den vorherigen Array
vergleichen ob die identisch sind? Und nur dann die LCD Routinen
aufrufen?
youth schrieb:> Karl Heinz Buchegger schrieb:>> Was hindert dich daran, eine Funktion: GetCoefficients() zu machen, in>> die du diese Sequenz verbannst?>> Nichts, nur dann muss ich die ganzen Variablen immer an die Funktion> übergeben oder teilweise zurückholen und in dem Zusammenhang wohl auch> mit mehreren Pointern arbeiten.
Du hast sie ja doch sowieso als globale Variablen.
> Das mit dem LCD stimmt natürlich, wie würdest du das denn umgehen?
Siehe letzten Vorschlag. Der erledigt das gleich mit