mikrocontroller.net

Forum: Compiler & IDEs Komm net drauf :-(


Autor: ghost (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi!

Hier mal mein Gesamtprogramm...

Ich habe noch nicht viel verändert, da ich mir über die Timer nicht ganz 
im klaren bin.

Müsste ich die Timer Einstellungen in die while(g_run) Schleife 
schreiben, damit sie erst beim Start anfangen zu zählen?

Und mach ich dann im Timeroverflow Interrupt eine Schleife die 
Hochzählt?

#include <avr/io.h>
#include <inttypes.h>
#include <avr/delay.h>      // definiert _delay_ms()
#include <avr/interrupt.h>
#include <util/delay.h>     // aktuelle Version in util
#include <stdio.h>
#include <stdio.h>
#include <stdlib.h>
#ifndef F_CPU
#define F_CPU 3686400UL     // Quarz mit 3.6864 Mhz ?? noch prüfen!!
#endif

#define true 1
#define false 0


// Funktion zum Entprellen
inline uint8_t debounce(volatile uint8_t *port, uint8_t pin)
{
    if ( ! (*port & (1 << pin)) )
    {
        // Pin wurde auf Masse gezogen, 100ms warten
        _delay_ms(100);
        if ( *port & (1 << pin) )
        {
            // Anwender Zeit zum Loslassen des Tasters geben
            _delay_ms(100);
            return 1;
        }
    }
    return 0;
};


//---------------- Global variables ------------------------

char g_run; // Variable zum Stoppen
int g_count; // Zähler

// ---------------------------------------------------------

// --------------- Interrupt zum Umschalten von g_run ------
ISR(INT0_vect)
{
  // toggle
  g_run = false;
}

// --------------- Interrupt bei Timeroverflow --------------
ISR(TIMER1_OVF_vect)
{
  g_count = 0;
  g_count++;



int main(void)
{
  DDRD = 0x00; // Port D ist Eingang
  PORTD = 0xFF; // interne Pullup-Widerstände aktiviert

  DDRB = 0xFF; // Port B ist Ausgang
  PORTB = 0x00;
  EICRA |= (1<<ISC01); // Fallende Flanke löst Interrupt aus
  EIMSK |= (1<<INT0);

  TIMSK |= (1<<TOIE1); // Bei Überlauf des Datenregisters von Timer 1 
wird Timer Overflow 1 Interruot ausgelöst

  //Konfiguration von Timer 1
  TCCR1A = 0x00; // Timer 1 ohne Outputpins und ohne PWM
  TCCR1B |= (1<<CS12) | (1<<CS10); // CPU-Takt/ 1024


  sei(); // Interrupts eingeschaltet

  g_run = 1;

  while( ! debounce(&PIND, PD0) );    //Wenn Taster an PIN PD0 gedrueckt 
wird while verlassen.

  while(g_run == 1)
  {
    int i;
    long j;
    i = rand() % 20; // Generierung der "Pulsbreite"
    j = rand() % 20; // Generierung der Zeit zwischen zwei Pulsen
    j = j * 60000; // Umrechnung in Millisekunden
    _delay_ms(j); // Verzögerungszeit zwischen zwei Pulsen
    PORTB |= (1<<PB0); // PB0 auf high
    _delay_ms(i); // PB0 für 1-20 ms auf high
    PORTB &= ~ (1<<PB0); // PB0 wieder auf low
    PORTB |= (1<<PB1); // PB1 auf high
    _delay_ms(10); // PB1 immer für 10 ms auf high
    PORTB &= ~ (1<<PB1); // PB1 wieder auf low
  };


  cli(); // Interrupts ausgeschaltet

  while(1);
  return 0;
}

Danke für eure Hilfe...

Autor: johnny.m (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> j = j * 60000; // Umrechnung in Millisekunden
> _delay_ms(j); // Verzögerungszeit zwischen zwei Pulsen
Hatten wir das nicht schon mal? Die _delay_xx-Funktionen funktionieren 
nur dann korrekt, wenn sie mit zur compile-Zeit bekannten Konstanten 
Werten aufgerufen werden und sie sind in Abhängigkeit von der 
CPU-Frequenz begrenzt!

> Und mach ich dann im Timeroverflow Interrupt eine Schleife die Hochzählt?
Zählschleifen haben in einer ISR eigentlich nichts verloren.

Was soll das Programm überhaupt machen? Warum postest Du sowas nicht in 
Deinem originalen Thread? Dann müsste man sich jetzt nicht den anderen 
Thread raussuchen um zu erfahren worum es eigentlich geht!

Autor: Jörg Wunsch (dl8dtl) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Außerdem fehlt mindestens bei g_run auf jeden Fall das "volatile".

Autor: Falk (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@ ghost

>Hier mal mein Gesamtprogramm...

Aha, es geht immer noch um die 1..20 min Verzögerung zur LED-Ansteuerung

>Und mach ich dann im Timeroverflow Interrupt eine Schleife die
>Hochzählt?

Nö.

>#define true 1
>#define false 0

Das kannst du dir sparen.

>// --------------- Interrupt bei Timeroverflow --------------
>ISR(TIMER1_OVF_vect)
>{
>  g_count = 0;
>  g_count++;

} fehlt hier

Die Initialisierung sieht mal gut aus. Dein Main läuft dann eigentlich 
nur noch in einer Endlosschleife etwas so

while(1);

Die Schow findet im Interrupt statt.

// --------------- Interrupt bei Timeroverflow --------------
ISR(TIMER1_OVF_vect)
{
  static uin16_t i, j;
  static uin8_t state=0;

  switch (state)
  {
   case 0:        // start, get new random values
      i = rand() % 20;   // Generierung der "Pulsbreite"
      j = rand() % 20;   // Generierung der Zeit zwischen zwei Pulsen
      j = j * 60000;     // Umrechnung in Millisekunden
      state = 1;
    break;

   case 1:        // first delay
      j--;
    if (j==0) state =2;
    break;

   case 2:        // first LED action
      PORTB |= (1<<PB0); // PB0 auf high
    state =3;
    break;

   case 3:        // second delay
      i--;
    if (i==0) state =4;
    break;

   case 4:        // second LED action
      PORTB &= ~ (1<<PB0); // PB0 wieder auf low
      PORTB |= (1<<PB1); // PB1 auf high
    state =5;
      i = 10;
    break;

   case 5:        // second delay
      i--;
    if (i==0) state =6;
    break;

   case 6:        // third LED action
      PORTB &= ~ (1<<PB1); // PB1 wieder auf low
    state =0;
    break;

  default: state = 0;      // just in case ;-)
  }
}

MfG
Falk

Autor: Jupp (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>> #define true 1
>> #define false 0

> Das kannst du dir sparen.

Nö.

#define TRUE 1
#define FALSE 0

könnte er sich sparen.


Autor: Falk (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@ Jupp

>>> #define true 1
>>> #define false 0

>> Das kannst du dir sparen.

>Nö.

>#define TRUE 1
>#define FALSE 0

>könnte er sich sparen.

Warum muss ich da gerade wieder an eine griechische Stadt mit K und den 
Auswurf von Exkrementen denken . . .?

MFG
Falk


Autor: ghost (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@Falk

Merci, sowas hab ich gesucht.

Autor: Falk (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@ ghost

>Merci, sowas hab ich gesucht.

Ich hoffe du verstehst auch den Unterschied?

MFG
Falk


Autor: ghost (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>Ich hoffe du verstehst auch den Unterschied?

Ich denke schon.

Der Compiler scheint nur die zwei Zeilen net zu mögen:

  static uin16_t i, j;
  static uin8_t state=0;

main.c:53: error: expected '=', ',', ';', 'asm' or '__attribute__' 
before 'i'
main.c:53: error: 'i' undeclared (first use in this function)
main.c:53: error: (Each undeclared identifier is reported only once
main.c:53: error: for each function it appears in.)
main.c:53: error: 'j' undeclared (first use in this function)
main.c:53: warning: left-hand operand of comma expression has no effect
main.c:53: warning: statement with no effect
main.c:56: error: 'state' undeclared (first use in this function
)

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
ghost wrote:
>>Ich hoffe du verstehst auch den Unterschied?
>
> Ich denke schon.
>
> Der Compiler scheint nur die zwei Zeilen net zu mögen:
>
>   static uin16_t i, j;
>   static uin8_t state=0;
>
> main.c:53: error: expected '=', ',', ';', 'asm' or '__attribute__'
> before 'i'

mach noch ein
#include <stdint.h>
ganz an den Anfang.

Der Compiler weiss nicht was ein uint16_t ist. stdint.h
enthält die dazu notwendigen Definitionen.

Autor: johnny.m (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Da fehlen ja auch zwei 't'! uin8_t und uin16_t findet er sicher auch mit 
der stdint.h nicht...

Autor: Falk (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@ johnny.m

>Da fehlen ja auch zwei 't'! uin8_t und uin16_t findet er sicher auch mit
>der stdint.h nicht...

Ich sach nur Licherkette. An alle Badesalz-Fans ;-)

MFG
Falk


Autor: johnny.m (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> ...Licherkette...
Ne Krombacherkette wär mir lieber...

Autor: ghost (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
So schaut jetzt main() aus:

int main(void)
{
  DDRD = 0x00; // Port D ist Eingang
  PORTD = 0xFF; // interne Pullup-Widerstände aktiviert

  DDRB = 0xFF; // Port B ist Ausgang
  PORTB = 0x00;

  // ------- Einstellungen für Ext. Interrupt zum Stoppen des Programms 
----
  EICRA |= (1<<ISC01); // Fallende Flanke löst Interrupt aus
  EIMSK |= (1<<INT0);
  // 
-----------------------------------------------------------------------


  TIMSK1 |= (1<<TOIE1); // Bei Überlauf des Datenregisters von Timer 1 
wird Timer Overflow 1 Interrupt ausgelöst

  //Konfiguration von Timer 1
  TCCR1A = 0x00; // Timer 1 ohne Outputpins und ohne PWM
  TCCR1B |= (1<<CS12) | (1<<CS10); // 3,6864MHZ/ 1024 = 3600 Hz


  sei(); // Interrupts eingeschaltet

  g_run = 1;

  while( ! debounce(&PIND, PD0) );    //Wenn Taster an PIN PD0 gedrueckt 
wird, wird while verlassen

  cli(); // Interrupts ausgeschaltet

  while(1);
  return 0;
}

Ich habe in switch mal i recht groß gemacht um ein Blinken zu sehen, 
aber es tut sich nix. Hab ich in main noch nen groben Bock drin??

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
ghost wrote:
> So schaut jetzt main() aus:

...

>
>   sei(); // Interrupts eingeschaltet
>
>   g_run = 1;
>
>   while( ! debounce(&PIND, PD0) );    //Wenn Taster an PIN PD0 gedrueckt
> wird, wird while verlassen
>
>   cli(); // Interrupts ausgeschaltet
>
>   while(1);
>   return 0;
> }

Wenn du mittels cli() die Interrupts global ausschaltest, kannst
du lange warten, bis ein Overflow Interrupt durchkommt. Die
eigentliche Arbeit wird während

   while(1)
     ;

im Hintergrund von einer ISR (Interrupt Service Routine) erledigt.
Die muss aber auch aufgerufen werden können! Das kann sie aber
nicht, wenn du mittels cli() die Interrupts sperrst.

Autor: Regler (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@Falk

>Warum muss ich da gerade wieder an eine griechische Stadt mit K und den
>Auswurf von Exkrementen denken . . .?

Keine Ahnung, vielleicht hast du ein Problem mit deiner Verdauung?

Wie auch immer, ich wollte es nur klarstellen, denn ich hasse 
Halbwissen, welches du hier gezeigt hast. LOL


Autor: ghost (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Also irgendwie funzt es net so wie ich will.

Das Programm soll nach 1- 20 Minuten einen Pin für ca 10 ms auf high 
legen und dann wieder auf low. Sofort danach einen anderen Pin auf high 
für ca 10 ms und dann wieder auf low. Und das ganze halt immer wieder 
bis man stoppen will.

Und halt noch ne Stop-Taste, die aber schon funktioniert ( mit dem 
externen interrupt).

Der Vorschlag von Falk ist ja ok, aber da muss ich doch irgendwie noch 
meine Frequenz anpassen? Könnte da der Fehler liegen?

Autor: Jörg Wunsch (dl8dtl) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Regler wrote:

> Wie auch immer, ich wollte es nur klarstellen, denn ich hasse
> Halbwissen, welches du hier gezeigt hast. LOL

Du meinst, solcherart wie du gerade zur Schau stellst?  (Falls Regler
derselbe wie Yupp sein sollte.)

Guck dir mal <stdbool.h> von C99 an.

Autor: Regler (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Tja, dann muß ich das wohl zurücknehmen.

Dennoch ist es schon bescheuert, dass einerseits in der von dir 
genannten Datei

#define true 1
#define false 0

auftaucht, man aber andererseits ohne die Inkludierung dieser Datei

#define TRUE 1
#define FALSE 0

definiert wurde, wo auch immer. Frei nach dem Motto: doppelt gemoppelt 
hält besser.

Autor: Jörg Wunsch (dl8dtl) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Regler wrote:

> auftaucht, man aber andererseits ohne die Inkludierung dieser Datei
>
> #define TRUE 1
> #define FALSE 0
>
> definiert wurde, wo auch immer.

Wo denn?  Bei mir nicht.  Keine der avr-libc- oder GCC-Headerdateien
bringt das mit.
$ cat foo.c
#include <avr/io.h>

int
main(void)
{
        return TRUE;
}
$ avr-gcc -mmcu=atmega1281 -c foo.c
foo.c: In function 'main':
foo.c:6: error: 'TRUE' undeclared (first use in this function)
foo.c:6: error: (Each undeclared identifier is reported only once
foo.c:6: error: for each function it appears in.)

Autor: ghost (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hab des Programm jetzt so geschrieben:

#include <avr/io.h>
#include <inttypes.h>
#include <avr/delay.h>      // definiert _delay_ms()
#include <avr/interrupt.h>
#include <util/delay.h>     // aktuelle Version in util
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#ifndef F_CPU
#define F_CPU 3686400UL     // Quarz mit 3.6864 Mhz ?? noch prüfen!!
#endif

#define true 1
#define false 0


// -------- Funktion zum Entprellen --------------------------
inline uint8_t debounce(volatile uint8_t *port, uint8_t pin)
{
    if ( ! (*port & (1 << pin)) )
    {
        // Pin wurde auf Masse gezogen, 100ms warten
        _delay_ms(100);
        if ( *port & (1 << pin) )
        {
            // Anwender Zeit zum Loslassen des Tasters geben
            _delay_ms(100);
            return 1;
        }
    }
    return 0;
};


//---------------- Global variables ------------------------

char g_run; // Variable zum Stoppen

// ---------------------------------------------------------

// --------------- Interrupt zum Umschalten von g_run ------
ISR(INT0_vect)
{
  // toggle
  g_run = false;
}

// --------------- Interrupt bei Timeroverflow --------------
ISR(TIMER1_OVF_vect)
{
  static uint16_t i, j;
  static uint8_t state=0;

  switch (state)
  {
    case 0:        // Start, Erzeugung der neuen Zufallszahlen
    i = rand() % 20;   // Generierung der "Pulsbreite"
    j = rand() % 20;   // Generierung der Zeit zwischen zwei Pulsen
    j = j * 60000;     // Umrechnung in Millisekunden

    state = 1;
    break;

    case 1:        // Erste Verzögerung: 1 - 20 Minuten
    j--;
    if (j==0) state =2;
    break;

    case 2:
    PORTB |= (1<<PB0); // PB0 auf high
    state =3;
    break;

    case 3:        // Verzögerung 1 - 20 ms
    i--;
    if (i==0) state =4;
    break;

    case 4:
    PORTB &= ~ (1<<PB0); // PB0 wieder auf low
    PORTB |= (1<<PB1); // PB1 auf high
    state =5;
    i = 10;
    break;

    case 5:        // 10ms Verzögerung
    i--;
    if (i==0) state =6;
    break;

    case 6:
    PORTB &= ~ (1<<PB1); // PB1 wieder auf low
    state =0;
    break;

    default: state = 0;
  }
}


int main(void)
{
  DDRD = 0x00; // Port D ist Eingang
  PORTD = 0xFF; // interne Pullup-Widerstände aktiviert

  DDRB = 0xFF; // Port B ist Ausgang
  PORTB = 0xFC;

  // ------- Einstellungen für Ext. Interrupt zum Stoppen des Programms 
----
  EICRA |= (1<<ISC01); // Fallende Flanke löst Interrupt aus
  EIMSK |= (1<<INT0);
  // 
-----------------------------------------------------------------------
  sei(); // Interrupts eingeschaltet

  g_run = 1;
  while( ! debounce(&PIND, PD0) );    //Wenn Taster an PIN PD0 gedrueckt 
wird, wird while verlassen
  while(g_run == 1)
  {
  TIMSK1 |= (1<<TOIE1); // Bei Überlauf des Datenregisters von Timer 1 
wird Timer Overflow 1 Interrupt ausgelöst

  //Konfiguration von Timer 1
  TCCR1A = 0x00; // Timer 1 ohne Outputpins und ohne PWM
  TCCR1B |= (1<<CS12) | (1<<CS10); // 3,6864MHZ/ 1024 = 3600 Hz




  };



  while(1);
  return 0;
}

Jetzt sollte es doch eigentlich beim drücken des Tasters an Pin PD0 
starten und solange durchlaufen bis ich den externen Interrupt durch 
drücken des Tasters an PD2 auslöse.

Das ganze ist ein kleines Teil für meine BA und sollte mich eigentlich 
nicht zu lange damit aufhalten ( auch wenn ich das Programmieren schon 
interessant finde...)

Habe ich evtl. den Overflow Vektor falsch gewählt? Oder noch ein 
Register falsch belegt?

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
ghost wrote:

> Habe ich evtl. den Overflow Vektor falsch gewählt? Oder noch ein
> Register falsch belegt?

Schmeiss mal das ganze Gerödel mit deinen Tastern raus.
Da blickt doch keiner mehr durch.

Halte dich an das einfache Schema:

int main()
{

   alles initialisieren

   //
   // Endlosschleife und den Timer Interrupt
   // machen lassen
   //
   while(1)
     ;
}

Dazu packst du dann noch die ISR und alles was an globalen
Variablen dazugehört. Dann setzt du den Vorteiler für
den Timer mal auf 1 (*) und gehst mit dem Ganzen in den Simulator
zum durchdebuggen.


(*) 1 deswegen, damit du dir im Simulator keinen Wolf auf der
F10 Taste tippst um den Timerwert um 1 zu erhöhen.

Autor: Falk (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@ ghost

Deine Programmierkenntnisse sind wohl schon ein wenig arg rostig, was?

int main(void)
{
  DDRD = 0x00; // Port D ist Eingang
  PORTD = 0xFF; // interne Pullup-Widerstände aktiviert

  DDRB = 0xFF; // Port B ist Ausgang
  PORTB = 0xFC;

  // ------- Einstellungen für Ext. Interrupt zum Stoppen des Programms
----
  EICRA |= (1<<ISC01); // Fallende Flanke löst Interrupt aus
  EIMSK |= (1<<INT0);
  //

  TIMSK1 |= (1<<TOIE1); // Bei Überlauf des Datenregisters von Timer 1
wird Timer Overflow 1 Interrupt ausgelöst

  //Konfiguration von Timer 1
  TCCR1A = 0x00; // Timer 1 ohne Outputpins und ohne PWM
  TCCR1B |= (1<<CS12) | (1<<CS10); // 3,6864MHZ/ 1024 = 3600 Hz

// sämtliche Konfiguration VOR das Aktivieren der Interrupts
-----------------------------------------------------------------------
  sei(); // Interrupts eingeschaltet

  g_run = 1;
  while( ! debounce(&PIND, PD0) );    //Wenn Taster an PIN PD0 gedrueckt
wird, wird while verlassen

  while(g_run == 1);      // Endlosschleife, bis durch INT0 G_run false 
wird, das Semikolon ist wichtig!

  cli();            // alle Interrupts, aus, das wars
  while(1);            // bis zum Sant Nimmerleinstag
}

>Habe ich evtl. den Overflow Vektor falsch gewählt? Oder noch ein
>Register falsch belegt?

Nur kleinere logische Schwächen ;-). Die Interrupts hast du nicht 
wirklich kapiert, oder?
Ausserdem musst du noch die Multiplikatoren anpassen, bei ~3600 Hz 
Timertakt ist deine Überlauf (=Interrupt)freqeunz 3600/256 ~14 Hz, 
sprich 71ms. Das ist dein Zeitraster.

MfG
Falk




Autor: ghost (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hab mittlerweile das Programm nochmal neu geschrieben. Jetzt 
funktioniert eigentlich alles so wie es soll. Nur mit dem externen 
Interrupt klappt es net so gut.

Wenn in der ISR meine globale Variable g_run = 0 gesetzt wird, sollte 
mein programm die while(g_run == 1) schleife verlassen und in die 
while(1) schleife laufen. Dann dürfte aber eigentlich nichts mehr 
passieren, oder? weil bei mir die testLEDs weiterhin blinken...

Autor: Falk Brunner (falk)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Aktueller Sourcecode?

MFG
Falk

Autor: ghost (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
#include <avr/io.h>
#include <inttypes.h>
#include <avr/delay.h>      // definiert _delay_ms()
#include <avr/interrupt.h>
#include <util/delay.h>     // aktuelle Version in util
#include <stdio.h>
#include <stdio.h>
#include <stdlib.h>
#ifndef F_CPU
#define F_CPU 3686400UL     // Quarz mit 3.6864 Mhz ?? noch prüfen!!
#endif


// Funktion zum Entprellen
inline uint8_t debounce(volatile uint8_t *port, uint8_t pin)
{
    if ( ! (*port & (1 << pin)) )
    {
        // Pin wurde auf Masse gezogen, 100ms warten
        _delay_ms(100);
        if ( *port & (1 << pin) )
        {
            // Anwender Zeit zum Loslassen des Tasters geben
            _delay_ms(100);
            return 1;
        }
    }
    return 0;
};


//---------------- Global variables ------------------------

// Variable zum Stoppen
char g_run;

// ---------------------------------------------------------

// --------------- Interrupt zum Umschalten von g_run ------
ISR(INT0_vect) // Externer Interrupt beim Drücken von Taster an PD2
{
  // toggle
  g_run = 0;
}

int main(void)
{
  DDRD = 0x00; // Port D ist Eingang
  PORTD = 0xFF; // interne Pullup-Widerstände aktiviert

  DDRB |= (1<<DDB0) | (1<<DDB1); // Pin 0 und 1 von Port B als Ausgang 
definiert
  PORTB = 0x00;
  EICRA |= (1<<ISC01); // fallende Flanke löst Interrupt aus
  EIMSK |= (1<<INT0);

  sei(); // Interrupts eingeschaltet

  g_run = 1;

  while( ! debounce(&PIND, PD0) );    //Wenn Taster an PIN PD0 gedrueckt 
wird while verlassen.

  while(g_run == 1)
  {

    _delay_ms(60);

    PORTB |= (1<<PB0); // PB0 auf high
    _delay_ms(10); // PB0 für 10 ms auf high
    PORTB &= ~ (1<<PB0); // PB0 wieder auf low
    PORTB |= (1<<PB1); // PB1 auf high
    _delay_ms(10); // PB1 immer für 10 ms auf high
    PORTB &= ~ (1<<PB1); // PB1 wieder auf low
  };

  while(1);
  return 0;
}

Autor: Falk Brunner (falk)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@ ghost

>Wenn in der ISR meine globale Variable g_run = 0 gesetzt wird, sollte
>mein programm die while(g_run == 1) schleife verlassen und in die
>while(1) schleife laufen. Dann dürfte aber eigentlich nichts mehr
>passieren, oder?

Ja.

Aber erstzte mal

char g_run;

durch

volatile char g_run;

> weil bei mir die testLEDs weiterhin blinken...

Dann wird dein Interrupt nicht ausgeführt. Hast du deinen 2. Taster, 
welcher den Interrupt auslösen soll auch and PD2 angeschlossen?.

MFG
Falk


Autor: ghost (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
hab das mit volatile grad selber bei AVR freaks gefunden...

jetzt klappt es. volatile heißt also, dass der wert global also auch in 
main geändert wird oder? dacht immer das macht eine globale variable 
sowieso??

Autor: Jörg Wunsch (dl8dtl) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
ghost wrote:

> volatile heißt also, dass der wert global also auch in
> main geändert wird oder? dacht immer das macht eine globale variable
> sowieso?

Das macht eine globale Variable immer, ja.

`volatile' besagt, dass der Compiler den Code so schreiben muss, dass
an einem sogenannten sequence point der Inhalt der Variablen auch
tatsächlich dem Ergebnis entsprechend der abstrakten Maschine
entsprechen soll.  In freier Übersetzung bedeutet das etwa so viel
wie, dass er jegliche Zugriffsoptimierung auf derartige Variablen
sein lassen soll.

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.