mikrocontroller.net

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


Autor: Alex V. L. (bastel_alex) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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%.
#include <stdbool.h>
#include <stdlib.h>
#include <stdint.h>

#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/power.h>
#include <avr/sleep.h>

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

#define CLOCK_PRESCALER 256
#define TIMER_PRESCALER 1024

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

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

static uint16_t countdown;
static volatile bool timer_expired;
volatile bool on;


ISR(TIM0_OVF_vect)
{
  if (--countdown == 0) {
    TCCR0B = 0;  /* turn off timer */
    timer_expired = true;
    clock_prescale_set(clock_div_1);
  }
}

ISR(INT0_vect)
{  
  if (on)
  {
    on = false;
    
    PORTB |= (1<<PB4); // LED 2*flashing: Off
    _delay_ms(20);
    PORTB &= ~(1<<PB4);
    _delay_ms(20);
    PORTB |= (1<<PB4); 
    _delay_ms(20);
    PORTB &= ~(1<<PB4);
    _delay_ms(20);
  }
  else if (!on)
  {
    on = true;
    
    PORTB |= (1<<PB4); // LED 1*flashing: On
    _delay_ms(20);
    PORTB &= ~(1<<PB4);
    _delay_ms(20);
  }
}

static void starttimer(uint16_t timeout)
{
  countdown = timeout;
  TCNT0 = 0;
  timer_expired = false;
  clock_prescale_set(clock_div_256);
  TCCR0B = _BV(CS02) | _BV(CS00);  /* start timer with prescaler 1024 */
}

static void ioinit(void)
{
  TIMSK0  = _BV(TOIE0);
  GIMSK  |= (1<<INT0); 
  MCUCR  |= (1<<ISC01);    // Falling edge
  MCUCR  &= ~(1<<ISC00);    // INT0 detection   
      
  sei();
  DDRB = _BV(4);  /* connection for LED or something else */
}

static void signal_event(void)
{
  PORTB |= _BV(4);
  _delay_ms(1000);
  PORTB &= ~_BV(4);
}

int
main(void)
{
  ioinit();

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

    starttimer(timeout);
    do
    {
      sleep_mode();
    }
    while (!timer_expired);
    
  if (on)
  signal_event();
  }
}


Beste Grüße

Autor: Alex V. L. (bastel_alex) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
keine ansätze?

Autor: Maxx (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Woran erkennst du das? Hast du ein Oszi um ein einzel oder doppelblinken 
der LED zu erkennen bei 20ms on-Zeit?
if (do)
signal_event()
wird ja erst mach ablauf des Timers ausgeführt. (Nicht überprüft aber 
deinen Kommentaren nach alle 20 Minuten ausgeführt)

Autor: Johann L. (gjlayde) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Alex V. L. (bastel_alex) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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?

Autor: Hc Zimmerer (mizch)
Datum:

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

Autor: Alex V. L. (bastel_alex) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Alex V. L. (bastel_alex) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@Johann - meinst du die fehlende INTF0 im GIF Register?

Autor: Alex V. L. (bastel_alex) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Alex V. L. (bastel_alex) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Juergen G. (jup)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Alex V. L. (bastel_alex) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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..

Autor: Alex V. L. (bastel_alex) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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?
ISR(INT0_vect)
{
  if (on)
  {
    PORTB |= (1<<PB4); // LED 1*flashing: Off
    _delay_ms(2);
    PORTB &= ~(1<<PB4);
    _delay_ms(10);

    on = 0;
    if (!on)
    {
      PORTB |= (1<<PB4);
      _delay_ms(2);
      PORTB &= ~(1<<PB4);
      _delay_ms(2);
    }
  }
  else 
  {
    PORTB |= (1<<PB4); // LED 2*flashing: On
    _delay_ms(2);
    PORTB &= ~(1<<PB4);
    _delay_ms(2);
    PORTB |= (1<<PB4); 
    _delay_ms(2);
    PORTB &= ~(1<<PB4);
    _delay_ms(10);

    on = 1;
    if (on)
    {
      PORTB |= (1<<PB4);
      _delay_ms(2);
      PORTB &= ~(1<<PB4);
      _delay_ms(2);
    }
  }
}

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.