Code: Globale Boolvariable mit INT0 Interrupt auf Tiny13 setzen - Hilfe?

OP Persönliche Seite #1917636
Lesenswert?

Hallo Community,

ich habe, aufbauend auf einem Beispielcode von Karl Heinz Buchegger, nur 
noch eine Funktion zu implementieren und es dann echt geschafft - aber 
die bereitet mir momentan probleme:

Ich möchte über einen hardwareentprellten taster und dem INT0 Interrupt 
bestimmen, ob der µC die Funtion "signal_event" in der mainschleife 
ausführt oder nicht. Zum wechseln ob ja oder nein, dachte ich an die 
if-bedingungen im ISR und eine globale boolvariable.
Bei meinem Code wird über den INT0 immer nur der zweite teil der 
ifbedingung ausgeführt, das heißt die bool ändert sich nicht.

Könnt ihr mir sagen, was ich falsch mache? Sehr viel mehr code passt 
nicht rein, bin momentan bei ca 88%.
1
#include <stdbool.h>
2
#include <stdlib.h>
3
#include <stdint.h>
4

5
#include <avr/io.h>
6
#include <avr/interrupt.h>
7
#include <avr/power.h>
8
#include <avr/sleep.h>
9

10
#define F_CPU 9.6E6
11
#include <util/delay.h>
12

13
#define CLOCK_PRESCALER 256
14
#define TIMER_PRESCALER 1024
15

16
#define TIMER_PERIOD (256 / (F_CPU / CLOCK_PRESCALER / TIMER_PRESCALER))
17

18
#define MEDIAN ( 1 * 60)  /* 10 minutes */
19

20
static uint16_t countdown;
21
static volatile bool timer_expired;
22
volatile bool on;
23

24

25
ISR(TIM0_OVF_vect)
26
{
27
  if (--countdown == 0) {
28
    TCCR0B = 0;  /* turn off timer */
29
    timer_expired = true;
30
    clock_prescale_set(clock_div_1);
31
  }
32
}
33

34
ISR(INT0_vect)
35
{  
36
  if (on)
37
  {
38
    on = false;
39
    
40
    PORTB |= (1<<PB4); // LED 2*flashing: Off
41
    _delay_ms(20);
42
    PORTB &= ~(1<<PB4);
43
    _delay_ms(20);
44
    PORTB |= (1<<PB4); 
45
    _delay_ms(20);
46
    PORTB &= ~(1<<PB4);
47
    _delay_ms(20);
48
  }
49
  else if (!on)
50
  {
51
    on = true;
52
    
53
    PORTB |= (1<<PB4); // LED 1*flashing: On
54
    _delay_ms(20);
55
    PORTB &= ~(1<<PB4);
56
    _delay_ms(20);
57
  }
58
}
59

60
static void starttimer(uint16_t timeout)
61
{
62
  countdown = timeout;
63
  TCNT0 = 0;
64
  timer_expired = false;
65
  clock_prescale_set(clock_div_256);
66
  TCCR0B = _BV(CS02) | _BV(CS00);  /* start timer with prescaler 1024 */
67
}
68

69
static void ioinit(void)
70
{
71
  TIMSK0  = _BV(TOIE0);
72
  GIMSK  |= (1<<INT0); 
73
  MCUCR  |= (1<<ISC01);    // Falling edge
74
  MCUCR  &= ~(1<<ISC00);    // INT0 detection   
75
      
76
  sei();
77
  DDRB = _BV(4);  /* connection for LED or something else */
78
}
79

80
static void signal_event(void)
81
{
82
  PORTB |= _BV(4);
83
  _delay_ms(1000);
84
  PORTB &= ~_BV(4);
85
}
86

87
int
88
main(void)
89
{
90
  ioinit();
91

92
  for (;;) {
93
    int r = rand();
94
    uint16_t timeout = (unsigned)r % (unsigned)(2 * MEDIAN / TIMER_PERIOD) + 1;
95

96
    starttimer(timeout);
97
    do
98
    {
99
      sleep_mode();
100
    }
101
    while (!timer_expired);
102
    
103
  if (on)
104
  signal_event();
105
  }
106
}


Beste Grüße
Gast #1917734
Lesenswert?

Woran erkennst du das? Hast du ein Oszi um ein einzel oder doppelblinken 
der LED zu erkennen bei 20ms on-Zeit?
1
if (do)
2
signal_event()
wird ja erst mach ablauf des Timers ausgeführt. (Nicht überprüft aber 
deinen Kommentaren nach alle 20 Minuten ausgeführt)
OP Persönliche Seite #1917781
Lesenswert?

@maxx:  die 20ms sind keine "echten" 20ms, was vielleicht am sleep mode 
des µCs liegt? die fusebits sind auf 9,6MHz intern gesetzt, trotzdem 
blinkt die led bei 2ms im delay ca 1s auf.

Korrekt, die soll auch erst nach ablaufen des timers ausgeführt (bzw 
nicht ausgeführt) werden - ich überprüfe momentan das "funktionieren" 
der ISR daran, dass eigentlich jedes zweite mal die led 2mal blinken 
sollte, was sie aber nicht tut.

@Johann: sorry, verstehe ich nicht genau. was ist falsch? Die MCUCR 
-registersetzung?
Die ISR wird auf jeden fall bei fallender flanke ausgeführt, das sehe 
ich ja an der (einmal) leuchtenden led. aber diese leuchtet eben immer 
nur einmal, wo sie doch jedes zweite mal zweimal blinken soll. Wo genau 
soll ich etwas ändern?
#1917855
Lesenswert?

Ich nehme mal an die delays in der ISR sind nur zum debuggen, trotzdem 
wuerde ich da empfehlen mal zwei Leds an unterschiedlichen Pins, eine 
fuer jeden If-Zweig zu benutzen.

Wie "gut" ist denn der Taster hardwaremaessig entprellt?

Interrupts sind sehr sensibel.

Versuch das mal in Software zu machen. Mindestens einen Zaehler und erst 
ab einer bestimmten Zaehler-Schwelle on umschalten.

Ju
OP Persönliche Seite #1917887
Lesenswert?

> Wie "gut" ist denn der Taster hardwaremaessig entprellt?
>
> Interrupts sind sehr sensibel.
>
> Versuch das mal in Software zu machen. Mindestens einen Zaehler und erst
> ab einer bestimmten Zaehler-Schwelle on umschalten.


Hallo Jürgen,
also ich hatte noch kein oszi dran, wenn ich den taster aber gedrückt 
halte wird kein interrupt ausgelöst, bis ich loslasse, ich würde also 
davon ausgehen, dass die entprellung passt. entprellt ist mit 33kOhm 
parallel zu 330nF zu ground.

Mit softwareentprellung habe ich so gar keine erfahrung, kann mir da 
jemand ein beispiel nennen, das hier sinnvoll ist? (auch in hinblick auf 
den verbleibenden sehr geringen flashspeicher - ich weiß dass es 
hunderte beiträge irgendwo gibt, aber das ist ja gerade das problem - 
was passt hier?)

Die zweite led wird jetzt angeschlossen..
OP Persönliche Seite #1917913
Lesenswert?

Mit dieser Überprüfung ergibt sich, dass die variable geändert wird 
(denn es blinkt dreimal, wenn die else schleife aufgerufen wird). Danach 
ist sie dann aber wieder auf dem vorherigen wert! wo wird sie 
zurückgesetzt? Was ist da bei der µC programmierung gnadenlos an mir 
vorbei gegangen?
1
ISR(INT0_vect)
2
{
3
  if (on)
4
  {
5
    PORTB |= (1<<PB4); // LED 1*flashing: Off
6
    _delay_ms(2);
7
    PORTB &= ~(1<<PB4);
8
    _delay_ms(10);
9

10
    on = 0;
11
    if (!on)
12
    {
13
      PORTB |= (1<<PB4);
14
      _delay_ms(2);
15
      PORTB &= ~(1<<PB4);
16
      _delay_ms(2);
17
    }
18
  }
19
  else 
20
  {
21
    PORTB |= (1<<PB4); // LED 2*flashing: On
22
    _delay_ms(2);
23
    PORTB &= ~(1<<PB4);
24
    _delay_ms(2);
25
    PORTB |= (1<<PB4); 
26
    _delay_ms(2);
27
    PORTB &= ~(1<<PB4);
28
    _delay_ms(10);
29

30
    on = 1;
31
    if (on)
32
    {
33
      PORTB |= (1<<PB4);
34
      _delay_ms(2);
35
      PORTB &= ~(1<<PB4);
36
      _delay_ms(2);
37
    }
38
  }
39
}

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren