Forum: Mikrocontroller und Digitale Elektronik Code: Globale Boolvariable mit INT0 Interrupt auf Tiny13 setzen - Hilfe?


von Alex V. (bastel_alex) Benutzerseite


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

von Alex V. (bastel_alex) Benutzerseite


Lesenswert?

keine ansätze?

von Maxx (Gast)


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)

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Die Initialisierung der Flanker-IRQ ist falsch, so daß u.U. der 
angenommene Zusammenhang zwischen fallender Flanke und on nicht besteht.

#1 die betreffende IRQ ist inaktiv
#2 Gewünschte Flanke einstellen
#3 IRQ-Flag löschen
#4 betreffende IRQ aktivieren

von Alex V. (bastel_alex) Benutzerseite


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?

von Hc Z. (mizch)


Lesenswert?

countdown ist nicht volatile, wird aber als Übergabe an den Interrupt 
verwendet.

von Alex V. (bastel_alex) Benutzerseite


Lesenswert?

die ganze geschichte mit dem timer(und seinen interrupts) funktioniert 
bereits einwandfrei (inklusive der zugehörigen funktionen).

Blos der externe Interrupt INT0 und alles was dazugehört
(also die bool on, ISR(INT0_vect), sowie die bezügliche Registersetzung 
in ioinit()) machen faxen.

von Alex V. (bastel_alex) Benutzerseite


Lesenswert?

@Johann - meinst du die fehlende INTF0 im GIF Register?

von Alex V. (bastel_alex) Benutzerseite


Lesenswert?

noch eine (vielleicht unnötige) korrektur fürs verständnis: Der 
kommentar neben der Definition #define MEDIAN ist falsch, momentan ist 
es eine ("1")minute.

von Alex V. (bastel_alex) Benutzerseite


Lesenswert?

ich sitze hier echt auf dem trockenen.. wenn ich die boolesche in 
ioinit() mit true initialisiere, wird NUR NOCH der erste teil der 
schleife in der ISR(INT0_vect) aufgerufen, aber auch das immer. Es 
scheint also so, als ob die boolesche nicht (innerhalb der schleife) 
verändert wird/werden kann.

von Juergen G. (jup)


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

von Alex V. (bastel_alex) Benutzerseite


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..

von Alex V. (bastel_alex) Benutzerseite


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
}

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.