Forum: Mikrocontroller und Digitale Elektronik BASCOM-Code eleganter/kürzer formulieren


von neuling (Gast)


Lesenswert?

Hallo,

folgender Code:
1
Gouz:
2
Uzvar = 1
3
   If Rot(1) = 0 Then
4
   Toggle 1r
5
   End If
6
   If Rot(2) = 0 Then
7
   Toggle 2r
8
   End If
9
   If Rot(3) = 0 Then
10
   Toggle 3r
11
   End If
12
   If Rot(4) = 0 Then
13
   Toggle 4r
14
   End If
15
   If Rot(5) = 0 Then
16
   Toggle 5r
17
   End If
18
   If Rot(6) = 0 Then
19
   Toggle 6r
20
   End If
21
   If Rot(7) = 0 Then
22
   Toggle 7r
23
   End If
24
   If Gruen(1) = 0 Then
25
   Toggle 1g
26
   End If
27
   If Gruen(2) = 0 Then
28
   Toggle 2g
29
   End If
30
   If Gruen(3) = 0 Then
31
   Toggle 3g
32
   End If
33
   If Gruen(4) = 0 Then
34
   Toggle 4g
35
   End If
36
   If Gruen(5) = 0 Then
37
   Toggle 5g
38
   End If
39
   If Gruen(6) = 0 Then
40
   Toggle 6g
41
   End If
42
   If Gruen(7) = 0 Then
43
   Toggle 7g
44
   End If
45
   If Blau(1) = 0 Then
46
   Toggle 1b
47
   End If
48
   If Blau(2) = 0 Then
49
   Toggle 2b
50
   End If
51
   If Blau(3) = 0 Then
52
   Toggle 3b
53
   End If
54
   If Blau(4) = 0 Then
55
   Toggle 4b
56
   End If
57
   If Blau(5) = 0 Then
58
   Toggle 5b
59
   End If
60
   If Blau(6) = 0 Then
61
   Toggle 6b
62
   End If
63
   If Blau(7) = 0 Then
64
   Toggle 7b
65
   End If
66
For Uzvar = 1 To 7
67
   Decr Rot(uzvar)
68
   Decr Gruen(uzvar)
69
   Decr Blau(uzvar)
70
Next Uzvar
71
Incr Uz_zyklen
72
If Uz_zyklen = 99 Then
73
   Uz_zyklen = 0
74
   Gosub Gooz
75
End If
76
Return
77
78
Gooz:
79
Uzvar = 1
80
For Uzvar = 1 To 7
81
Rotkopie(uzvar) = Rot(uzvar) - X
82
If Rotkopie(uzvar) < 0 Then
83
Rotkopie(uzvar) = 0
84
End If
85
Gruenkopie(uzvar) = Gruen(uzvar) - X
86
If Gruenkopie(uzvar) < 0 Then
87
Gruenkopie(uzvar) = 0
88
End If
89
Blaukopie(uzvar) = Blau(uzvar) - X
90
If Blaukopie(uzvar) < 0 Then
91
Blaukopie(uzvar) = 0
92
End If
93
Next Uzvar
94
Incr Oz_zyklen
95
1r = 0
96
1b = 0
97
1g = 0
98
99
2r = 0
100
2g = 0
101
2b = 0
102
103
3r = 0
104
3g = 0
105
3b = 0
106
107
4r = 1
108
4g = 1
109
4b = 1
110
111
5r = 1
112
5g = 1
113
5b = 1
114
115
6r = 1
116
6g = 1
117
6b = 1
118
119
7r = 1
120
7g = 1
121
7b = 1
122
Return
Aus meiner main-Loop bzw. anderen gosubs werden die drei Arrays für 7 
rote, grüne und blaue LEDs befüllt mit Werten zwischen 0 und 100. Je 
nach Zahlenwert sollen die LEDs unterschiedlich hell leuchten.
Ich möchte dabei das dargestellte "Bild" alle 10 ms refreshen um 
Flackern zu vermeiden, sprich das Array wird mit gooz (go Oberzyklus) 
neu geladen. Zwischen jedem Oberzyklus sollen 100 Unterzyklen 
stattfinden und je nach Helligkeitswert sollen die LED unterschiedlich 
lange leuchten (PWM). Dazu zählt eine for-Schleife das Array runter und 
danach prüft eine if-Abfrage ob der Wert der jeweiligen LED 0 ist und 
schaltet die LED ggf. ab.
Ich muss das leider mit toggle machen, denn die LEDs sind zum Teil 
common-cathode und common-anode.

Fällt jemandem was ein wie ich den Code im Interrupt gouz und dem davon 
kontrollierten gooz eindampfen könnte bei selber Funktion?

Nochmal die Anforderungen: Ein Array mit Werten zwischen 0 und 100 wird 
ausgelesen und dementsprechend sollen die LEDs gedimmt werden. Dazu soll 
ein ADC-Wert die Gesamthelligkeit steuern (wird nicht laufend 
ausgelesen), indem er vom Array jeweils bis maximal 100 abzieht.

Unterzyklus (gouz) ist interruptgesteuert und wird alle 100 µs 
ausgelöst, Oberzyklus (gooz) alle 100 Unterzyklen ausgeführt, also alle 
10 ms.
Oder schafft das ein ATmega8 @ 16 Hz auch so?

Gruß

von neuling (Gast)


Lesenswert?

ach ja: incr oz_zyklen brauche ich als zeitgeber für meine main-schleife 
bzw. andere gosubs, die muss also drin bleiben.

von neuling (Gast)


Lesenswert?

Und falls es irgendwie von Belang sein sollte:
Das hier ist der aktuelle Code.
1
$regfile = "m8def.dat"
2
$crystal = 8000000
3
$hwstack = 100
4
$swstack = 100
5
$framesize = 100
6
7
'setzt alle Ports/Pins für LEDs
8
9
Config Portb = Output
10
Config Portd = Output
11
12
'1. LED (CC)
13
Config Portc.2 = Output
14
1r Alias Portc.2
15
16
Config Portc.4 = Output
17
1g Alias Portc.4
18
19
Config Portc.5 = Output
20
1b Alias Portc.5
21
22
'2. LED (CC)
23
2r Alias Portb.5
24
25
Config Portc.1 = Output
26
2g Alias Portc.1
27
28
Config Portc.0 = Output
29
2b Alias Portc.0
30
31
'3. LED (CC)
32
3r Alias Portb.2
33
3g Alias Portb.4
34
3b Alias Portb.3
35
36
'4. LED (CA)
37
4r Alias Portd.7
38
4g Alias Portb.1
39
4b Alias Portb.0
40
41
'5. LED (CA)
42
5r Alias Portb.7
43
5g Alias Portd.6
44
5b Alias Portd.5
45
46
'6. LED (CA)
47
6r Alias Portd.3
48
6g Alias Portb.6
49
6b Alias Portd.4
50
51
'7. LED (CA)
52
7r Alias Portd.0
53
7g Alias Portd.2
54
7b Alias Portd.1
55
56
'Konfiguriert Schalter und Trimmer
57
Config Adc = Single , Prescaler = Auto , Reference = Avcc
58
Start Adc
59
60
Config Pinc.1 = Input
61
Taster Alias Pinc.1
62
Taster = 1
63
64
65
'erzeugt alle nötigen Variablen und Arrays
66
Dim Messwert As Word
67
Dim Zz As Word
68
Dim Uz_zyklen As Byte
69
Dim Oz_zyklen As Dword
70
Dim Rotkopie(7) As Byte
71
Dim Gruenkopie(7) As Byte
72
Dim Blaukopie(7) As Byte
73
Dim Rot(7)as Byte
74
Dim Gruen(7) As Byte
75
Dim Blau(7) As Byte
76
Dim Newprog As Bit
77
Dim Prog As Byte
78
Dim Uzvar As Byte
79
Dim X As Word
80
Dim Y As Byte
81
82
'aktiviert Unterzyklus
83
Const Timer1_Preload = 64736
84
85
Config Timer1 = Timer, Prescale = 1
86
Enable Timer1
87
Timer1 = Timer1_Preload
88
On Timer1 Gouz
89
Enable Interrupts
90
91
92
'Schaltet alle LEDs aus (wichtig fürs spätere toggeln)
93
1r = 1
94
1b = 1
95
1g = 1
96
97
2r = 1
98
2g = 1
99
2b = 1
100
101
3r = 1
102
3g = 1
103
3b = 1
104
105
4r = 0
106
4g = 0
107
4b = 0
108
109
5r = 0
110
5g = 0
111
5b = 0
112
113
6r = 0
114
6g = 0
115
6b = 0
116
117
7r = 0
118
7g = 0
119
7b = 0
120
121
122
123
Do
124
If Taster = 1 Then
125
Disable Interrupts
126
Waitms 50
127
Oz_zyklen = 0
128
Enable Interrupts
129
Bitwait Taster , Reset
130
   If Oz_zyklen >= 600 Then
131
   Gosub Messen
132
   Else
133
      If Prog > 15 Then
134
      Prog = 0
135
      Else
136
      Incr Prog
137
      End If
138
   End If
139
Newprog = 1
140
End If
141
142
Select Case Prog
143
Case 1 : Gosub Goweiss
144
Case 2 : Gosub Gorot
145
End Select
146
Loop
147
148
End
149
150
Messen:
151
Disable Interrupts                                          'erfasst über ADC die Stellung des Poti
152
Messwert = Getadc(3)
153
Enable Interrupts
154
Messwert = Messwert / 10
155
X = Messwert
156
Return
157
158
Zufallszahl:
159
Zz = Rnd(100)
160
Return
161
162
Gouz:
163
Uzvar = 1
164
   If Rot(1) = 0 Then
165
   Toggle 1r
166
   End If
167
   If Rot(2) = 0 Then
168
   Toggle 2r
169
   End If
170
   If Rot(3) = 0 Then
171
   Toggle 3r
172
   End If
173
   If Rot(4) = 0 Then
174
   Toggle 4r
175
   End If
176
   If Rot(5) = 0 Then
177
   Toggle 5r
178
   End If
179
   If Rot(6) = 0 Then
180
   Toggle 6r
181
   End If
182
   If Rot(7) = 0 Then
183
   Toggle 7r
184
   End If
185
   If Gruen(1) = 0 Then
186
   Toggle 1g
187
   End If
188
   If Gruen(2) = 0 Then
189
   Toggle 2g
190
   End If
191
   If Gruen(3) = 0 Then
192
   Toggle 3g
193
   End If
194
   If Gruen(4) = 0 Then
195
   Toggle 4g
196
   End If
197
   If Gruen(5) = 0 Then
198
   Toggle 5g
199
   End If
200
   If Gruen(6) = 0 Then
201
   Toggle 6g
202
   End If
203
   If Gruen(7) = 0 Then
204
   Toggle 7g
205
   End If
206
   If Blau(1) = 0 Then
207
   Toggle 1b
208
   End If
209
   If Blau(2) = 0 Then
210
   Toggle 2b
211
   End If
212
   If Blau(3) = 0 Then
213
   Toggle 3b
214
   End If
215
   If Blau(4) = 0 Then
216
   Toggle 4b
217
   End If
218
   If Blau(5) = 0 Then
219
   Toggle 5b
220
   End If
221
   If Blau(6) = 0 Then
222
   Toggle 6b
223
   End If
224
   If Blau(7) = 0 Then
225
   Toggle 7b
226
   End If
227
For Uzvar = 1 To 7
228
   Decr Rot(uzvar)
229
   Decr Gruen(uzvar)
230
   Decr Blau(uzvar)
231
Next Uzvar
232
Incr Uz_zyklen
233
If Uz_zyklen = 99 Then
234
   Uz_zyklen = 0
235
   Gosub Gooz
236
End If
237
Return
238
239
Gooz:
240
Uzvar = 1
241
For Uzvar = 1 To 7
242
Rotkopie(uzvar) = Rot(uzvar) - X
243
If Rotkopie(uzvar) < 0 Then
244
Rotkopie(uzvar) = 0
245
End If
246
Gruenkopie(uzvar) = Gruen(uzvar) - X
247
If Gruenkopie(uzvar) < 0 Then
248
Gruenkopie(uzvar) = 0
249
End If
250
Blaukopie(uzvar) = Blau(uzvar) - X
251
If Blaukopie(uzvar) < 0 Then
252
Blaukopie(uzvar) = 0
253
End If
254
Next Uzvar
255
Incr Oz_zyklen
256
1r = 0
257
1b = 0
258
1g = 0
259
260
2r = 0
261
2g = 0
262
2b = 0
263
264
3r = 0
265
3g = 0
266
3b = 0
267
268
4r = 1
269
4g = 1
270
4b = 1
271
272
5r = 1
273
5g = 1
274
5b = 1
275
276
6r = 1
277
6g = 1
278
6b = 1
279
280
7r = 1
281
7g = 1
282
7b = 1
283
Return
284
285
286
Goweiss:
287
Newprog = 0
288
For Y = 1 To 7
289
Rot(y) = 100
290
Gruen(y) = 100
291
Blau(y) = 100
292
Next Y
293
Y = 0
294
Return
295
296
Gorot:
297
For Y = 1 To 7
298
Rot(y) = 100
299
Next Y
300
Y = 0
301
Return

Es fehlen noch ein paar gosub-Programme, die von Select case aufgerufen 
werden.

von Steckpointer (Gast)


Lesenswert?

If Else case sind nicht deine Freunde?

von Rainer U. (r-u)


Lesenswert?

Kürzer wirst Du sicher, wenn Du in dem Fall auf Aliase verzichtest, 
sondern direkt auf den Ports arbeitest - dann kannst Du mit 
Bitmaskenoperationen mehrere resp. alle Bits auf einmal schalten oder 
negieren.

PortB = &B01000100 ist kürzer als

PortB.0=0
PortB.1=0
PortB.2=1
usw.

von neuling (Gast)


Lesenswert?

if-else-cases sind schonmal gut, die habe ich ggleich eingebaut, frisst 
der Compiler ohne zu meckern.

@Rainer Unsinn: Sehe ich ein, das kann ich aber nicht bei Port C machen, 
da ich dort zwei Pins habe - beim Googeln habe ich keine Möglichkeit 
gefunden zwei Pins auszuschließen aus einer Bitmaskenoperation.

von neuling (Gast)


Lesenswert?

So, diese beiden Schnipsel sind geändert:
1
Gouz:
2
Uzvar = 1
3
   If Rot(1) = 0 Then
4
   Toggle 1r
5
   Elseif Rot(2) = 0 Then
6
   Toggle 2r
7
   Elseif Rot(3) = 0 Then
8
   Toggle 3r
9
   elseIf Rot(4) = 0 Then
10
   Toggle 4r
11
   elseIf Rot(5) = 0 Then
12
   Toggle 5r
13
   elseIf Rot(6) = 0 Then
14
   Toggle 6r
15
   elseIf Rot(7) = 0 Then
16
   Toggle 7r
17
   elseIf Gruen(1) = 0 Then
18
   Toggle 1g
19
   elseIf Gruen(2) = 0 Then
20
   Toggle 2g
21
   elseIf Gruen(3) = 0 Then
22
   Toggle 3g
23
   elseIf Gruen(4) = 0 Then
24
   Toggle 4g
25
   elseIf Gruen(5) = 0 Then
26
   Toggle 5g
27
   elseIf Gruen(6) = 0 Then
28
   Toggle 6g
29
   elseIf Gruen(7) = 0 Then
30
   Toggle 7g
31
   elseIf Blau(1) = 0 Then
32
   Toggle 1b
33
   elseIf Blau(2) = 0 Then
34
   Toggle 2b
35
   elseIf Blau(3) = 0 Then
36
   Toggle 3b
37
   elseIf Blau(4) = 0 Then
38
   Toggle 4b
39
   elseIf Blau(5) = 0 Then
40
   Toggle 5b
41
   elseIf Blau(6) = 0 Then
42
   Toggle 6b
43
   elseIf Blau(7) = 0 Then
44
   Toggle 7b
45
   End If
46
For Uzvar = 1 To 7
47
   Decr Rot(uzvar)
48
   Decr Gruen(uzvar)
49
   Decr Blau(uzvar)
50
Next Uzvar
51
Incr Uz_zyklen
52
If Uz_zyklen = 99 Then
53
   Uz_zyklen = 0
54
   Gosub Gooz
55
End If
56
Return
57
58
Gooz:
59
Uzvar = 1
60
For Uzvar = 1 To 7
61
Rotkopie(uzvar) = Rot(uzvar) - X
62
If Rotkopie(uzvar) < 0 Then
63
Rotkopie(uzvar) = 0
64
End If
65
Gruenkopie(uzvar) = Gruen(uzvar) - X
66
If Gruenkopie(uzvar) < 0 Then
67
Gruenkopie(uzvar) = 0
68
End If
69
Blaukopie(uzvar) = Blau(uzvar) - X
70
If Blaukopie(uzvar) < 0 Then
71
Blaukopie(uzvar) = 0
72
End If
73
Next Uzvar
74
Incr Oz_zyklen
75
76
Portb = &B11111100                                          'setzt alle LEDs an Port B und D auf ein
77
Portd = &B00000001
78
1r = 1
79
1g = 1
80
1b = 1
81
2g = 1
82
2b = 1
83
Return

von Rainer U. (r-u)


Lesenswert?

Doch das geht prinzipiell so:



Variable = PortC

zum setzen auf 1:
Variable = Variable OR Bitmaske, zu setzende Bits=1, unveränderliche=0

zum setzen auf 0:
Variable = Variable UND Bitmaske, zu löschende Bits=0, unveränderliche=1

PortC = Variable



Ich hoffe, ich hab mich nicht vertan.. :-)

von Paul P. (paul_p792)


Lesenswert?

Dass du jetzt aber eine generelle Funktionsänderung hast ist gewollt?

Vorher:
   If Rot(1) = 0 Then
   Toggle 1r
   End If
   If Rot(2) = 0 Then
   Toggle 2r
   End If
Also egal welchen Wert Rot(1) hatte, der zweite Vergleich wird trotzdem 
ausgeführt.

Jetzt:
   If Rot(1) = 0 Then
   Toggle 1r
   Elseif Rot(2) = 0 Then
   Toggle 2r
Also werden die weiteren Vergleiche nur ausgeführt wenn Rot(1)<>0 ist, 
ansonsten wird alles hinter elseif ignoriert. Gilt dann natürlich analog 
für Rot(2)<>0 usw.

Die erste Version kannst du auch kompakter und damit übersichtlicher 
schreiben:
   If Rot(1) = 0 Then Toggle 1r
   If Rot(2) = 0 Then Toggle 2r
   If Rot(3) = 0 Then Toggle 3r

von Simpel (Gast)


Lesenswert?

Wenn du Elseif statt If verwendest, wird nur die erste erfüllte 
Bedingung ausgeführt und dann der Rest der If-Else-Reihe übersprungen. 
Ich denke nicht, dass das in deinem Sinne ist...

von Simpel (Gast)


Lesenswert?

Paul Pahl war schneller... :)

von tested? (Gast)


Lesenswert?

neuling schrieb:
> So, diese beiden Schnipsel sind geändert:
1
> .
2
> Rotkopie(uzvar) = Rot(uzvar) - X
3
> If Rotkopie(uzvar) < 0 Then
4
>     Rotkopie(uzvar) = 0
5
> End If
6
> .

Rotkopie hat laut "Dim Rotkopie(7) As Byte" Byteelemente. Die Inhalte 
können also nicht kleiner 0 werden, oder. Geht das? Wird 
"Rotkopie(uzvar) = 0" (und gleich aufgebaute Codestücke) irgendwann 
ausgeführt?

von Eric B. (beric)


Lesenswert?

neuling schrieb:
> beim Googeln habe ich keine Möglichkeit
> gefunden zwei Pins auszuschließen aus einer Bitmaskenoperation.
1
var = PortC              ' read port C
2
3
' single pin operations using bitmasks and logic operators
4
var = var AND &b11110111 ' clear  bit 3
5
var = var OR  &b00000100 ' set    bit 2
6
var = var XOR &b00000010 ' toggle bit 1
7
8
PortC = var              ' write back portC

EDIT: Also wenn du bits 0, 1, und 5 "löschen "möchtest:
1
var = var AND &b11011100

: Bearbeitet durch User
von tested? (Gast)


Lesenswert?

Eric B. schrieb:
>
1
> var = PortC              ' read port C
2
> 
3
> ' single pin operations using bitmasks and logic operators
4
> var = var AND &b11110111 ' clear  bit 3
5
> var = var OR  &b00000100 ' set    bit 2
6
> var = var XOR &b00000010 ' toggle bit 1
7
> 
8
> PortC = var              ' write back portC
9
>

Warum mit var und nicht gleich

PORTC = PORTC and &b11110111 ' clear  bit 3

etc

von Eric B. (beric)


Lesenswert?

tested? schrieb:
> Warum mit var und nicht gleich
>
> PORTC = PORTC and &b11110111 ' clear  bit 3
>
> etc

Damit erst das Endergebnis von allen Operationen auf dem Port sichbar 
ist und nicht alle Zwischenschritte. Das wäre in diesem Fall 
wahrscheinlich nicht so relevant, aber tut auch nicht weh :-)

Edit: Man könnte natürlich auch alles in einem Schritt machen. Etwa so:
1
clearBits  = &b11110111
2
setBits    = &b00000100
3
toggleBits = &b11110000
4
5
PortC = ((PortC AND clearBits) OR setBits ) XOR toggleBits

: Bearbeitet durch User
von neuling (Gast)


Lesenswert?

Danke @paul pahl und simpel.
@paul pahl
Brauche ich da kein end if?

@port auf einmal:
Geht das tatsächlich schneller?
Port B und D habe ich jetzt als Register zum Auf-Einmal-setzen, C noch 
manuell.

Kann ich eigentlich auch direkt das Ergebnis einer logischen Aussage wie 
(rot(1)>0) bzw. NOT (rot(4)>0) auf einen Port geben?

Also so:
Portxyz = (rot(1)>0)?

Würde sehr viele if-Abfragen und Codezeilen sparen. Außerdem fällt die 
Toggelei weg und ich schreibe den Wert sauber direkt auf die LEDs statt 
sie zwischendurch kurz anzuschalten.

von greg (Gast)


Lesenswert?

Ich will ja nicht trollen, aber wenn ich mir diesen Code anschaue, dann 
verstehe ich die ab und zu auftauchenden Kommentare nach dem Schema 
"nimm BASCOM, das ist nicht so kryptisch wie C" immer weniger.

von Bastler (Gast)


Lesenswert?

greg schrieb:
> Ich will ja nicht trollen, aber wenn ich mir diesen Code anschaue, dann
> verstehe ich die ab und zu auftauchenden Kommentare nach dem Schema
> "nimm BASCOM, das ist nicht so kryptisch wie C" immer weniger.

Das könnte ein C Anfänger genau so Zeile für Zeile geschrieben haben. 
Dabei wäre dann C auch nicht besser.

Nein - ich programmiere nicht mit BASCOM.

von Paul P. (paul_p792)


Lesenswert?

> Brauche ich da kein end if?
Nicht wenn alles in einer Zeile steht, erst wenn ein ganzer 
Anweisungsblock folgt muss dieser mit endif abgeschlossen werden.

> verstehe ich die ab und zu auftauchenden Kommentare nach dem Schema
> "nimm BASCOM, das ist nicht so kryptisch wie C" immer weniger.
Sehr witzig. Obigen Code versteht sogar mein Kater, bei C würde er nur 
einen Buckel machen und fauchen...

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.