Forum: Compiler & IDEs Interrupt in C


von Orange (Gast)


Lesenswert?

Hallo Zusammen,
ich bin noch blutiger Anfänger (vor 3 Tagen begonnen) und komm nun mit 
den Interrupts nicht weiter. Ohne viele Worte mein kleines Programm:

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

unsigned int i;
unsigned int f;

ISR(INT1_vect)
{
 DDRB=0xFF;
 while(f<=50000)
 {
  PORTB=0x08;
  f=f+1;
 }
 f=0;
}

int main()
{
 DDRB=0xFF;
 sei();
 while(1)
 {
  while(i<=50000)
  {
   PORTB=0x04;
   i=i+1;
  }
  i=0;
  while(i<=50000)
  {
   PORTB=0x00;
   i=i+1;
  }
  i=0;
 }
}

Was hab ich vergessen oder falsch gemacht?
Schon mal Danke für Antworten :)

mfg Orange

von andy (Gast)


Lesenswert?

Hallo,
habe vor drei Tagen den Führerschein gemacht und bin noch nicht
Formel 1 Fahrer.Was habe ich falsch gemacht???.

Lern doch erst mal die einfachsten grundlagen.

Es fehlt die hälfte und die hälfte die da ist,ist Müll.

gruss

andy

von Jörg G. (joergderxte)


Lesenswert?

@OP Kannst du mal in Worten beschreiben, was das Programm machen soll? 
das ist nämlich nicht wirklich offensichtlich...

von Kai S. (zigzeg)


Lesenswert?

1.) statt
1
 while(i<=50000)
2
  {
3
   PORTB=0x04;
4
   i=i+1;
5
  }
6
  i=0;

besser for() loop nehmen:
1
for(i=0; i <= 50000; i = i +1)
2
{
3
PORTB = 0x04;
4
}
Vorteile: Uebersichtlicher, kompakter, ausserdem wird i vor Benutzung 
initialisiert !
Bei Deinem Code ist die Dauer der ersten Schleife Zufall, denn i wir 
nicht initializiert, und kann somit irgend einen Wert haben.

2.) Damit in die Interruptroutine verzweigt wird muss irgend ein "Event" 
konfiguriert sein (z.B. ein Timer), um dass auszuloesen. Bei diesem 
Programm nicht vorhanden => die Interrupt-Routine wird nie angesprungen.

von Orange (Gast)


Lesenswert?

harte Worte... ;)
Ich bin mir dessen bewusst, dass ich doch sehr wild das ganze anfang.
In meinem Techniker hab ich die Zeit alles in Ruhe nachzuarbeiten, doch 
momentan brauch ich zügig ein Programm und wie ich da hinkomm is mir 
ehrlich gesagt wurschd. Hauptsache es funktioniert irgendwie

Wie würde deiner Ansicht diese Aufgabe zu lösen sein?
Dass ich seh wie es richtig sein sollte^^

ATtiny2313
LED am Ausgang soll blinken und wenn ich Taster (INT1) betätige soll 
eine andere LED kurz angehn und danach der normal Rythmus wieder weiter.
Und das ganze über Interrupt halt...

von Kai S. (zigzeg)


Lesenswert?

Orange schrieb:

> ehrlich gesagt wurschd. Hauptsache es funktioniert irgendwie

Das ist genau die richtige Einstellung. Nicht.

> ATtiny2313
> LED am Ausgang soll blinken und wenn ich Taster (INT1) betätige soll
> eine andere LED kurz angehn und danach der normal Rythmus wieder weiter.

Dann must Du noch einschalten dass der INT1 Pin einen Interrupt 
ausloest. Siehe Datenblatt.
BTW: Koennte sein dass das Blinken bei der Laenge (Kuerze !) der 
Schleifen recht hektisch ist. Besser _delay() verwenden.

von Orange (Gast)


Lesenswert?

@Kai S.
Danke für den Tipp, werd ich beherzigen.

@Jörg G.
hab grad dem Gast Andy geantwortet

von Markus (Gast)


Lesenswert?

Wenns nur blinken soll und Du eh nix lernen willst, sondern nur deinen 
Lehrer verschaukeln, such Dir was fertiges aus dem Internet. Geht am 
schnellsten und vergelichsweise hirnlos. Besser auf jeden Fall als der 
Scheiß den Du dir da ausm Hirn drückst.

von andy (Gast)


Lesenswert?

Hallo,

harte Worte müssen manchmal sein.
Schau in das tut hier rein und du müsstest einen Interrupt in ca. 1 
Stunde
hinkriegen und auch halbwegs verstehen.

und wie ich da hinkomm is mir
ehrlich gesagt wurschd. Hauptsache es funktioniert irgendwie

Das ist schon mal eine sehr löbliche einstellung (kopfschüttel).

Hausaufgabe ?

gruss

andy

von Orange (Gast)


Lesenswert?

Also irwie kommen mir die Antworten der Gäste immer etwas hart vor... :P

Naja, das is eig gar nich worauf ich hinaus will...^^
Bitte nicht, ich weiß selber dass das sehr utopisch klingt:

Bei meim Kumpel hab isch schon vor längerem richtig geil eine 
Beleuchtung mit RGB_LEDs eingebaut. Zurzeit wird jeder Farbenstrang 
einzelnd per Schalter 1/0 gemacht. Nun kommt der Controller ins Spiel.
Vorstellung:
2 Inkrementgeber, der eine regelt ein Farbspecktrum, der andere die 
Helligkeit. und wenn ich nen separaten Taster betätige soll alles sofort 
weiß sein.

...Nix wildes eig.^^

von Karl H. (kbuchegg)


Lesenswert?

Orange schrieb:
> Also irwie kommen mir die Antworten der Gäste immer etwas hart vor... :P
>
> Naja, das is eig gar nich worauf ich hinaus will...^^
> Bitte nicht, ich weiß selber dass das sehr utopisch klingt:
>
> Bei meim Kumpel hab isch schon vor längerem richtig geil eine
> Beleuchtung mit RGB_LEDs eingebaut. Zurzeit wird jeder Farbenstrang
> einzelnd per Schalter 1/0 gemacht. Nun kommt der Controller ins Spiel.
> Vorstellung:
> 2 Inkrementgeber, der eine regelt ein Farbspecktrum, der andere die
> Helligkeit. und wenn ich nen separaten Taster betätige soll alles sofort
> weiß sein.
>
> ...Nix wildes eig.^^


Im Prinzip nicht.
Wenn man weiß wies geht.

Aber bis man das weiß, vergeht Zeit.
Und daher hilft es auch nichts, wenn man mitten drinn einsteigt und die 
Grundlagen aussen vor lässt.

PS: Dazu brauchst du eigentlich gar keinen Interrupt. Tasterabfragen 
brauchen so gut wie nie einen Interrupt. Aber da muss der Rest des 
Programmes dann auch dazu passen. Deine vielen while Schleifen werden 
dir da zum Stolperstein. Im ganzen Programm gibt es nur 1 einzige 
Schleife und die ist die Hauptschleife in main(). ALles andere wird 
zeitlich gestaffelt da drinnen erledigt. Mit jedem Durchlauf durch die 
Schleife immer nur ein kleines bischen Arbeit machen lassen (zb auf die 
nächste Farbstufe dimmen)

von Orange (Gast)


Lesenswert?

@Karl Heinz Buchegger
Ok, Zusatzinfo:

die dimmung der einzelnen Farben plan ich über pwm. wenn das Programm 
sich tatsächich ohne interrupts realisieren lässt wäre toll, weil dann 
hab ich Zeit um mich noch mehr mit gepflogenheiten und basics zu 
beschäftigen.

von Kai S. (zigzeg)


Lesenswert?

Man kann eigentlich fast alles ohne Interrupts lösen. Dann kommen z.B. 
Abfragen der Taste etc. einfach in die Hauptschleife.
Mache Dinge sind mit Interrupts, wenn man sie denn verstanden hat, 
einfacher bzw. eleganter zu lösen.

von Karl H. (kbuchegg)


Lesenswert?

Kai S. schrieb:

> Mache Dinge sind mit Interrupts, wenn man sie denn verstanden hat,
> einfacher bzw. eleganter zu lösen.

Zustimmung.
Nur Taster auf Interrupts zu legen, macht nur in Ausnahmefällen Sinn. 
Wenn der Taster den µC aus dem Tiefschlaf holen muss beispielsweise. 
Ansonsten macht das mehr Ärger als ein direkter Einbau in die 
Hauptschleife.
Und einen eventbasierten Programmierstil fördert das ausserdem, was dann 
wiederrum der Bedienbarkeit zu Gute kommt.

von Orange (Gast)


Lesenswert?

Sieht das schon besser aus?

#include <avr/io.h>
#include <avr/delay.h>

#define z 5

void main(void)
{
 DDRB = (1<<DDB2) | (1<<DDB3);
 DDRD &= ~(1<<DDD3);
 while(1)
 {
  if(PIND & (1<<PIND3))
  {
   PORTB |= (1<<PORTB3);
   _delay_ms(z);
   PORTB &= ~(1<<PORTB3);
  }
  else
  {
   PORTB |= (1<<PORTB2);
   _delay_ms(z);
   PORTB &= ~(1<<PORTB2);
   _delay_ms(z);
  }
 }
}

schon mal danke für eure Beteiligung und Mühen!

von Werner B. (werner-b)


Lesenswert?

Sieht doch schon gut aus.
Drei Hinweise:

1. Fünf Millisekunden... da siehtst du nichts mehr blinken. Das ist 
einfach nur "etwas dunkler". Bei 100 ms sieht man schon ein deutliches 
(auf)Blitzen.

2. Etwas AVR-GCC/WinAVR spezifisches ist das _delay_ms().
Schon mal gut, dass du nicht versuchst _delay_ms() mit einer Variablen 
als Parameter auszuführen. Das ist hier im Forum eines der TOP 3 Themen, 
dass dann "der Flash Speicher nicht mehr ausreicht" und "die Zeiten 
nicht stimmen". Das kommt davon, dass in diesem Fall die Fließkomma 
Bibliothek mit eingebunden wird. Variable verzögerungen packt man darum 
in do/while oder for Schleifen.

3. Was mich auf 2. gebracht hat: Es existiert in C die Konvention, das 
man per #define definierte Ausdrücke (blöde Formulierung, ist aber so) 
in Großbuchstaben schreibt. So sieht man sofort wo man nach der 
Definition des Ausdruckes zu suchen hat. Also besser "#define Z 5", oder 
noch besser "#define CONST_DELAY_TIME 5".
Dem Compiler selbst ist das zwar völlig egal, aber andere Programmierer 
die den Code in die Finger bekommen wissen sofort um was es geht.

von Orange (Gast)


Lesenswert?

@ Werner B.
Vielen Dank für das Feedback, hab den definierten Ausdruck schon 
angepasst ;)
lg Orange

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Jetzt darfst du aber auch noch schnell das Forum zu bedienen lernen. ;-)
Code fasst man in [ c ] ... [ /c ] (die Leerzeichen dabei weglassen),
dann sieht er besser aus:
1
#include <avr/io.h>
2
#include <avr/delay.h>
3
4
#define z 5
5
6
void main(void)
7
{
8
 DDRB = (1<<DDB2) | (1<<DDB3);
9
 DDRD &= ~(1<<DDD3);
10
 while(1)
11
 {
12
  if(PIND & (1<<PIND3))
13
  {
14
   PORTB |= (1<<PORTB3);
15
   _delay_ms(z);
16
   PORTB &= ~(1<<PORTB3);
17
  }
18
  else
19
  {
20
   PORTB |= (1<<PORTB2);
21
   _delay_ms(z);
22
   PORTB &= ~(1<<PORTB2);
23
   _delay_ms(z);
24
  }
25
 }
26
}

p.s.: Über "void main(void)" beklagt sich der Compiler regelmäßig,
da es nicht C-Standard-konform ist (vereinfacht gesagt).  Schreib
besser "int main(void)".  Ob du dabei am Ende noch eine (nie
erreichte, durch die Endlosschleife davor) Anweisung "return 0;"
schreibst oder nicht, ist dem Compiler dann relativ egal.

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.