Morgen! Eine Frage zur static-Variable: Ich habe diese deklariert, damit die Variable in der Funktion beim nächsten Aufruf auch wieder vorhanden ist und ihren Wert nicht verliert. Wenn ich diese nun aber nicht mehr benötige, wie werde ich sie wieder los? Gibt es einen Befehl, um den Speicher wieder frei zu geben?
:
Verschoben durch Admin
Ewald schrieb: > Wenn ich diese nun aber nicht mehr benötige, wie werde ich sie > wieder los? Überhaupt nicht. > Gibt es einen Befehl, um den Speicher wieder frei zu geben? Nein.
A. K. schrieb: > Nein. Wie? Einmal in die elt gesetzt...für immer am Hals? Ist ja schlimmer als n Kind.
Nu - weshalb heisst "static" wohl so? Damit es dynamisch ist? Beschreib lieber mal das eigentliche Problem als deinen fehlgeschlagenen Ansatz zur Lösung. Es gibt nämlich auch statische Zeiger auf dynamischen Speicher, wenn's unbedingt sein muss.
A. K. schrieb: > Damit es dynamisch ist? Nee, natürlich nicht, nur kann ja sein, dass man sie explizit wieder killen kann, wenn man sie nicht mehr benötigt.
1 | void current_test_out (void) |
2 | {
|
3 | static uint8_t position = 5; |
4 | |
5 | static int8_t number_1 = 0; |
6 | static int8_t number_2 = 4; |
7 | static int8_t number_3 = 0; |
8 | static int8_t number_4 = 0; |
9 | |
10 | uint32_t dac_test_value = 0; |
11 | |
12 | .....
|
Das ganze ist in einem Menü. number_1 bis number_4 sind vier Stellen auf einem LCD, welche man mit +/- -Tasten einzeln erhöhen, bzw. verringern kann. Da es noch andere Sachen im Programm zu tun gibt, wird das Menü zyklisch aufgerufen, die eigentliche Funktion also verlassen. Wenn ich die Variablen nicht als static deklariere, sind sie natürlich beim nächsten Aufruf weg. Und meine Frage wäre jetzt gewesen, dass wenn ich den Menüpunkt nicht mehr aufrufe, die Variable auch weg kann.
Nimm eine globale Variable und nenn sie help. Dann kannst du mit ihr machen, was du willst... ;-)
A. K. schrieb: > Du machst dir wegen der paar Bytes solche Sorgen? Nein, war ja nur ne Frage, ob es geht.
Ewald schrieb: > Wenn ich die Variablen nicht als static deklariere, sind sie natürlich > beim nächsten Aufruf weg. Schon. Aber warum muss sich diese Funktion die Werte merken? Warum kann man sich die nicht ausserhalb merken? Warum müssen das 4 int8_t sein? Warum kann das nicht ein einzelner int8_t sein, der von der Funktion bei Betreten (die Funktion bekommt den Wert mit) in die einzelnen Stellen zerlegt wird und der von der Funktion vor dem Verlassen wieder zu einem int8_t zusammengebaut wird? Die Funktion liefert dann an den Aufrufer den neuen, vom Benutzer veränderten Wert zurück. Die aufrufende Funktion macht dann mit dem Wert, was auch immer notwendig ist und die Funktion muss sich selbst intern nichts merken. Neben dem geringeren Speicherplatzverbrauch gewinnst du dadurch auch Flexibilität, da du diese 'Einstellfunktion' dann für viele verschiedene Werte in deinem Programm benutzen kannst und nicht nur für einen. Du versuchst gerade ein 'Problem' zu lösen, dass du bei einem vernünftigen Programmdesign gar nicht hättest.
Karl heinz Buchegger schrieb: > Warum kann man sich die nicht ausserhalb merken? Meinst du mit ner globalen Variable?
Karl heinz Buchegger schrieb: > dass du bei einem > vernünftigen Programmdesign gar nicht hättest So lang bin ich eben noch nicht beim Programmieren...
Ewald schrieb: > Karl heinz Buchegger schrieb: >> Warum kann man sich die nicht ausserhalb merken? > > Meinst du mit ner globalen Variable? Kann sein. Aber: Warum müssen das 4 int8_t sein? Warum kann das nicht ein einzelner int8_t sein, der von der Funktion bei Betreten (die Funktion bekommt den Wert mit) in die einzelnen Stellen zerlegt wird und der von der Funktion vor dem Verlassen wieder zu einem int8_t zusammengebaut wird? Die Funktion liefert dann an den Aufrufer den neuen, vom Benutzer veränderten Wert zurück. Die aufrufende Funktion macht dann mit dem Wert, was auch immer notwendig ist und die Funktion muss sich selbst intern nichts merken. Neben dem geringeren Speicherplatzverbrauch gewinnst du dadurch auch Flexibilität, da du diese 'Einstellfunktion' dann für viele verschiedene Werte in deinem Programm benutzen kannst und nicht nur für einen.
Es ist halt quasi so:
1 | main
|
2 | {
|
3 | irgendwas... |
4 | irgendwas anderes... |
5 | |
6 | if (menue_soll_angezeigt_werden == JA) |
7 | {
|
8 | switch (menuepunkt) |
9 | {
|
10 | punkt1:
|
11 | {
|
12 | ...
|
13 | }
|
14 | punktX:
|
15 | {
|
16 | static uint8_t position = 5; |
17 | |
18 | static int8_t number_1 = 0; |
19 | static int8_t number_2 = 4; |
20 | static int8_t number_3 = 0; |
21 | static int8_t number_4 = 0; |
22 | |
23 | uint32_t dac_test_value = 0; |
24 | |
25 | ...
|
26 | }
|
27 | }
|
28 | }
|
29 | }
|
Ewald schrieb: > Es ist halt quasi so: Nicht 'quasi'. Jeder Fall ist immer ein wenig anders. Wenn man konkret sagen soll, wie es besser gehen könnte, muss man auch den konkreten Code sehen.
So, das ist das ganze dazu, ist natürlich jetzt recht lang, sind eigentlich nur abfragen drin um bestimmte Grenzen nicht zu über-/unterschreiten. 4-stellige LCD-Anzeige bei der man mit PLUS und MINUS hoch und runter zählen kann und mit einer dritten Taste die Stelle wechselt. Damit stellt man einen Strom ein, der dann zu einem DAC geschickt wird, wenn man die dritte Taste langegedrückt hält.
1 | main
|
2 | {
|
3 | ...
|
4 | |
5 | if ((menu_item == 0) && (get_button_long (BUTTON_3))) |
6 | {
|
7 | menu_item = 1; |
8 | }
|
9 | |
10 | if (menu_item != 0) |
11 | {
|
12 | current_test_out (); |
13 | }
|
14 | |
15 | ...
|
16 | }
|
17 | |
18 | |
19 | |
20 | void current_test_out (void) |
21 | {
|
22 | static uint8_t position = 5; |
23 | |
24 | static int8_t number_1 = 0; |
25 | static int8_t number_2 = 4; |
26 | static int8_t number_3 = 0; |
27 | static int8_t number_4 = 0; |
28 | |
29 | uint32_t dac_test_value = 0; |
30 | |
31 | if (ten_ms_toggle) |
32 | {
|
33 | ten_ms_toggle = FALSE; |
34 | |
35 | lcd_clear_display (); |
36 | lcd_jump_to (2,4); |
37 | lcd_send_string ("mA"); |
38 | lcd_jump_to (1,1); |
39 | |
40 | switch (position) |
41 | {
|
42 | case 1: |
43 | {
|
44 | if (display_toggle) |
45 | {
|
46 | lcd_send_num (number_1, FALSE); |
47 | }
|
48 | else
|
49 | {
|
50 | lcd_send_num (' ', FALSE); |
51 | }
|
52 | |
53 | lcd_send_num (number_2, TRUE); |
54 | lcd_send_num (number_3, FALSE); |
55 | lcd_send_num (number_4, FALSE); |
56 | |
57 | break; |
58 | }
|
59 | |
60 | case 2: |
61 | {
|
62 | lcd_send_num (number_1, FALSE); |
63 | |
64 | if (display_toggle) |
65 | {
|
66 | lcd_send_num (number_2, TRUE); |
67 | }
|
68 | else
|
69 | {
|
70 | lcd_send_num (' ', TRUE); |
71 | }
|
72 | |
73 | lcd_send_num (number_3, FALSE); |
74 | lcd_send_num (number_4, FALSE); |
75 | |
76 | break; |
77 | }
|
78 | |
79 | case 3: |
80 | {
|
81 | lcd_send_num (number_1, FALSE); |
82 | lcd_send_num (number_2, TRUE); |
83 | |
84 | if (display_toggle) |
85 | {
|
86 | lcd_send_num (number_3, FALSE); |
87 | }
|
88 | else
|
89 | {
|
90 | lcd_send_num (' ', FALSE); |
91 | }
|
92 | |
93 | lcd_send_num (number_4, FALSE); |
94 | |
95 | break; |
96 | }
|
97 | |
98 | case 4: |
99 | {
|
100 | lcd_send_num (number_1, FALSE); |
101 | lcd_send_num (number_2, TRUE); |
102 | lcd_send_num (number_3, FALSE); |
103 | |
104 | if (display_toggle) |
105 | {
|
106 | lcd_send_num (number_4, FALSE); |
107 | }
|
108 | else
|
109 | {
|
110 | lcd_send_num (' ', FALSE); |
111 | }
|
112 | |
113 | break; |
114 | }
|
115 | |
116 | case 5: |
117 | {
|
118 | lcd_send_num (number_1, FALSE); |
119 | lcd_send_num (number_2, TRUE); |
120 | lcd_send_num (number_3, FALSE); |
121 | lcd_send_num (number_4, FALSE); |
122 | |
123 | break; |
124 | }
|
125 | }
|
126 | |
127 | if (BUTTON_PLUS) |
128 | {
|
129 | switch (position) |
130 | {
|
131 | case 1: |
132 | {
|
133 | number_1 += 1; |
134 | |
135 | if (number_1 > 2) |
136 | {
|
137 | number_1 = 0; |
138 | }
|
139 | |
140 | break; |
141 | }
|
142 | |
143 | case 2: |
144 | {
|
145 | number_2 += 1; |
146 | |
147 | if (number_1 == 2) |
148 | {
|
149 | if (number_2 > 4) |
150 | {
|
151 | number_2 = 0; |
152 | }
|
153 | }
|
154 | else if (number_1 == 0) |
155 | {
|
156 | if (number_2 > 9) |
157 | {
|
158 | number_2 = 3; |
159 | }
|
160 | }
|
161 | else
|
162 | {
|
163 | if (number_2 > 9) |
164 | {
|
165 | number_2 = 0; |
166 | }
|
167 | }
|
168 | |
169 | break; |
170 | }
|
171 | |
172 | case 3: |
173 | {
|
174 | number_3 += 1; |
175 | |
176 | if ((number_1 == 2) && (number_2 == 4)) |
177 | {
|
178 | number_3 = 0; |
179 | }
|
180 | else if ((number_1 == 0) && (number_2 == 3)) |
181 | {
|
182 | if (number_3 > 9) |
183 | {
|
184 | number_3 = 5; |
185 | }
|
186 | }
|
187 | else
|
188 | {
|
189 | if (number_3 > 9) |
190 | {
|
191 | number_3 = 0; |
192 | }
|
193 | }
|
194 | |
195 | break; |
196 | }
|
197 | |
198 | case 4: |
199 | {
|
200 | number_4 += 1; |
201 | |
202 | if ((number_1 == 2) && (number_2 == 4)) |
203 | {
|
204 | number_4 = 0; |
205 | }
|
206 | else
|
207 | {
|
208 | if (number_4 > 9) |
209 | {
|
210 | number_4 = 0; |
211 | }
|
212 | }
|
213 | |
214 | break; |
215 | }
|
216 | }
|
217 | }
|
218 | |
219 | if (BUTTON_MINUS) |
220 | {
|
221 | switch (position) |
222 | {
|
223 | case 1: |
224 | {
|
225 | number_1 -= 1; |
226 | |
227 | if (number_1 < 0) |
228 | {
|
229 | number_1 = 2; |
230 | }
|
231 | |
232 | break; |
233 | }
|
234 | |
235 | case 2: |
236 | {
|
237 | number_2 -= 1; |
238 | |
239 | if (number_1 == 0) |
240 | {
|
241 | if (number_2 < 3) |
242 | {
|
243 | number_2 = 9; |
244 | }
|
245 | }
|
246 | |
247 | else if (number_1 == 2) |
248 | {
|
249 | if (number_2 < 0) |
250 | {
|
251 | number_2 = 4; |
252 | }
|
253 | }
|
254 | else
|
255 | {
|
256 | if (number_2 < 0) |
257 | {
|
258 | number_2 = 9; |
259 | }
|
260 | }
|
261 | |
262 | break; |
263 | }
|
264 | |
265 | case 3: |
266 | {
|
267 | number_3 -= 1; |
268 | |
269 | if ((number_1 == 2) && (number_2 == 4)) |
270 | {
|
271 | number_3 = 0; |
272 | }
|
273 | else if ((number_1 == 0) && (number_2 == 3)) |
274 | {
|
275 | if (number_3 < 5) |
276 | {
|
277 | number_3 = 9; |
278 | }
|
279 | }
|
280 | else
|
281 | {
|
282 | if (number_3 < 0) |
283 | {
|
284 | number_3 = 9; |
285 | }
|
286 | }
|
287 | |
288 | break; |
289 | }
|
290 | |
291 | case 4: |
292 | {
|
293 | number_4 -= 1; |
294 | |
295 | if ((number_1 == 2) && (number_2 == 4)) |
296 | {
|
297 | number_4 = 0; |
298 | }
|
299 | else
|
300 | {
|
301 | if (number_4 < 0) |
302 | {
|
303 | number_4 = 9; |
304 | }
|
305 | }
|
306 | |
307 | break; |
308 | }
|
309 | }
|
310 | }
|
311 | }
|
312 | |
313 | if (get_button_short (BUTTON_3)) |
314 | {
|
315 | if ((number_1 == 2) && (number_2 >= 4)) |
316 | {
|
317 | number_2 = 4; |
318 | number_3 = 0; |
319 | number_4 = 0; |
320 | }
|
321 | else if ((number_1 == 0) && (number_2 <= 3)) |
322 | {
|
323 | number_2 = 3; |
324 | number_3 = 5; |
325 | number_4 = 0; |
326 | }
|
327 | |
328 | position += 1; |
329 | |
330 | if (position > 5) |
331 | {
|
332 | position = 1; |
333 | }
|
334 | }
|
335 | |
336 | if (get_button_long (BUTTON_3)) |
337 | {
|
338 | if ((number_1 == 2) && (number_2 >= 4)) |
339 | {
|
340 | number_2 = 4; |
341 | number_3 = 0; |
342 | number_4 = 0; |
343 | }
|
344 | else if ((number_1 == 0) && (number_2 <= 3)) |
345 | {
|
346 | number_2 = 3; |
347 | number_3 = 5; |
348 | number_4 = 0; |
349 | }
|
350 | |
351 | position = 5; |
352 | |
353 | dac_test_value = (number_1 * 1000); |
354 | dac_test_value += (number_2 * 100); |
355 | dac_test_value += (number_3 * 10); |
356 | dac_test_value += number_4; |
357 | |
358 | if ((dac_test_value > 2000) || (dac_test_value < 400)) |
359 | {
|
360 | dac_test_value = (dac_test_value * 131072); |
361 | dac_test_value = (dac_test_value / 3200); |
362 | dac_write (dac_test_value, ALARM); |
363 | }
|
364 | else
|
365 | {
|
366 | dac_test_value = (dac_test_value - 400); |
367 | dac_test_value = (dac_test_value * 65536); |
368 | dac_test_value = (dac_test_value / 1600); |
369 | dac_write (dac_test_value, NORMAL); |
370 | }
|
371 | }
|
372 | |
373 | if (BUTTON_P_M) // Verlassen |
374 | {
|
375 | number_1 = 0; |
376 | number_2 = 4; |
377 | number_3 = 0; |
378 | number_4 = 0; |
379 | |
380 | menu_item = 0; |
381 | }
|
382 | }
|
Das sieht jetzt für mich erst mal so aus, als ob du den Strom zwischen 0 und 2500 einstellen können willst. Melde mich gleich noch mal
Ein nicht unerklecklicher Teil deiner Funktion beschäftigt sich damit, die 4 einzelnen Stellen und deren Zusammenhänge zu 'verwalten'. Da würde ich einen Ansatzpunkt sehen um den Code zu vereinfachen. Wenn du grundsätzlich nur einen int16_t hättest, der den momentan eingestellten Strom enthält, dann ist ja das Drücken von +/- an den einzelnen Position gleichwertig damit, dass dieser Strom um 1; 10; 100; 1000 erhöht/erniedrigt wird. Damit fällt dir dann aber auch vieles weg, was sich jetzt nur um Überträge, Bereichsgrenzen etc. dreht. Das ist das eine. Das andere ist: In einem guten Software Design, macht eine Funktion eine Aufgabe und nur diese Aufgabe. Ich würde daher trennen: Die Funktion soll sich um die Benutzereingabe kümmern, einen übergebenen Wert entsprechend der Tastendrücke manipulieren und als Rückgabewert auch noch mitteilen, ob der Wert jetzt zum DAC gegeben werden soll oder nicht. D.h. nicht die Funktion speicher den aktuellen Wert für current, sondern der existiert entweder beim Aufrufer oder überhaupt in einer globalen Variablen. Das ebnet dann auch den Weg um zb den Wert im EEPROM zwischenzuspeichern (damit er beim Ein/Ausschalten des Geräts wieder verfügbar ist) oder eine PC-Schnittstelle über UART nachzurüsten etc.
1 | //
|
2 | // wandelt einen Wert in seine ASCII Darstellung
|
3 | // es werden immer 4 Stellen generiert, wobei mit
|
4 | // führenden 0-en aufgefüllt wird.
|
5 | //
|
6 | void my_itoa( int16_t wert, char* buffer ) |
7 | {
|
8 | //
|
9 | // das wäre die simpelste Variante
|
10 | // sprintf( buffer, "%04d", wert );
|
11 | |
12 | buffer[0] = wert / 1000 + '0'; |
13 | wert = wert % 1000; |
14 | buffer[1] = wert / 100 + '0'; |
15 | wert = wert % 100; |
16 | buffer[2] = wert / 10 + '0'; |
17 | buffer[3] = wert % 10 + '0'; |
18 | buffer[4] = '\0'; |
19 | }
|
20 | |
21 | //
|
22 | // Die Funktion wendet Tastendrücke auf den übergebenen Wert an
|
23 | //
|
24 | // '+' Wert wird erhöht
|
25 | // '-' Wert wird erniedrigt
|
26 | //
|
27 | // Rückgabe:
|
28 | // TRUE Wert soll an den DAC geschickt werden, Eingabe abgeschlossen
|
29 | // FALSE Wert ist manipuliert, Eingabe aber noch nicht abgeschlossen
|
30 | //
|
31 | // Argumente:
|
32 | // *wert Zeiger auf eine int16_t Variable, die verändert werden soll
|
33 | // *digitPos Welche Ziffer ist drann mit editieren
|
34 | // 0 ... Einer
|
35 | // 1 ... Zehner
|
36 | // 2 ... Hunderter
|
37 | // 3 ... Tausender
|
38 | //
|
39 | uint8_t current_test_out( int16_t* wert, uint8_t* digitPos ) |
40 | {
|
41 | char buffer[5]; |
42 | int16_t increment[] = { 1, 10, 100, 1000 }; |
43 | |
44 | if( ten_ms_toggle ) |
45 | {
|
46 | ten_ms_toggle = FALSE; |
47 | |
48 | lcd_clear_display (); |
49 | lcd_jump_to (2,4); |
50 | lcd_send_string ("mA"); |
51 | lcd_jump_to (1,1); |
52 | |
53 | //
|
54 | // die Zahl einfach mal mit allen 4 Stellen ausgeben
|
55 | //
|
56 | my_itoa( *wert, buffer ); |
57 | lcd_send_string( buffer ); |
58 | |
59 | //
|
60 | // Für das Blinken die richtige Stelle mit einem Leerzeichen
|
61 | // überschreiben
|
62 | //
|
63 | if( toggle_display ) { |
64 | lcd_jump_to( 1, 4 - digitPos ); |
65 | lcd_send_string( " " ); |
66 | }
|
67 | |
68 | //
|
69 | // die Tasten auswerten
|
70 | //
|
71 | if( BUTTON_PLUS ) |
72 | *wert = *wert + increment[digitPos]; |
73 | |
74 | if( BUTTON_MINUS ) |
75 | *wert = *wert - increment[digitPos]; |
76 | |
77 | // sicherstellen, dass der Wert im Rahmen bleibt
|
78 | // dabei auch Overflows und Underflows handhaben
|
79 | if( *wert > 3499 ) |
80 | *wert = 3499 |
81 | |
82 | if( *wert < 35 ) |
83 | *wert = 35; |
84 | |
85 | //
|
86 | // wenn jetzt noch die 3.te Taste
|
87 | //
|
88 | // Ein kurzer Druck bedeutet: ab zur nächsten Stelle
|
89 | //
|
90 | if( get_button_short( BUTTON_3 ) ) |
91 | *digitPos += 1; |
92 | if( *digitPos == 4 ) |
93 | *digitPos = 0; |
94 | }
|
95 | |
96 | //
|
97 | // ein langer Druck bedeutet:
|
98 | // Wert am DAC setzen. Das wird einfach dem Aufrufer gemeldet
|
99 | //
|
100 | if( get_button_long( BUTTON_3 ) ) |
101 | return 1; |
102 | }
|
103 | |
104 | return 0; |
105 | }
|
106 | |
107 | int main() |
108 | {
|
109 | int16_t current = 35; |
110 | uint8_t digitPos = 0; |
111 | |
112 | ...
|
113 | |
114 | |
115 | while( 1 ) { |
116 | ....
|
117 | |
118 | |
119 | if( ..... |
120 | |
121 | if( current_test_out( ¤t, &digitPos ) ) |
122 | set_Current_DAC( current ); |
123 | |
124 | ...
|
Warnung: ungetesteter Code Ob ich mir allerdings den ganzen Teil mit Editierung der Einzelstellen antun würde, weiß ich ehrlich gesagt nicht. Ich hätte mir die PeDa Entprellung genommen und ganz einfach mit dessen Autorepeat den Wert einfach um +/- 1 erhöht, bzw. wenn der Autorepeat einsetzt, den Wert um +/- 100 erhöht/erniedrigt. Letztendes ist das für den Benutzer wahrscheinlich angenehmer, als wie wenn er erst mit einer 3.ten Taste kompliziert auf die Stelle manövrieren muss, die er braucht und die um 1 erhöhen/erniedrigen muss.
OK, vielen Dank schonmal, das werde ich mir jetzt erstmal zu Gemüte führen!
was für ein Display benutzt du eigentlich? der standard text-display-controller (k.A. wie der heißt) hat einen einschaltbaren cursor, der blinkt entweder als ganzer Block, oder als Unterstrich. Da braucht man sich nicht selbst um das blinken kümmern
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.