Forum: Mikrocontroller und Digitale Elektronik Zwei Interrupts/Auswertungen gleichzeitig


von Lokus P. (derschatten)


Lesenswert?

Ich möchte gerne Tasten abfragen und gleichzeitig eine LED (Punkt einer 
7-Segment) blinken lassen.
Wie macht man das am geschicktesten?

Ich habe mir dazu dieses Beispiel mal angesehen und ausprobiert:
https://www.mikrocontroller.net/articles/Multitasking
Hier wird das ganze ohne Interrupts gezeigt.

Allerdings funktioniert das bei mir irgendwie nicht:
"Funktion (void blinken(uint8_t taste)"
1
/************************************************************************/
2
/*                                    */
3
/*            Commodore 1541-II Bubble            */
4
/*                Toolbox                  */
5
/*                                    */
6
/************************************************************************/
7
#include <avr/io.h>
8
#include <avr/interrupt.h>
9
#include <avr/eeprom.h>
10
#include <util/delay.h>
11
12
// CPU: ATtiny2313-20PU 8MHz
13
// =======================================================================
14
15
#define LEDS_PORT    PORTB                  // 7-Segment PORT
16
#define TASTER_PORT    PORTA                  // Taster PORT
17
#define SCHALTER_PORT  PORTD                  // Schalter PORT
18
19
#define LEDS_DDR    DDRB
20
#define TASTER_DDR    DDRA
21
#define SCHALTER_DDR  DDRD
22
23
#define TASTER_PIN    PINA
24
25
#define MENU_TASTER    (1 << PA0)
26
#define LICHT_EIN    (PINA & 1 << PA1)
27
28
29
// Schaltmuster
30
// -----------------------------------------------------------------------
31
#define EINSCHALT    0x70                  // 0111 0000
32
#define ALL_LOW      0x00                  // 0000 0000
33
#define ALL_HI      0xFF                  // 1111 1111
34
#define RESET      0x40                  // 0100 0000
35
#define ID_HI      0x30                  // 0011 0000
36
#define ID_8      0x30                  // 0011 0000
37
#define ID_9      0x20                  // 0010 0000
38
#define ID_10      0x10                  // 0001 0000
39
#define ID_11      0x00                  // 0000 0000
40
#define WRITE      0x08                  // 0000 1000
41
42
// Tastendruck
43
// -----------------------------------------------------------------------
44
#define REPEAT_START  50                    // nach 500ms
45
#define REPEAT_NEXT    20                    // alle 200ms
46
47
#define DELAY      50
48
49
// Segment Anzeige
50
// -----------------------------------------------------------------------
51
#define _8        0x7F                  // 0111 1111
52
#define _9        0x67                  // 0110 0111
53
#define _10        0x3F                  // 0011 1111
54
#define _11        0x36                  // 0000 0110
55
#define _I        0x30                  // 0011 0000
56
#define _D        0x5E                  // 0101 1110
57
#define _S        0x6D                  // 0110 1101
58
#define _R        0x50                  // 0101 0000
59
#define _A        0x77                  // 0111 0111
60
#define _C        0x39                  // 0011 1001
61
#define _J        0x1E                  // 0000 1110
62
#define _E        0x79                  // 0111 1001
63
#define _H        0x80                  // 1000 0000
64
65
volatile int8_t nSelect = 0;
66
volatile int8_t ende;
67
volatile uint8_t marker;
68
69
static int8_t lichtval;
70
static int16_t timeCount = 0;
71
static int16_t lichtCount = 0;
72
73
uint8_t key_state;                        // Entprellt und invertierter Tastenstatus:
74
                                // bit = 1: Taste gedrückt
75
uint8_t key_press;                        // Tastendruck erkannt
76
uint8_t key_rpt;                        // Langer Tastendruck mit Wiederholung
77
uint8_t eeprom_floppyid EEMEM = 1;                // Speicherstelle 1 im EEPROM für Floppy-ID
78
uint8_t licht = 1;
79
uint8_t laufwerkid;
80
uint8_t laufwerkidled;
81
82
ISR(TIMER0_OVF_vect)
83
{
84
  static uint8_t ct0, ct1, rpt;
85
  uint8_t i;
86
87
  TCNT0 = (uint8_t)(int16_t)-(F_CPU / 1024 * 10e-3 + 0.5);
88
89
  i = key_state ^ ~TASTER_PIN;                // Taste gewechselt ?
90
  ct0 = ~(ct0 & i);                      // Reset oder zähle ct0
91
  ct1 = ct0 ^ (ct1 & i);                    // Reset oder zähle ct1
92
  i &= ct0 & ct1;                        // count until roll over ?
93
  key_state ^= i;                        // then toggle debounced state
94
  key_press |= key_state & i;                  // 0 -> 1: Tastendruck registrieren
95
96
  if((key_state & MENU_TASTER) == 0)              // Überprüfe Wiederholfunktion
97
    rpt = REPEAT_START;                    // Verzögerung starten
98
  if(--rpt == 0)
99
  {
100
    rpt = REPEAT_NEXT;                    // Wiederhole Verzögerung
101
    key_rpt |= key_state & MENU_TASTER;
102
  }
103
104
  if(timeCount > 0)                      // Timer für Menüwechsel
105
  {
106
    timeCount--;
107
    if(timeCount == 0)
108
    {
109
      nSelect = 0;
110
      ende = 1;
111
    }
112
  }
113
114
  if(lichtCount > 0)                      // Timer für Diskwechselimpuls
115
  {
116
    SCHALTER_PORT |= (WRITE);
117
    lichtCount--;
118
    if(lichtCount == 0)
119
      lichtval = LICHT_EIN;
120
  }
121
122
  if(licht == 0)                        // Schreibschutzerkennung = AUS
123
  {
124
    if(LICHT_EIN)                      // wenn schreibgeschützt (HIGH)
125
    {
126
      SCHALTER_PORT &= ~(WRITE);              // LICHTAUSGANG = LOW / Schreiben erlaubt
127
      marker &= ~(_H);                  // 7-Segment Punkt löschen
128
    }
129
    if(!(LICHT_EIN))                    // wenn nicht schreibgeschützt (LOW)
130
      licht = 1;
131
  }
132
133
  if(licht == 1)                        // Schreibschutzerkennung = EIN
134
  {
135
    if(LICHT_EIN)                      // wenn schreibgeschützt (HIGH)
136
    {
137
      SCHALTER_PORT |= (WRITE);              // LICHTAUSGANG = HIGH / Schreiben nicht erlaubt
138
      marker |= (_H);                    // 7-Segment Punkt anzeigen
139
    }
140
    if(!(LICHT_EIN))                    // wenn nicht schreibgeschützt (LOW)
141
    {
142
      SCHALTER_PORT &= ~(WRITE);              // LICHTAUSGANG = LOW / Schreiben erlaubt
143
      marker &= ~(_H);                  // 7-Segment Punkt löschen
144
    }
145
  }
146
147
  if(licht == 2)                        // Schreibschutzerkennung = IMMER AUS
148
  {
149
    if((LICHT_EIN != lichtval) && (lichtCount == 0))    // wenn schreibgeschützt (HIGH) und Diskwechsel erfolgt
150
      lichtCount = 25;                  // LICHTAUSGANG für 150ms auf HIGH
151
152
    if(LICHT_EIN == lichtval)
153
      SCHALTER_PORT &= ~(WRITE);              // LICHTAUSGANG = LOW / Schreiben nicht erlaubt
154
155
  }
156
}
157
158
uint8_t get_key_press(uint8_t key_mask)
159
{
160
  cli();                            // Lese und lösche Atomic
161
  key_mask &= key_press;                    // Tastenzustand lesen
162
  key_press ^= key_mask;                    // Tastenzustand löschen
163
  sei();
164
  return key_mask;
165
}
166
167
uint8_t get_key_rpt(uint8_t key_mask)
168
{
169
  cli();                            // Lese und lösche Atomic
170
  key_mask &= key_rpt;                    // Tastenzustand lesen
171
  key_rpt ^= key_mask;                    // Tastenzustand löschen
172
  sei();
173
  return key_mask;
174
}
175
176
uint8_t get_key_short(uint8_t key_mask)
177
{
178
  cli();                            // Tastenzustand lesen und Tastendruck Atomic
179
  return get_key_press(~key_state & key_mask);
180
}
181
182
uint8_t get_key_long(uint8_t key_mask)
183
{
184
  return get_key_press(get_key_rpt(key_mask));
185
}
186
187
void blinken(uint8_t taste)
188
{
189
    static uint16_t zaehler=0;
190
191
    if (taste)
192
  {
193
        if (zaehler>=999)
194
    {
195
      marker ^= (_H);
196
            zaehler=0;
197
        }
198
    }
199
    else
200
  {
201
        if (zaehler>=99)
202
    {
203
            marker ^= (_H);
204
            zaehler=0;
205
        }
206
    }
207
  _delay_ms(1);
208
    zaehler++;
209
}
210
211
void floppy_id(int8_t floppyid)
212
{
213
  SCHALTER_PORT |= (ID_HI);                  // Alle ID-PIN = HIGH  
214
  SCHALTER_PORT &= ~(floppyid);                // ID-PIN = LOW
215
216
  switch(floppyid)
217
  {
218
    case ID_8:
219
      laufwerkidled = _8;
220
      break;
221
    case ID_9:
222
      laufwerkidled = _9;
223
      break;
224
    case ID_10:
225
      laufwerkidled = _10;
226
      break;
227
    case ID_11:
228
      laufwerkidled = _11;
229
      break;
230
  }
231
}
232
233
void reset()
234
{
235
  SCHALTER_DDR |= (RESET);                  // ResetPIN = Ausgang
236
  SCHALTER_PORT &= ~(RESET);                  // ResetPIN = LOW
237
  _delay_ms(DELAY);                      // Warten
238
  SCHALTER_DDR &= ~(RESET);                  // ResetPIN = Eingang
239
  SCHALTER_PORT |= (RESET);                  // ResetPIN = PullUp
240
}
241
242
void eeprom_var(void)
243
{
244
  if(eeprom_read_byte(&eeprom_floppyid) != ALL_HI)
245
  {
246
    laufwerkid = eeprom_read_byte(&eeprom_floppyid);    // Floppy-ID aus EEPROM auslesen
247
    floppy_id(laufwerkid);
248
  }
249
}
250
251
void ioinit()
252
{
253
  LEDS_DDR = ALL_HI;                      // 7-SEGMENT-PORT = Ausgang
254
255
  SCHALTER_DDR = ALL_HI;                    // SCHALT-PORT = Ausgang
256
  SCHALTER_PORT = EINSCHALT;                  // EINSCHALT-ZUSTAND
257
258
  TASTER_DDR = ALL_LOW;                    // LICHTSCHRANKE = Eingang
259
  TASTER_PORT = ALL_HI;                    // LICHTSCHRANKE = PullUp
260
261
  TCCR0B = (1 << CS02) | (1 << CS00);              // Interrupt durch 1024 teilen
262
  TIMSK = 1 << TOIE0;                      // Timer Interrupt aktivieren
263
}
264
265
int main(void)
266
{
267
  int32_t val = 0;
268
  ioinit();
269
  reset();
270
  eeprom_var();
271
272
  sei();                            // Interrupts aktivieren
273
274
  for(;;)
275
  {
276
    LEDS_PORT = laufwerkidled | marker;
277
278
    if(get_key_short(MENU_TASTER))
279
    {
280
      timeCount = 300;                  // Zeitzähler auf 5sek setzen
281
      val = 0;                      // Tasterwert zurücksetzen
282
    }
283
284
    while(timeCount > 0)
285
    {
286
      if(get_key_short(MENU_TASTER))
287
      {
288
        timeCount = 300;
289
        val++;                      // Tasterwert um 1 erhöhen
290
      }
291
292
      if(nSelect == 0)                  // Haupt-Menü
293
      {
294
        if (val > 2) val = 0;
295
      }
296
297
      if(nSelect == 1)                  // Floppy-ID Menü
298
      {
299
        if (val > 6) val = 3;
300
      }
301
302
      if(nSelect == 2)                  // Schreibschutz-Menü
303
      {
304
        if (val > 9) val = 7;
305
      }
306
307
      switch(val)
308
      {
309
        // Hauptmenü
310
        case 0:
311
          LEDS_PORT = _I;                // I -> ID
312
          if(get_key_long(MENU_TASTER))
313
          {
314
            val = 3;
315
            nSelect = 1;
316
          }
317
          break;
318
        case 1:
319
          LEDS_PORT = _S;                // S -> Schreibschutz
320
          if(get_key_long(MENU_TASTER))
321
          {
322
            val = 7;
323
            nSelect = 2;
324
          }
325
          break;
326
        case 2:
327
          LEDS_PORT = _R;                // R -> Reset
328
          if(get_key_long(MENU_TASTER))
329
          {
330
            reset();
331
            val = 0;
332
            nSelect = 0;
333
            timeCount = 1;
334
          }
335
          break;
336
337
        // Floppy-ID
338
        case 3:
339
          LEDS_PORT = _8;                // 8 -> ID 8
340
341
          if(get_key_long(MENU_TASTER))
342
          {
343
            floppy_id(ID_8);
344
            eeprom_write_byte(&eeprom_floppyid, ID_8);
345
            reset();
346
            timeCount = 1;
347
          }
348
          break;
349
        case 4:
350
          LEDS_PORT = _9;                // 9 -> ID 9
351
352
          if(get_key_long(MENU_TASTER))
353
          {
354
            floppy_id(ID_9);
355
            eeprom_write_byte(&eeprom_floppyid, ID_9);
356
            reset();
357
            timeCount = 1;
358
          }
359
          break;
360
        case 5:
361
          LEDS_PORT = _10;              // 10 -> ID 10
362
363
          if(get_key_long(MENU_TASTER))
364
          {
365
            floppy_id(ID_10);
366
            eeprom_write_byte(&eeprom_floppyid, ID_10);
367
            reset();
368
            timeCount = 1;
369
          }
370
          break;
371
        case 6:
372
          LEDS_PORT = _11;              // 11 -> ID 11
373
374
          if(get_key_long(MENU_TASTER))
375
          {
376
            floppy_id(ID_11);
377
            eeprom_write_byte(&eeprom_floppyid, ID_11);
378
            reset();
379
            timeCount = 1;
380
          }
381
          break;
382
383
        // Schreibschutzerkennung
384
        case 7:
385
          LEDS_PORT = _A;                // A -> Aus
386
          if(get_key_long(MENU_TASTER))
387
          {
388
            licht = 0;
389
            timeCount = 1;
390
          }
391
          break;
392
        case 8:
393
          LEDS_PORT = _E;                // E -> Ein
394
          if(get_key_long(MENU_TASTER))
395
          {
396
            licht = 1;
397
            timeCount = 1;
398
          }
399
          break;
400
        case 9:
401
          LEDS_PORT = _I;                // I -> Immer
402
          if(get_key_long(MENU_TASTER))
403
          {
404
            lichtval = LICHT_EIN;
405
            licht = 2;
406
            blinken(LICHT_EIN);
407
            timeCount = 1;
408
          }
409
          break;
410
      }
411
    }
412
  }
413
}

Die LED leuchtet ständig.

Allerdings würde ich das ganze gerne mittels Interrupts machen.
Nimmt man sich dazu einen zweiten Timer oder wie geht man da vor?
Oder wie würdet ihr das machen?

von Karl M. (Gast)


Lesenswert?

Hallo,

da fehlt die Init von Pedas Enprellroutine.

ct0 = ct1 = 0xff;

von Regelcop (Gast)


Lesenswert?

Lokus P. schrieb:
> Oder wie würdet ihr das machen?

Ich würde mich erst mal an die Regeln halten.
Du bist lang genug hier angemeldet um das zu wissen.

>>Wichtige Regeln - erst lesen, dann posten!
>>........
>>Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

von Karl M. (Gast)


Lesenswert?

Hallo,

so mit if - then - else Konstrukten hast Du keine Ahnung ?

Oder warum wird mind. 2 mal der Zustand einer Variable abgefragt ?

Dann könnte man der Übersicht halber alles ist Select - Case - Endselect 
verpacken.

von Lokus P. (derschatten)


Lesenswert?

Karl M. schrieb:

> da fehlt die Init von Pedas Enprellroutine.
>
> ct0 = ct1 = 0xff;
Danke für den Hinweis.

> Oder warum wird mind. 2 mal der Zustand einer Variable abgefragt ?
>
Wo meinst du?

: Bearbeitet durch User
von Karl M. (Gast)


Lesenswert?

Guten Morgen Lokus Pokus,

Der Code wird durch diese Schreibweise nicht leserlicher und ist auch 
nicht optimal, in Bezug auf Speichernutzung.
Z.B.
1
if(LICHT_EIN) // wenn schreibgeschützt (HIGH)
2
  { /* .. */ }
3
if(!(LICHT_EIN))  // wenn nicht schreibgeschützt (LOW)
4
  { /* .. */ }

von Lokus P. (derschatten)


Lesenswert?

Karl M. schrieb:
> Guten Morgen Lokus Pokus,
>
> Der Code wird durch diese Schreibweise nicht leserlicher und ist auch
> nicht optimal, in Bezug auf Speichernutzung.
> Z.B.
>
> if(LICHT_EIN) // wenn schreibgeschützt (HIGH)
>   { /* .. */ }
> if(!(LICHT_EIN))  // wenn nicht schreibgeschützt (LOW)
>   { /* .. */ }
Hallo Karl,

da hast du recht, das kann man mit einem ELSE besser lösen.
Danke.

Karl M. schrieb:
> Dann könnte man der Übersicht halber alles ist Select - Case - Endselect
> verpacken.

Was meinst du mit "alles"?

von Einer K. (Gast)


Lesenswert?

Karl M. schrieb:
> Guten Morgen Lokus Pokus,
>
> Der Code wird durch diese Schreibweise nicht leserlicher und ist auch
> nicht optimal, in Bezug auf Speichernutzung.
> Z.B.if(LICHT_EIN) // wenn schreibgeschützt (HIGH)
>   { /* .. */ }
> if(!(LICHT_EIN))  // wenn nicht schreibgeschützt (LOW)
>   { /* .. */ }

? ? ? ?

Hier haben wir einen Programmierer, welcher das if mag.
Und gerne einsetzt.
Auch diese gerne auch 4 bis 5 Ebene tief schachtelt.
Dann ein Switch und da drin noch ein paar if.

Ganz sicher ist sowas nicht mein Stil.
Aber die Schreibweise:
if(dies) tuDas();
if(!dies) TuWasAnderes();
Mindert die Schachtelungstiefe, vermeidet zumindest das else.
Und ist von daher auch gut!

Ansonsten stelle ich den Code auf meinem Monitor recht groß ein, klarer: 
So dass ich den Text flüssig und leicht (konzentrationsschonend) lesen 
kann.

Hier geht das nicht.
Hier ist die Regel, dass ein ganzer Block, also {} und das dazwischen, 
auf eine Bildschirmseite passen muss nicht eingehalten.

Bei dieser Unübersichtlichkeit wäre mir jedes Mittel recht, welches den 
Code "flach" hält.
Mehr als recht.

von DraconiX (Gast)


Lesenswert?

Arduino F. schrieb:
> Aber die Schreibweise:
> if(dies) tuDas();
> if(!dies) TuWasAnderes();
> Mindert die Schachtelungstiefe, vermeidet zumindest das else.
> Und ist von daher auch gut!

Nee, ist nicht gut - kostet Rechenzeit, ist unleserlich und völlig 
Sinnbefreit. Und wenn ich diese Verschachtelungen und 
Mehrfachabfragungen in der Timer ISR sehe - dann wird mir Himmelangst 
und Bange. Und das alles auf nem Tiny23 wo es eh knapp mit den Resourcen 
aussieht. Das das Ding macht was es soll, ist arg verwunderlich.

Wenn man schon ein Art Threading einsetzt, sollte dies auch strukturiert 
sein.

von Lokus P. (derschatten)


Lesenswert?

Tipps wie man es richtig macht?
Bin für alles offen...

Und zu meinem ursprünglichen Problem wäre ich auch für Tipps dankbar.

: Bearbeitet durch User
von Peter II (Gast)


Lesenswert?

Lokus P. schrieb:
> Tipps wie man es richtig macht?
> Bin für alles offen...

dann musst du in Vorleistung gehen und den Code zeigen.

von DraconiX (Gast)


Lesenswert?

Lokus P. schrieb:
> Tipps wie man es richtig macht?

Willst du da meine ehrliche Meinung hören? Wenn ja: Fang neu an! Nimm 
dir ein Papier und ein Stift zur Hand, lese dir folgendes durch: 
https://de.wikipedia.org/wiki/Zustandsdiagramm_(UML) und arbeite deine 
State Machine durch.

Dann wirst du sehen das du vieles, sehr vieles in deinem Code einfach 
verkomplizierst. Das Ergebnis, solltest du es richtig machen, wird ein 
sehr effizienter Code, dein µC wird das machen was du willst und die 
Resourcen reichen für mehr.

von Einer K. (Gast)


Lesenswert?

Lokus P. schrieb:
> Tipps wie man es richtig macht?
> Bin für alles offen...

Keine Funktion länger, als 25 Zeilen
Schachtelungstiefen über 3 werden unleserlich
Schachtelungstiefen über 7 sind böse, Übermenschlichkeit ist gefragt

Variablen heißen nicht val, auch nicht value, denn wir wissen, dass da 
ein Value drin steckt. Ein Variable heißt z.B. keyPressedCount, wenn sie 
die Anzahl Tastendrücke halten soll.



Funktionen kann man auch inline machen.
Damit erhält man die Übersichtlichkeit, vermeidet aber den 
Call-Return-Stack overhead

von Lokus P. (derschatten)


Lesenswert?

ok, wie verhindert man Schachtelungstiefen über 3 ?

Sehr vieles kann in dem Code nicht verkompliziert sein. Der Großteil 
stammt ja von hier aus den Forumsbeispielen.

: Bearbeitet durch User
von Einer K. (Gast)


Lesenswert?

Lokus P. schrieb:
> ok, wie verhindert man Schachtelungstiefen über 3 ?

Hmm...

Vielleicht hast du mich nicht richtig verstanden...

Mein Priorität lag eher auf:
Arduino F. schrieb:
> Keine Funktion länger, als 25 Zeilen
Damit erledigt sich das andere Problem meist gleich mit.


Also den Code in sinnvolle Teilbereiche aufteilen.
Diese Teilbereiche lassen sich dann auch gut einzeln testen.

Man muss sich ja nicht sklavisch an die 25 Zeilen halten...
Aber als Richtwert... geht das schon...

von Lokus P. (derschatten)


Lesenswert?

Nur ich sehe bei meinem Code nicht wirklich den Sinn etwas auszulagern.
Die CASE? Die IF?

Maximal einige Teile im Interrupt.

Wozu gibt es denn die Hauptschleife, wenn man da nicht die meisten Code 
hin setzt?

Bisher leider nur sehr oberflächliche Tipps.

Und mein Hauptproblem kann ich damit auch nicht lösen.

: Bearbeitet durch User
von Einer K. (Gast)


Lesenswert?

Lokus P. schrieb:
> Und mein Hauptproblem kann ich damit auch nicht lösen.

Dein Hauptproblem ist offensichtlich, dass dein Programm nicht tut was 
es soll. Und wenn es übersichtlich wäre, dann würdest du den Fehler 
vermutlich schnell finden. Es ist aber nicht so übersichtlich, dass du 
den Fehler schnell findest.
Und ich finde ihn auch nicht.
Mir stellen sich die Nackenhaare auf, wenn dich die Wurst sehe.

Ich wende mich ab.

von Lokus P. (derschatten)


Lesenswert?

Das Grundprogramm funktioniert problemlos.
Lediglich das "blinken" Beispiel aus meinem ersten Beitrag funktioniert 
nicht.

Ich mach das nur als Hobby nicht beruflich, somit werde ich hier niemals 
perfekt optimierten CODE herbeizaubern können.

: Bearbeitet durch User
von Einer K. (Gast)


Lesenswert?

Lokus P. schrieb:
> Lediglich das "blinken" Beispiel aus meinem ersten Beitrag funktioniert
> nicht.

Dann dividiere das Blinken aus der Wurst raus.
Betrachte das Blinken als einen eigenständigen endlichen Automaten.
Eine einzige globale Variable reicht. Eigentlich so gar nur ein Bit.
Ich nenne das Bit z.B. "Blinkanforderung"
Programmiere es so, dass dein Blinken "nebenläufig" arbeitet.

Teste es einzeln.

von Route_66 H. (route_66)


Lesenswert?

Lokus P. schrieb:
> Ich mach das nur als Hobby nicht beruflich, somit werde ich hier niemals
> perfekt optimierten CODE herbeizaubern können.

Es geht doch nicht um perfekt optimierten Code, sondern um 
übersichtliche Strukturen des Programmtextes.

Zum Blinken: ich nutze gern ein Verfahren das mir erlaubt, mitten im 
Programmablauf einfach einer Bytevariable (z.B. blink) einen Wert 
zuzuweisen und die LED blinkt ganz automatisch in einem bestimmten 
Muster:
blink = 0 -> LED aus
blink= 255 -> LED dauernd an
blink= 0b11110000 -> LED blinkt langsam
blink = 0b10101010 -> LED blinkt schnell
blink = 0b10000000 -> LED blitzt regelmäßig kurz auf
uws.

Dazu wird im Timer-Interrupt die Variable blink in regelmäßigen 
Abständen durch das Carry rotiert und dieses Flag zum LED-Pin gesandt.
Ganz einfach.

von Dieter F. (Gast)


Lesenswert?


von Lokus P. (derschatten)


Lesenswert?

Dieter F. schrieb:
> Beitrag "Externe Signale mit AVR Schalten"

Ja, was ist damit?
Hast du etwas dazu beizutragen?

von Dieter F. (Gast)


Lesenswert?

Lokus P. schrieb:
> Ja, was ist damit?

Hilft ein wenig zu verstehen, wo Du unterwegs bist - mehr nicht. Ggf. 
könntest Du ja auch einen Schaltplan einstellen - evtl. ist ja nicht 
unbedingt (nur) die Logik ursächlich.

(Habe übrigens selbst noch einen Brotkasten - aber kein Dolphin-DOS)

Lokus P. schrieb:
> Hast du etwas dazu beizutragen?

Ja, ich würde die Variable "licht" volatile deklarieren.

Lokus P. schrieb:
1
 static int8_t lichtval;
2
 static int16_t timeCount = 0;
3
 static int16_t lichtCount = 0;

Und da passt auch was nicht ... die verwendest Du doch auch in der ISR - 
oder?

Lokus P. schrieb:
1
 TCNT0 = (uint8_t)(int16_t)-(F_CPU / 1024 * 10e-3 + 0.5);

Dieses Konstrukt muss man erst mal verstehen ..

von dummschwaetzer (Gast)


Lesenswert?

Hallo,
mach mal bei deinen ganzen #define die Kommentare weg, z.B:
org:
#define EINSCHALT    0x70                  // 0111 0000
geändert:
#define EINSCHALT    0x70

von Lokus P. (derschatten)


Lesenswert?

Dieter F. schrieb:
> static int8_t lichtval;
>  static int16_t timeCount = 0;
>  static int16_t lichtCount = 0;
>
> Und da passt auch was nicht ... die verwendest Du doch auch in der ISR -
> oder?

Nicht nur, auch im main.

Dieter F. schrieb:
> TCNT0 = (uint8_t)(int16_t)-(F_CPU / 1024 * 10e-3 + 0.5);
>
> Dieses Konstrukt muss man erst mal verstehen ..

Muß man das, wenns funktioniert.
Aber ich denke das kann am besten der Peter beantworten. Das stammt von 
ihm und ist Teil der Tastenentprellung: 
https://www.mikrocontroller.net/articles/Entprellung

dummschwaetzer schrieb:
> Hallo,
> mach mal bei deinen ganzen #define die Kommentare weg, z.B:
> org:
> #define EINSCHALT    0x70                  // 0111 0000
> geändert:
> #define EINSCHALT    0x70

Ähm, warum?

: Bearbeitet durch User
von dummschwaetzer (Gast)


Lesenswert?

spiel mal präprozessor:
#define Name Ausdruck //Kommentar
im Programm:
if(Name)
wird eventuell ersetzt durch
if(Ausdruck //Kommentar)

von Lokus P. (derschatten)


Lesenswert?

Wird das in die IF-Schleife mit einbezogen?
Welche Auswirkung hat das denn?

Ich kann hier leider nicht folgen aufgrund fehlenden Wissens.

Wie sollte man sonst mit Kommentaren umgehen?

: Bearbeitet durch User
von S. R. (svenska)


Lesenswert?

Lokus P. schrieb:
> Wird das in die IF-Schleife mit einbezogen?

Erstens: ES GIBT KEINE IF-SCHLEIFEN.
Zweitens: Ja, der C-Präprozessor versteht kein C.

Lokus P. schrieb:
> Welche Auswirkung hat das denn?

Ein Doppelslash leitet einen Kommentar bis zum Ende der Zeile ein. Der 
frisst im Zweifelsfall keine Klammer weg und führt zu Syntaxfehlern.

Nutze einfach normale C-Kommentare,
also mit /* anfangen und mit */ aufhören.

: Bearbeitet durch User
von Dieter F. (Gast)


Lesenswert?

Lokus P. schrieb:
> Welche Auswirkung hat das denn?

Verzeih bitte, wenn ich das krass ausdrücke:

"Ich kann nicht irgendetwas in die Gegend rotzen und hoffen, dass andere 
es schon richten."

Du wirst Dich also selbst kümmern müssen oder einen Kümmerer finden 
(gegen Entgelt), der Dir das richtet.

von A. S. (Gast)


Lesenswert?

dummschwaetzer schrieb:
> if(Name)
> wird eventuell ersetzt durch
> if(Ausdruck //Kommentar)

Der Code ist nicht optimal. Und // ist nicht ANSI C, wird aber von den 
allermeisten Compilern unterstützt. Aber solche Kommentare erschweren es 
dem UP dann doch, nützliche Hilfestellungen von dummgeschwaetztem zu 
unterscheiden.

von Lokus P. (derschatten)


Lesenswert?

Route 6. schrieb:

> Muster:
> blink = 0 -> LED aus
> blink= 255 -> LED dauernd an
> blink= 0b11110000 -> LED blinkt langsam
> blink = 0b10101010 -> LED blinkt schnell
> blink = 0b10000000 -> LED blitzt regelmäßig kurz auf
> uws.
>
> Dazu wird im Timer-Interrupt die Variable blink in regelmäßigen
> Abständen durch das Carry rotiert und dieses Flag zum LED-Pin gesandt.
> Ganz einfach.

Kannst du mir das genauer erläutern wie das im Interrupt aussehen muß?
Wo genau definiere ich denn dann die Blinkzeit?

Dieter F. schrieb:
> Du wirst Dich also selbst kümmern müssen oder einen Kümmerer finden
> (gegen Entgelt), der Dir das richtet.

Warum soll ich das andere machen lassen? Das macht ja Spass dran 
herumzubasteln, sonst wäre ich ja nicht hier. Ich suche mir nur Tipps 
zusammen.

: Bearbeitet durch User
von Dieter F. (Gast)


Lesenswert?

Lokus P. schrieb:
> Ich suche mir nur Tipps
> zusammen.

Nö,

Dieter F. schrieb:
> "Ich kann nicht irgendetwas in die Gegend rotzen und hoffen, dass andere
> es schon richten."

So sieht es aus und nicht anders. Mehr sage (schreibe) ich nicht dazu.

von S. R. (svenska)


Lesenswert?

Lokus P. schrieb:
> Kannst du mir das genauer erläutern wie das im Interrupt aussehen muß?

Nö. Dafür gibt es Tutorials.

von Lokus P. (derschatten)


Lesenswert?

Ja? Wie nennt sich denn das "Verfahren" ?

von Zitadelle (Gast)


Lesenswert?

Dieter F. schrieb:
> So sieht es aus und nicht anders. Mehr sage (schreibe) ich nicht dazu.

Halte Dich dann aber auch dran. Das wäre sehr hilfreich für den weiteren 
Fortgang.

von Dieter F. (Gast)


Lesenswert?

Zitadelle schrieb:
> Halte Dich dann aber auch dran. Das wäre sehr hilfreich für den weiteren
> Fortgang.

Gäste-Kommentare blende ich dazu mal aus :-)

von Lokus P. (derschatten)


Angehängte Dateien:

Lesenswert?

Ich habe nun was gefunden das wunderbar funktioniert:

1
int16_t timerFreq = 1000; 
2
int16_t ledCount = 1000;
3
int8_t ledFreq = 10;
4
5
...
6
// Im Interrupt: 
7
8
  ledCount -= ledFreq;
9
10
  if (ledCount <= 0)
11
  {
12
     marker ^= (_H);
13
    ledCount += timerFreq;
14
  }

Was mir jetzt allerdings sehr seltsam vorkommt ist, dass es genau so 
funktioniert wie ich gerne hätte.
Nur warum?

Der Interrupt sollte doch ständig laufen, und die LED auch immer 
blinken.
Tatsächlich blinkt sie jedoch nur dann wenn die Variable licht=2 ist.

Warum?

Kompletter code im Anhang...

: Bearbeitet durch User
von Walter S. (avatar)


Lesenswert?

dummschwaetzer schrieb:
> spiel mal präprozessor:
> #define Name Ausdruck //Kommentar
> im Programm:
> if(Name)
> wird eventuell ersetzt durch
> if(Ausdruck //Kommentar)

was heißt eventuell?
Bei gcc jedenfalls schon Mal nicht,
was für einen Compiler verwendest du?

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.