Hallo
Kann mir jemand von euch helfen.
Wie kann ich einen Interrup, nicht über Hardware mit einem Taster, sondern über Software starten.
Mein Problem : Ich möchte beim Master, über einen Taster, Programm beenden auslösen.
Gleichzeitig soll beim Slave, über den I2C Bus, auch ein Programm mit Interrup beendet werden.
Danke im Voraus
Jürgen
Du bist verwirrt!
(zumindest sieht das für mich so aus)
Software Interrupts machen Sinn, wenn der Prozessor mehrere Schutzebenen kennt.
Die üblichen µC kennen sowas nicht.
Also:
Du buddelst auf der falschen Baustelle.
und was passiert, wenn das Programm beendet wurde?
und warum Interrupt?
@combie : beim Atmega kannst du den PCI auslösen, wenn du mit den Pins wackelst. Wenn man dann noch eine LED dranbastelt hast du fast so ein schönes Erlebnis wie auf der PDP11 ![]()
@combie : beim Atmega kannst du den PCI auslösen,
Man kann auch mit der Stirn versuchen, einen Nagel in die Wand zu kloppen.
Der Begriff Softwareinterrupt ist relativ klar belegt.
PCI ist ganz klar ein Hardwareinterrupt.
Nu, der TO möchte keinen Softwareinterrupt, sondern einen Interrupt über Software triggern - wie auch immer. Dass das keinen großen Sinn macht ist eh klar ![]()
Dass das keinen großen Sinn macht ist eh klar
Eben....
Wozu dann der Holzweg?
Die Nebelkerze?
Merksatz:
Wer in die falsche Richtung läuft,
braucht sich nicht zu beeilen.
Hallo,
Dein Ansatz "Interrupt" ist völlig falsch. Für den Master fragst Du ganz normal den Eingang ab und wertest das mit z.B If... aus. Ebenfalls muss die Information des Tasters in den Daten an den Slave enthalten sein. Dann kann der Slave das ebenfalls auf die geiche Weise auswerten.
Heinz
Naja...
Der Slave Callback läuft sowieso im Interrupt Kontext.
Alleine das ist schon ein Grund zu sagen, dass Softwareinterrupts hier fehl am Platze sind.
Hallo
dass man einen Interrupt nicht mit Software starten kann, hat mir mein Bauchgefühl auch gesagt.
War mir als Anfänger aber nicht sicher.
Jetzt ist mir klar wie es nicht geht, aber kann mir einer von euch auch erklären wie ich das lösen kann.
Bitte mit leicht verständlichen Sätze, da meine Programmier Fähigkeiten nicht die besten sind.
Nochmals Danke im Voraus
Jürgen
Bitte mit leicht verständlichen Sätze, da meine Programmier Fähigkeiten nicht die besten sind.
Das merken wir auch so!
Oder hältst du uns für so ****?
Wenn du bitte in leicht verständlichen Sätzen beschreiben würdest, was dein Problem ist, vielleicht...
Meine Modellbahn Anlage besteht bis jetzt aus drei Modulen.
Im Mittelmodul kann ich die Beleuchtung und noch ein paar Bewegungsabläufe mit Taster ein- und ausschalten.
Die Signale gehen von einem Modul zum nächsten Modul über den I2C Bus.
Alles funktioniert einwandfrei, nur die Beleuchtung in meinem Kurhotel lässt sich nicht mehr ausschalten,
da sie sich in einer Endlosschleife befindet. Daher auch meine Idee mit dem Interrupt.
Ich glaube auch daß Du dich da in etwas verzettelst was nicht so funktionieren kann.
Ein interrupt ist ein Teil des Programms das bei einem gewissen Ereignis abgearbeitet wird, unabhängig von dem was der Rest des Programms macht. EIn Interrupt ist nicht dazu da etws zu beenden.
Das "Bitte Müll raustragen" Deiner Frau kommt ja auch unerwartet und im falschesten Moment. Da muß man das Bier und den Fußball stehen lassen und kann danach dort weitermachen wo man aufgehört hat.
Fragen an die C-besser-Könner als ich einer bin. Die Interrupt-Funktion kann wohl auch wie jede andere Funktion via Programm aufgerufen werden?
Grüße Uwe
Auf einem einfachen µC kann man Programme oder Programmteile nicht beenden, ohne den ganzen Controller anzuhalten. Was man machen kann ist ein Flag setzen, das anzeigt, ob ein Programmteil in loop() ausgeführt werden soll oder nicht.
bool runThis = false; //globales Flag
void loop() {
...
if (runThis) { DasHierNurBeiBedarfLaufenLassen; }
Dieses Flag kann man auch in einem Interrupt setzen, aber wenn man dazu den (Software-) Interrupt erst auslösen müßte, dann kann man stattdessen ganz einfach das Flag auch ohne Umweg setzen.
Fragen an die C-besser-Könner als ich einer bin. Die Interrupt-Funktion kann wohl auch wie jede andere Funktion via Programm aufgerufen werden?
Ja und nein!
Normale Funktionen werden mit dem ASM Statement RET beendet.
Interrupt Routinen werden mit RETI beendet.
Das muss man beachten!
5.88 RET – Return from Subroutine
5.88.1 Description
Returns from the subroutine. The return address is loaded from the STACK. The Stack Pointer uses a pre-increment
scheme during RET
5.89 RETI – Return from Interrupt
5.89.1 Description
Returns from the interrupt. The return address is loaded from the STACK, and the Global Interrupt Enable bit is set.
Note that the Status Register is not automatically stored when entering an interrupt routine, and it is not restored
when returning from an interrupt routine. This must be handled by the application program. The Stack Pointer uses a
pre-increment scheme during RETI.
Ja und nein!
Immerhin programmierst du in C++, und da gibt es diesen Unterschied nicht.
void myHandler (); deklariert eine normale Funktion, die jeder der sie kennt verwenden kann. Was in die Interrupt- Verarbeitung eingehängt wird, wird also nochmal einen Rahmen drumrum machen.
Immerhin programmierst du in C++, und da gibt es diesen Unterschied nicht.
:o :o :o
Natürlich endet die ISR mit "reti"
Und eine normale Funktion mit ret.
Mit den bekannten Folgen.
Zudem muss eine solche Prototype Deklaration so aussehen:
extern "C" void TIMER0_COMPA_vect();
Und was ist mit
void myHandler() {return;}
void setup() {
attachInterrupt(0, myHandler, CHANGE);
myHandler();
}
void loop(){
myHandler();
}
Irgendwelche Probleme?
myHandler ist eine normale Funktion, die evtl. auch von einer ISR aufgerufen wird, wenn du da einen Unterschied deutlich machen willst.
Wenn sie als/in ISR läuft, sind natürlich viele Sachen tabu.
Einverstanden?
Einer der größten Fehler im Arduino-Design ist die Existenz von attachInterrupt. Dadurch wird es zu einfach, schwere Fehler zu machen.
Einverstanden?
Ach sicher.... teileweise
Einer der größten Fehler im Arduino-Design ist die Existenz von attachInterrupt. Dadurch wird es zu einfach, schwere Fehler zu machen.
z.B. damit.
Albtraumartige Push Pop Kaskaden kommen noch dazu.
Und was ist mit
....
attachInterrupt(0, myHandler, CHANGE);
Natürlich ist myHandler eine stinknormale Callback Funktion.
Keine ISR.
Läuft aber im ISR Kontext, weil sie von einer aufgerufen wird.
Wenn z.B. attachInterrupt im Code vorkommt, dann werden die ISR für ALLE Pin Hardwareinterrupts erzeugt.
Total teures Verfahren!
Aber hier dreht es sich ja darum eine Interrupt Routine aus C++ heraus aufzurufen.
Habe dein Beispiel, mal mit meinem zusammengegossen
void myHandler() {return;}
extern "C" void TIMER0_COMPA_vect();
int main()
{
detachInterrupt(0);
DDRB = _BV(PB5);
TIMER0_COMPA_vect();
TIMER0_COMPA_vect();
//attachInterrupt(0, myHandler, CHANGE);
}
ISR(TIMER0_COMPA_vect)
{
PINB = _BV(PB5); // toggle Pin 13 UNO
}
Der erzeugte Asmcode:
E:\temp\Arduino/sketch_jan15f.ino.elf: file format elf32-avr
Disassembly of section .text:
00000000 <__vectors>:
0: 0c 94 34 00 jmp 0x68 ; 0x68 <__ctors_end>
4: 0c 94 51 00 jmp 0xa2 ; 0xa2 <__vector_1>
8: 0c 94 78 00 jmp 0xf0 ; 0xf0 <__vector_2>
c: 0c 94 49 00 jmp 0x92 ; 0x92 <__bad_interrupt>
10: 0c 94 49 00 jmp 0x92 ; 0x92 <__bad_interrupt>
14: 0c 94 49 00 jmp 0x92 ; 0x92 <__bad_interrupt>
18: 0c 94 49 00 jmp 0x92 ; 0x92 <__bad_interrupt>
1c: 0c 94 49 00 jmp 0x92 ; 0x92 <__bad_interrupt>
20: 0c 94 49 00 jmp 0x92 ; 0x92 <__bad_interrupt>
24: 0c 94 49 00 jmp 0x92 ; 0x92 <__bad_interrupt>
28: 0c 94 49 00 jmp 0x92 ; 0x92 <__bad_interrupt>
2c: 0c 94 49 00 jmp 0x92 ; 0x92 <__bad_interrupt>
30: 0c 94 49 00 jmp 0x92 ; 0x92 <__bad_interrupt>
34: 0c 94 49 00 jmp 0x92 ; 0x92 <__bad_interrupt>
38: 0c 94 4c 00 jmp 0x98 ; 0x98 <__vector_14>
3c: 0c 94 49 00 jmp 0x92 ; 0x92 <__bad_interrupt>
40: 0c 94 49 00 jmp 0x92 ; 0x92 <__bad_interrupt>
44: 0c 94 49 00 jmp 0x92 ; 0x92 <__bad_interrupt>
48: 0c 94 49 00 jmp 0x92 ; 0x92 <__bad_interrupt>
4c: 0c 94 49 00 jmp 0x92 ; 0x92 <__bad_interrupt>
50: 0c 94 49 00 jmp 0x92 ; 0x92 <__bad_interrupt>
54: 0c 94 49 00 jmp 0x92 ; 0x92 <__bad_interrupt>
58: 0c 94 49 00 jmp 0x92 ; 0x92 <__bad_interrupt>
5c: 0c 94 49 00 jmp 0x92 ; 0x92 <__bad_interrupt>
60: 0c 94 49 00 jmp 0x92 ; 0x92 <__bad_interrupt>
64: 0c 94 49 00 jmp 0x92 ; 0x92 <__bad_interrupt>
00000068 <__ctors_end>:
68: 11 24 eor r1, r1
6a: 1f be out 0x3f, r1 ; 63
6c: cf ef ldi r28, 0xFF ; 255
6e: d8 e0 ldi r29, 0x08 ; 8
70: de bf out 0x3e, r29 ; 62
72: cd bf out 0x3d, r28 ; 61
00000074 <__do_copy_data>:
74: 11 e0 ldi r17, 0x01 ; 1
76: a0 e0 ldi r26, 0x00 ; 0
78: b1 e0 ldi r27, 0x01 ; 1
7a: e2 e6 ldi r30, 0x62 ; 98
7c: f1 e0 ldi r31, 0x01 ; 1
7e: 02 c0 rjmp .+4 ; 0x84 <__do_copy_data+0x10>
80: 05 90 lpm r0, Z+
82: 0d 92 st X+, r0
84: a4 30 cpi r26, 0x04 ; 4
86: b1 07 cpc r27, r17
88: d9 f7 brne .-10 ; 0x80 <__do_copy_data+0xc>
8a: 0e 94 9f 00 call 0x13e ; 0x13e <main>
8e: 0c 94 af 00 jmp 0x15e ; 0x15e <_exit>
00000092 <__bad_interrupt>:
92: 0c 94 00 00 jmp 0 ; 0x0 <__vectors>
00000096 <nothing>:
#include <stdio.h>
#include "wiring_private.h"
static void nothing(void) {
}
96: 08 95 ret
00000098 <__vector_14>:
TIMER0_COMPA_vect();
//attachInterrupt(0, myHandler, CHANGE);
}
ISR(TIMER0_COMPA_vect)
{
98: 8f 93 push r24
PINB = _BV(PB5); // toggle Pin 13 UNO
9a: 80 e2 ldi r24, 0x20 ; 32
9c: 83 b9 out 0x03, r24 ; 3
}
9e: 8f 91 pop r24
a0: 18 95 reti
000000a2 <__vector_1>:
IMPLEMENT_ISR(INT6_vect, EXTERNAL_INT_6)
IMPLEMENT_ISR(INT7_vect, EXTERNAL_INT_7)
#else
IMPLEMENT_ISR(INT0_vect, EXTERNAL_INT_0)
a2: 1f 92 push r1
a4: 0f 92 push r0
a6: 0f b6 in r0, 0x3f ; 63
a8: 0f 92 push r0
aa: 11 24 eor r1, r1
ac: 2f 93 push r18
ae: 3f 93 push r19
b0: 4f 93 push r20
b2: 5f 93 push r21
b4: 6f 93 push r22
b6: 7f 93 push r23
b8: 8f 93 push r24
ba: 9f 93 push r25
bc: af 93 push r26
be: bf 93 push r27
c0: ef 93 push r30
c2: ff 93 push r31
c4: e0 91 00 01 lds r30, 0x0100 ; 0x800100 <intFunc>
c8: f0 91 01 01 lds r31, 0x0101 ; 0x800101 <intFunc+0x1>
cc: 09 95 icall
ce: ff 91 pop r31
d0: ef 91 pop r30
d2: bf 91 pop r27
d4: af 91 pop r26
d6: 9f 91 pop r25
d8: 8f 91 pop r24
da: 7f 91 pop r23
dc: 6f 91 pop r22
de: 5f 91 pop r21
e0: 4f 91 pop r20
e2: 3f 91 pop r19
e4: 2f 91 pop r18
e6: 0f 90 pop r0
e8: 0f be out 0x3f, r0 ; 63
ea: 0f 90 pop r0
ec: 1f 90 pop r1
ee: 18 95 reti
000000f0 <__vector_2>:
IMPLEMENT_ISR(INT1_vect, EXTERNAL_INT_1)
f0: 1f 92 push r1
f2: 0f 92 push r0
f4: 0f b6 in r0, 0x3f ; 63
f6: 0f 92 push r0
f8: 11 24 eor r1, r1
fa: 2f 93 push r18
fc: 3f 93 push r19
fe: 4f 93 push r20
100: 5f 93 push r21
102: 6f 93 push r22
104: 7f 93 push r23
106: 8f 93 push r24
108: 9f 93 push r25
10a: af 93 push r26
10c: bf 93 push r27
10e: ef 93 push r30
110: ff 93 push r31
112: e0 91 02 01 lds r30, 0x0102 ; 0x800102 <intFunc+0x2>
116: f0 91 03 01 lds r31, 0x0103 ; 0x800103 <intFunc+0x3>
11a: 09 95 icall
11c: ff 91 pop r31
11e: ef 91 pop r30
120: bf 91 pop r27
122: af 91 pop r26
124: 9f 91 pop r25
126: 8f 91 pop r24
128: 7f 91 pop r23
12a: 6f 91 pop r22
12c: 5f 91 pop r21
12e: 4f 91 pop r20
130: 3f 91 pop r19
132: 2f 91 pop r18
134: 0f 90 pop r0
136: 0f be out 0x3f, r0 ; 63
138: 0f 90 pop r0
13a: 1f 90 pop r1
13c: 18 95 reti
0000013e <main>:
EIMSK &= ~(1 << INT0);
13e: e8 98 cbi 0x1d, 0 ; 29
intFunc[interruptNum] = nothing;
140: 8b e4 ldi r24, 0x4B ; 75
142: 90 e0 ldi r25, 0x00 ; 0
144: 90 93 01 01 sts 0x0101, r25 ; 0x800101 <intFunc+0x1>
148: 80 93 00 01 sts 0x0100, r24 ; 0x800100 <intFunc>
DDRB = _BV(PB5);
14c: 80 e2 ldi r24, 0x20 ; 32
14e: 84 b9 out 0x04, r24 ; 4
TIMER0_COMPA_vect();
150: 0e 94 4c 00 call 0x98 ; 0x98 <__vector_14>
TIMER0_COMPA_vect();
154: 0e 94 4c 00 call 0x98 ; 0x98 <__vector_14>
}
158: 90 e0 ldi r25, 0x00 ; 0
15a: 80 e0 ldi r24, 0x00 ; 0
15c: 08 95 ret
0000015e <_exit>:
15e: f8 94 cli
00000160 <__stop_program>:
160: ff cf rjmp .-2 ; 0x160 <__stop_program>
Hallo,
dass der Ansatz "Interrupt" völlig falsch war, ist mir jetzt auch klar.
Ich bin gerade dabei einen anderen Weg zu gehen.
Wollte euch bei Eurer Diskussion nicht stören.
Werde mich auf jeden Fall wieder melden, vermutlich weil ich es nicht hin bekomme.
Nochmals Danke für Eure Hilfe.
Warum ist das Einloggen jetzt so umständlich. Früher war ich ruck zuck in dem Forum drinnen.
Jetzt ist es jedes Mal ein Glückspiel.
Gruß Jürgen
Wollte euch bei Eurer Diskussion nicht stören.
Danke. Sehr nett von dir, dass du für uns diesen Thread gestartet hast. ![]()