AVR Studio - Programmlänge angeblich zu groß

OP #3108018
Lesenswert?

Sehr geehrtes Forum,
ich habe folgendes Problem :
Ich bin gerade am Lernen von Interrupts, habe mir da ein Programm
geschrieben, und was passiert jetzt? Mein AVR Studio sagt mir beim 
Debuggen, dass das Programm zu groß wäre, komischer Weise (Siehe Bild) :
4KB Flash Speicher, gerade ca. 360 Bytes benutzt, warum steht dann da 
over?

Mein Code im Folgenden:
1
.include "M48PAdef.inc"
2

3
; //////////////////////////////////////////////////////////////
4
;  ExternInterrupt
5
;  Kevin Riehl - 29.03.2013
6
;  
7
;  Dieses Programm lässt ein Hauptprogramm laufen
8
;  und wird, bei einem Tastendruck an C0 unterbrochen,
9
;  und startet damit eine Interruptsubroutine
10
;  
11
; //////////////////////////////////////////////////////////////
12
; /////// Defintionen
13
; //////////////////////////////////////////////////////////////
14

15
.DEF STACK_LOW = R16
16
.DEF STACK_HIG = R17
17

18
.DEF COUNTER = R25
19
; //////////////////////////////////////////////////////////////
20
; Stackpointerinitialisierung
21
  LDI STACK_LOW, LOW(RAMEND)    ;Stackpointer initialisieren
22
  OUT SPL, STACK_LOW
23
  LDI STACK_HIG, HIGH(RAMEND)   ;Stackpointer initialisieren
24
  OUT SPH, STACK_HIG
25
; //////////////////////////////////////////////////////////////
26

27
; LCD INITIALISIEREN
28
RCALL Wait1000MS
29
RCALL LCD_INIT
30

31
; INTERRUPTS INITIALISIEREN bei PCINT8
32
SEI
33
.ORG 0xC08
34
  RJMP interrupt
35

36
.CSEG
37

38
; HAUPTPROGRAMM
39
main:
40
LDI COUNTER,'0'
41

42
a :
43
  MOV INFO,COUNTER
44
  RCALL LCD_HOME
45
  RCALL LCD_DATA
46
  RCALL Wait1000ms
47
  CPI COUNTER,'9'+1
48
  BRNE a
49

50
rjmp main
51

52

53
interrupt:
54
CLI
55
LDI ZL,LOW (text*2)
56
LDI ZH,HIGH(text*2)
57

58
RCALL LCD_LINE2
59

60
loop:
61
  LPM
62

63
; Testen ob Ende
64
  TST R0
65
  BREQ b
66

67
; Zeichen ausgegeben
68
  MOV INFO,R0
69
  RCALL LCD_DATA
70

71
; Zeiger auf nächstes Byte setzen
72
  ADIW ZL,1
73
  RCALL Wait1000MS
74
  RJMP loop
75

76
b :
77
  RCALL LCD_LINE1
78
  SEI
79
  RETI
80

81
; //////////////////////////////////////////////////////////////
82

83
.include "LCD_Lib.asm"
84

85
text: .DB "NEBENROUTINE :-)",0

Ach und nebenbei :
Ich benutze den Atmega48pa, und will am PC0 einen Interrupt auslösen, so 
richtig oder nicht?

Danke für eure Hilfe!
m.f.G. Developer_X
Angehängte Dateien:
#3108026
Lesenswert?

K. R. schrieb:
> Ich bin gerade am Lernen von Interrupts, habe mir da ein Programm
> geschrieben, und was passiert jetzt? Mein AVR Studio sagt mir beim
> Debuggen, dass das Programm zu groß wäre, komischer Weise (Siehe Bild) :
> 4KB Flash Speicher, gerade ca. 360 Bytes benutzt, warum steht dann da
> over?
1
.ORG 0xC08
Weil du Teile deines Programms außerhalb des existierenden Flash 
platziert hast.
OP #3108029
Lesenswert?

Ich dachte das würde meinem Mikrocotnroller sagen, dass er ein Interrupt 
von Port CO bekommen soll, PCINT8.

Wie kann ich denn einen Interrupt von PCINT8 setzen, das heißt ihm 
sagen, wenn Port C0 an, durch button, also PCInt8 an, dann soll die 
Subroutine "interrupt" aufgerufen werden.

Wie kann ich das machen?

Danke,
m.f.G. Developer_X
Gast #3108039
Lesenswert?

Entweder an den Anfang die ganze Interrupttabelle hinschreiben oder die 
richtige Adresse aus dem Datenblatt suchen. Beim ATMega8 wäre das zum 
Beispiel für externe Interrupts die Adressen 1 und 2.
Der Vorteil der Tabelle ist, dass aus Versehen aktivierte Interrupts das 
Programm nicht beeinflussen.
(Firma: matzetronics) #3108040
Lesenswert?

1. Der Mega48/88/168/328 hat nur Interruptvektoren für die drei PCINT 
Gruppen , nicht für jeden Pin einen eigenen. Pin PCINT8 löst also 
Interrupt PCINT1 aus.
2. Deinem Programm fehlt die Vektortabelle ab ORG 0x00. Siehe das 
Datenblatt unter 'Interrupt Vectors in ATMega48P':
1
The most typical and general program setup for the Reset and Interrupt Vector Addresses in
2
ATmega48P is:
3
Address Labels Code Comments
4
0x000          rjmp  RESET          ; Reset Handler
5
0x001          rjmp  EXT_INT0       ; IRQ0 Handler
6
0x002          rjmp  EXT_INT1       ; IRQ1 Handler
7
0x003          rjmp  PCINT0         ; PCINT0 Handler
8
0x004          rjmp  PCINT1         ; PCINT1 Handler
9
0x005          rjmp  PCINT2         ; PCINT2 Handler
10
0x006          rjmp  WDT ; Watchdog Timer Handler
11
0x007          rjmp  TIM2_COMPA     ; Timer2 Compare A Handler
12
0x008          rjmp  TIM2_COMPB     ; Timer2 Compare B Handler
13
0x009          rjmp  TIM2_OVF       ; Timer2 Overflow Handler
14
0x00A          rjmp  TIM1_CAPT      ; Timer1 Capture Handler
15
0x00B          rjmp  TIM1_COMPA     ; Timer1 Compare A Handler
16
0x00C          rjmp  TIM1_COMPB     ; Timer1 Compare B Handler
17
0x00D          rjmp  TIM1_OVF       ; Timer1 Overflow Handler
18
0x00E          rjmp  TIM0_COMPA     ; Timer0 Compare A Handler
19
0x00F          rjmp  TIM0_COMPB     ; Timer0 Compare B Handler
20
0x010          rjmp  TIM0_OVF       ; Timer0 Overflow Handler
21
0x011          rjmp  SPI_STC        ; SPI Transfer Complete Handler
22
0x012          rjmp  USART_RXC      ; USART, RX Complete Handler
23
0x013          rjmp  USART_UDRE     ; USART, UDR Empty Handler
24
0x014          rjmp  USART_TXC      ; USART, TX Complete Handler
25
0x015          rjmp  ADC ; ADC Conversion Complete Handler
26
0x016          rjmp  EE_RDY         ; EEPROM Ready Handler
27
0x017          rjmp  ANA_COMP       ; Analog Comparator Handler
28
0x018          rjmp  TWI ; 2-wire Serial Interface Handler
29
0x019          rjmp  SPM_RDY        ; Store Program Memory Ready Handler
Da sind alle Vektoren drin, die Interrupts auslösen. Entweder machst du 
per
1
.ORG 0x004 
2
      rjmp meinPCINT1
den einzelnen Vektor oder du baust die komplette Tabelle nach und lässt 
unbenutzte IRQs auf ein RETI laufen. Der Reset Vektor bei ORG 0x000 ist 
aber zwingend notwendig, sonst startet dein Programm irgendwo.
Gast #3108053
Lesenswert?

K. R. schrieb:

> Ich dachte das würde meinem Mikrocotnroller sagen, dass er ein Interrupt
> von Port CO bekommen soll, PCINT8.

Oh Gott...

Wie wäre es, wenn du erstmal die verschissene Dokumentation lesen 
würdest, bevor du dich an's Programmieren machst?

> Wie kann ich denn einen Interrupt von PCINT8 setzen, das heißt ihm
> sagen, wenn Port C0 an, durch button, also PCInt8 an, dann soll die
> Subroutine "interrupt" aufgerufen werden.

Eigentlich garnicht.

Bestenfalls kannst du dafür sorgen, daß

1) überhaupt ein Interrupt ausgelöst wird, wenn es an diesem Portpin 
wackelt.

Dazu mußt du bei PCINT-Interrupts typischerweise das zuständige 
Maskenregister für den Portpin setzen und zusätzlich das 
Interruptmaskenregister für den zuständigen PCINT-Interrupt. Welche 
Register das jeweils genau sind, ist deviceabhängig und steht in dem 
verschissenen Datenblatt.

2) Der Interruptvektor der benutzten Vektortabelle den Code deiner ISR 
durchläuft.

Dazu mußt du erstmal festlegen, welche Vektortabelle benutzt wird (oder 
dich mit der standardmäßig aktiven ab Adresse 0 abfinden), dann dort im 
richtigen Vektor entweder einen Sprungbefehl zum Code deiner ISR 
platzieren oder direkt deine ISR (was allerdings nur geht, solange du 
die dadurch ggf. überschriebenen Vektoren nicht noch für andere Zwecke 
benötigst.

Welche Vektortabellen möglich sind, wie man sie auswählt, welche 
Vektoren existieren und wo genau sie in der Tabelle liegen, als das ist 
wieder deviceabhängig und steht deshalb im verschissenen Datenblatt, 
welches du verdammt nochmal einfach mal lesen solltest!
OP #3108087
Lesenswert?

An Alle anderen außer den Vorredner :
Ich habe mir ja das Datenblatt vom Atmega48PA durchgelesen, da steht 
aber nichts davon, dass INT1 für PICINT8 bis 14 verantwortlich wäre, das 
ist nur bei den Flagveränderungen so.

Des Weiteren steht da ja, dass man einstellen kann, im Register :
EIMSK welche von den Interrupts (0 oder 1) abgefragt werden, aber das 
Register existiert in meinem Assembler Editor nicht, und wenn ich im 
Datenblatt die Registeraufteilung finde, und die entsprechende Adresse 
im Code anstatt EIMSK hinterlege, meint er es wäre ein invalides 
Register.

Was mich auch noch wundert ist, dass .ORG und Reset nur am Anfang des 
Codes geschrieben werden können, mein Code sieht wie folgt aus :
1
; INTERRUPTS INITIALISIEREN bei PCINT8
2
SEI
3

4
.ORG 0x004 
5
      rjmp interrupt
6
RESET:
7

8
.include "M48PAdef.inc"
9

10
; //////////////////////////////////////////////////////////////
11
;  ExternInterrupt
12
;  Kevin Riehl - 29.03.2013
13
;  
14
;  Dieses Programm lässt ein Hauptprogramm laufen
15
;  und wird, bei einem Tastendruck an C0 unterbrochen,
16
;  und startet damit eine Interruptsubroutine
17
;  
18
; //////////////////////////////////////////////////////////////
19
; /////// Defintionen
20
; //////////////////////////////////////////////////////////////
21

22
.DEF STACK_LOW = R16
23
.DEF STACK_HIG = R17
24

25
.DEF COUNTER = R25
26
; //////////////////////////////////////////////////////////////
27
; Stackpointerinitialisierung
28
  LDI STACK_LOW, LOW(RAMEND)    ;Stackpointer initialisieren
29
  OUT SPL, STACK_LOW
30
  LDI STACK_HIG, HIGH(RAMEND)   ;Stackpointer initialisieren
31
  OUT SPH, STACK_HIG
32
; //////////////////////////////////////////////////////////////
33

34
; LCD INITIALISIEREN
35
RCALL Wait1000MS
36
RCALL LCD_INIT
37

38
LDI 0x3D,0b00000010 ; DASS SEI EIMSK
39

40
; HAUPTPROGRAMM
41
main:
42
LDI COUNTER,'0'
43

44
a :
45
  MOV INFO,COUNTER
46
  RCALL LCD_HOME
47
  RCALL LCD_DATA
48
  RCALL Wait1000ms
49
  CPI COUNTER,'9'
50
  BRNE a
51

52
rjmp main
53

54

55
interrupt:
56
CLI
57
LDI ZL,LOW (text*2)
58
LDI ZH,HIGH(text*2)
59

60
RCALL LCD_LINE2
61

62
loop:
63
  LPM
64

65
; Testen ob Ende
66
  TST R0
67
  BREQ b
68

69
; Zeichen ausgegeben
70
  MOV INFO,R0
71
  RCALL LCD_DATA
72

73
; Zeiger auf nächstes Byte setzen
74
  ADIW ZL,1
75
  RCALL Wait1000MS
76
  RJMP loop
77

78
b :
79
  RCALL LCD_LINE1
80
  SEI
81
  RETI
82

83
; //////////////////////////////////////////////////////////////
84

85
.include "LCD_Lib.asm"
86

87
text: .DB "NEBENROUTINE :-)",0

Was genau muss ich jetzt machen, ich check es nicht, auch nach dem 
Tutorial im Forum, das mir bereitgestellt wurde nicht, wenn ich das 
ganze einfach am INT1 oder INT0 Pin mache, gehts ja einfach, wie kann 
ich aber gezielt den Interrupt auf nur einen PIN, nämlich PC0 setzen?

In meinem Buch wirds nicht erklärt!
Gast #3108093
Lesenswert?

Hi

>Was mich auch noch wundert ist, dass .ORG und Reset nur am Anfang des
>Codes geschrieben werden können, mein Code sieht wie folgt aus :

Stimmt nicht. Kann man überall benutzen, wenn man weiß was man macht.

>SEI

>.ORG 0x004
>      rjmp interrupt
>RESET:

Damit plazierst du das 'RESET' auf die Adresse 0x0005 und das ist 
falsch.

MfG Spess
#3108100
Lesenswert?

Datenblatt Abschnitt: 12. External Interrupts

"
The
pin change interrupt PCI2 will trigger if any enabled PCINT23...16 pin 
toggles. The pin change
interrupt PCI1 will trigger if any enabled PCINT14...8 pin toggles. The 
pin change interrupt PCI0
will trigger if any enabled PCINT7...0 pin toggles. The PCMSK2, PCMSK1 
and PCMSK0 Registers
control which pins contribute to the pin change interrupts.
"
OP #3108118
Lesenswert?

Erstma danke, also ist INT1 für PCINT8 zuständig^^.

In dem Tutorial heißt es, dass man dann ganz einfach einem Interrupt 
eine ISR zuweisen kann indem man folgendes macht :
1
.include "m8def.inc"
2
 
3
.def temp = r16
4
 
5
.org 0x000
6
         rjmp main            ; Reset Handler
7
.org INT0addr
8
         rjmp int0_handler    ; IRQ0 Handler
9
.org INT1addr
10
         rjmp int1_handler    ; IRQ1 Handler
11
 
12
 
13
main:                         ; hier beginnt das Hauptprogramm
14
 
15
         ldi temp, LOW(RAMEND)
16
         out SPL, temp
17
         ldi temp, HIGH(RAMEND)
18
         out SPH, temp
19
 
20
         ldi temp, 0x00
21
         out DDRD, temp
22
 
23
         ldi temp, 0xFF
24
         out DDRB, temp
25
 
26
         ldi temp, (1<<ISC01) | (1<<ISC11) ; INT0 und INT1 auf fallende Flanke konfigurieren
27
         out MCUCR, temp
28
 
29
         ldi temp, (1<<INT0) | (1<<INT1) ; INT0 und INT1 aktivieren
30
         out GICR, temp
31
 
32
         sei                   ; Interrupts allgemein aktivieren
33
 
34
loop:    rjmp loop             ; eine leere Endlosschleife
35
 
36
int0_handler:
37
         sbi PORTB, 0
38
         reti
39
 
40
int1_handler:
41
         cbi PORTB, 0
42
         reti

Wenn ich das mache, kommen fehlermeldungen auf, weil mein Code dann 
irgendwie verschoben ist, komisch, im tutorial klappt es angeblich :
1
; INTERRUPTS INITIALISIEREN bei PCINT8
2

3
.org 0x000
4
         rjmp start            ; Reset Handler
5
.org INT0addr
6
     NOP
7
.org INT1addr
8
         rjmp interrupt    ; IRQ1 Handler
9

10

11
.include "M48PAdef.inc"
12

13
; //////////////////////////////////////////////////////////////
14
;  ExternInterrupt
15
;  Kevin Riehl - 29.03.2013
16
;  
17
;  Dieses Programm lässt ein Hauptprogramm laufen
18
;  und wird, bei einem Tastendruck an C0 unterbrochen,
19
;  und startet damit eine Interruptsubroutine
20
;  
21
; //////////////////////////////////////////////////////////////
22
; /////// Defintionen
23
; //////////////////////////////////////////////////////////////
24

25
start:
26
SEI
27

28
.DEF STACK_LOW = R16
29
.DEF STACK_HIG = R17
30

31
.DEF COUNTER = R25
32
;... hier gehts weiter wie vorher

Fehlermeldung :
1
G:\Software Projects\2013\March\Interrupts\ExternInterrupt.asm(5): error: Overlap in .cseg: addr=0x0 conflicts with 0x0:0x1
2
G:\Software Projects\2013\March\Interrupts\ExternInterrupt.asm(6): error: Use of undefined or forward referenced symbol 'INT0addr' in .org
3
G:\Software Projects\2013\March\Interrupts\ExternInterrupt.asm(7): error: Overlap in .cseg: addr=0x0 conflicts with 0x0:0x1
4
G:\Software Projects\2013\March\Interrupts\ExternInterrupt.asm(8): error: Use of undefined or forward referenced symbol 'INT1addr' in .org
5
G:\Software Projects\2013\March\Interrupts\ExternInterrupt.asm(9): error: Overlap in .cseg: addr=0x0 conflicts with 0x0:0x1
#3108162
Lesenswert?

K. R. schrieb:
> Ich habe mir ja das Datenblatt vom Atmega48PA durchgelesen, da steht
> aber nichts davon, dass INT1 für PICINT8 bis 14 verantwortlich wäre...

Datenblatt:
13. External Interrupts
The pin change interrupt PCI1 will trigger if any enabled PCINT[14:8] 
pin toggles.

Was Du benutzen willst ist nicht INT1 (Vector 3) sondern PCINT1 (Vector 
5). Weiter steht dort:

The PCMSK2, PCMSK1 and PCMSK0 Registers control which pins contribute to 
the pin change interrupts.

Das heist für Dich, Du mußt im PCMSK1 noch die Maske einstellen, auf 
welchen PIN oder welche PINs der Interrupt reagieren soll.

K. R. schrieb:
> wie kann
> ich aber gezielt den Interrupt auf nur einen PIN, nämlich PC0 setzen?

Im PCICR das Bit PCIE1 setzen (Pin Change Interrupt Enable 1)
Im PCMSK1 das Bit PCINT8 setzen (Pin Change Enable Mask 8)
Interrupts generell erlauben
Auswerteroutine bei Interruptvektor PCINT1 starten (rjmp auf die 
Routine).

Die Routine wird bei jedem Pegelwechsel aufgerufen, ob Dein PIN auf L 
oder auf H gewechselt ist, mußt Du in der Routine selbst feststellen.

Reinhard
Gast #3108170
Lesenswert?

Hi

>.org 0x000
>         rjmp start            ; Reset Handler
>.org INT0addr
>     NOP
>.org INT1addr
>         rjmp interrupt    ; IRQ1 Handler

>.include "M48PAdef.inc"


>G:\Software Projects\2013\March\Interrupts\ExternInterrupt.asm(6): error: Use of 
undefined or forward referenced symbol 'INT0addr' in .org

Das Include gehört an den Anfang des Programms. Vor dem .include 
"M48PAdef.inc" weiß der Assemler nicht, was z.B. 'INT0addr' bedeutet.

MfG spess
#3108177
Lesenswert?

K. R. schrieb:
> Fehlermeldung :
ist ja nun geklärt.

Und tu Dir selbst einen Gefallen und setze an den Anfang Deiner 
Programme die gesamte Interruptvektortabelle. Bei nicht genutzen 
Interrupts ein reti reinschreiben. Später -in größeren Programmen- 
sollte man für nicht genutzte Interrupts eine Routine haben, die 
wenigstens die ungewollte Auslösung eines solchen meldet bzw. 
registriert. Aber für den Anfang reicht ein reti.

Reinhard
OP #3108214
Lesenswert?

Reinhard R. schrieb:
> K. R. schrieb:
>> Fehlermeldung :
> ist ja nun geklärt.
>
> Und tu Dir selbst einen Gefallen und setze an den Anfang Deiner
> Programme die gesamte Interruptvektortabelle. Bei nicht genutzen
> Interrupts ein reti reinschreiben. Später -in größeren Programmen-
> sollte man für nicht genutzte Interrupts eine Routine haben, die
> wenigstens die ungewollte Auslösung eines solchen meldet bzw.
> registriert. Aber für den Anfang reicht ein reti.
>
> Reinhard

Zwei Probleme sind da aber immer noch:

1)
Der Assembler findet :
1
LDI PCICR, 0b00000010
2
LDI PCMSK1,0b00000001

ist nicht möglich :
1
G:\Software Projects\2013\March\Interrupts\ExternInterrupt.asm(27): error: Invalid register
2
G:\Software Projects\2013\March\Interrupts\ExternInterrupt.asm(28): error: Invalid register
hm...

2)
Irgendwie klappt das mit dem RETI nach dem Include aber auch nicht:
1
.include "M48PAdef.inc"
2

3
; INTERRUPTS INITIALISIEREN bei PCINT8
4

5
.ORG RESET RJMP
6
RETI
7
RETI
8
RETI
9
.ORG PCINT1 RJMP interrupt    ; IRQ1 Handler
10
RETI
11
RETI
12
RETI
13
RETI
14
RETI
15
RETI
16
RETI
17
RETI
18
RETI
19
RETI
20
RETI
21
RETI
22
RETI
23
RETI
24
RETI
25
RETI
26
RETI
27
RETI
28
RETI
29
RETI
30
RETI
31

32
start:
33
SEI
34

35
LDI PCICR, 0b00000010
36
LDI PCMSK1,0b00000001
37

38

39
.DEF STACK_LOW = R16
40
.DEF STACK_HIG = R17
41

42
.DEF COUNTER = R25
43
; //////////////////////////////////////////////////////////////
44
; Stackpointerinitialisierung
45
  LDI STACK_LOW, LOW(RAMEND)    ;Stackpointer initialisieren
46
  OUT SPL, STACK_LOW
47
  LDI STACK_HIG, HIGH(RAMEND)   ;Stackpointer initialisieren
48
  OUT SPH, STACK_HIG
49
; //////////////////////////////////////////////////////////////
50

51
; LCD INITIALISIEREN
52
RCALL Wait1000MS
53
RCALL LCD_INIT
54
;... ab hier weiter wie bisher

Fehler:
1
G:\Software Projects\2013\March\Interrupts\ExternInterrupt.asm(6): error: Use of undefined or forward referenced symbol 'RESET' in .org
2
G:\Software Projects\2013\March\Interrupts\ExternInterrupt.asm(10): error: Overlap in .cseg: addr=0x1 conflicts with 0x0:0x4
3
G:\Software Projects\2013\March\Interrupts\ExternInterrupt.asm(11): error: Overlap in .cseg: addr=0x2 conflicts with 0x0:0x4
4
G:\Software Projects\2013\March\Interrupts\ExternInterrupt.asm(12): error: Overlap in .cseg: addr=0x3 conflicts with 0x0:0x4
Gast #3108231
Lesenswert?

Hi

>LDI PCICR, 0b00000010
>LDI PCMSK1,0b00000001

ldi funktioniert nur mit den Registern r16...r31.

>.ORG RESET RJMP
>.ORG PCINT1 RJMP interrupt    ; IRQ1 Handler

Das '.org xyz' und 'rjmp abcd' gehören in verschieden Zeilen.

Hast du dir eigentlich mal das Tutorial hier angesehen? Da steht drin, 
wie man es richtig macht.

MfG Spess
#3108281
Lesenswert?

K. R. schrieb:
> Der Assembler findet :
> LDI PCICR, 0b00000010
> LDI PCMSK1,0b00000001
>
> ist nicht möglich...

Steht alles im Datenblatt, aber das ist -zugegebenermaßen- recht groß.
Also, Datenblatt:

8.5 I/O Memory
... For the Extended I/O space from 0x60 - 0xFF in SRAM, only the
ST/STS/STD and LD/LDS/LDD instructions can be used.

PCICR hat die Adresse 0x68
PCMSK1 hat die Adresse 0x6C
fallen also beide in die oben zitierte Kategorie. Wird dann so gemacht:

ldi ZH,high(PCICR)
ldi ZL,low(PCICR)
ldi r16,0b00000010
st  Z,r16
ldi ZH,high(PCMSK1)
ldi ZL,low(PCMSK1)
ldi r16,0b00000001
st  Z,r16

Dann freut sich Dein AVR-Studio :-)

Reinhard
Gast #3108302
Lesenswert?

Hi

>ldi ZH,high(PCICR)
>ldi ZL,low(PCICR)
>ldi r16,0b00000010
>st  Z,r16
>ldi ZH,high(PCMSK1)
>ldi ZL,low(PCMSK1)
>ldi r16,0b00000001
>st  Z,r16

>Dann freut sich Dein AVR-Studio :-)

Eher nach dem Motto 'von hinten durch die Brust ins Auge'. Ein
1
  ldi r16,1<<PCIE1
2
  sts PCICR,r16
3
  ldi r16,1<<PCINT8
4
  sts PCMSK1,r16
reicht und ist besser lesbar.

MfG Spess
OP #3108345
Lesenswert?

Danke erstma für eure hilfe,

aber es will immer noch nicht klappen :
1
.include "M48PAdef.inc"
2

3
; INTERRUPTS INITIALISIEREN bei PCINT8
4

5
.ORG 0x000
6
  RJMP start
7
RETI
8
RETI
9
RETI
10
.ORG PCINT1 
11
  RJMP interrupt    ; IRQ1 Handler
12
RETI
13
RETI
14
RETI
15
RETI
16
RETI
17
RETI
18
RETI
19
RETI
20
RETI
21
RETI
22
RETI
23
RETI
24
RETI
25
RETI
26
RETI
27
RETI
28
RETI
29
RETI
30
RETI
31
RETI
32
RETI
33

34
start:
35
SEI
36

37
ldi ZH,high(PCICR)
38
ldi ZL,low(PCICR)
39
ldi r16,0b00000010
40
st  Z,r16
41
ldi ZH,high(PCMSK1)
42
ldi ZL,low(PCMSK1)
43
ldi r16,0b00000001
44
st  Z,r16
45

46
.DEF STACK_LOW = R16
47
.DEF STACK_HIG = R17
48

49
.DEF COUNTER = R25
50
; //////////////////////////////////////////////////////////////
51
; Stackpointerinitialisierung
52
  LDI STACK_LOW, LOW(RAMEND)    ;Stackpointer initialisieren
53
  OUT SPL, STACK_LOW
54
  LDI STACK_HIG, HIGH(RAMEND)   ;Stackpointer initialisieren
55
  OUT SPH, STACK_HIG
56
; //////////////////////////////////////////////////////////////
57

58
; LCD INITIALISIEREN
59
RCALL Wait1000MS
60
RCALL LCD_INIT
61
;... hier gehts weiter
1
G:\Software Projects\2013\March\Interrupts\ExternInterrupt.asm(11): error: Overlap in .cseg: addr=0x1 conflicts with 0x0:0x4
2
G:\Software Projects\2013\March\Interrupts\ExternInterrupt.asm(12): error: Overlap in .cseg: addr=0x2 conflicts with 0x0:0x4
3
G:\Software Projects\2013\March\Interrupts\ExternInterrupt.asm(13): error: Overlap in .cseg: addr=0x3 conflicts with 0x0:0x4

Sorry Leute, aber in meinem Buch und den meisten Tutorials (ICH BIN NOCH 
ANFÄNGER, UND MAßE MIR NICHT AN ALLES ZU KÖNNEN!) wird das anders 
gemacht... Deshalb seid mir nicht böse wenn ich wieder was übersehen 
habe, aber ich sehe es echt nicht, und die nächste Sache ist, dass es 
mich wundert, denn im Tutorial stand nicht explizit dass ein 
Zeilenumbruch nötig ist, ich dachte zumindest, weil es in anderen 
Programmiersprachen teilweise auch so ist, dass es nicht nötig ist...

Ich hoffe ihr könnt mir bei diesem letzten Problem helfen, danke

m.f.G. Developer_X
#3108352
Lesenswert?

K. R. schrieb:

> Sorry Leute, aber in meinem Buch und den meisten Tutorials (ICH BIN NOCH
> ANFÄNGER, UND MAßE MIR NICHT AN ALLES ZU KÖNNEN!) wird das anders
> gemacht...

Dann mach es so, wie du es dort liest.

Aber sieh dir die Dinge um Himmels willen endlich mal GENAU und EXAKT 
an! Es reicht nicht, wenn du die Dinge einfach irgendwie wischi waschi 
abmalst und nach Gutdünken einfach irgendwie in ein File 
zusammenkopierst. Sorgfalt ist einer der Um- Und AUf-Dinge in der ganze 
Programmierung. Sorgfalt und die Beachtung von Details.
Dazu gehören Schreibweisen, dazu gehören Reihenfolgen, dazu gehört Doku 
lesen, dazu gehört ... alles.
WEnn du das nicht kannst, dann fehlt dir etwas wesentliches was ein 
Programmierer haben muss. In dem Fall wäre ein Kunststudium vorzuziehen. 
Da kann man hinterher immer noch sagen, das sollte so sein und die 
Putzfrau verklagen, die das Kunstwerk mit einem Müllhaufen verwechselt 
hat.
Gast #3108362
Lesenswert?

Es mag vielleicht sein, das in den Beispielen nur eine der Möglichkeiten 
benutzt wird, etwas zu erledigen, ohne Hinweis darauf, das es auch 
anders geht. Gerade deswegen ist es empfehlenswert, erstmal genau den 
Beispielen zu folgen und ergänzend ein C-Buch zu lesen. Ansonsten musst 
Du Dir vorwerfen lassen, nicht in jeder zweiten Zeile den Namen Deiner 
Grossmutter genannt zu haben, denn es stand ja nicht da, das das nicht 
zulässig ist.

Naja. Gut, das ich den schönen Artikel über css hier gelesen habe. Dann 
gehab Dich wohl.
#3108369
Lesenswert?

PCINT0 ist nicht das was du denkst das es ist.

Die Konstante für die Speicherposition des Interrupt Vektors des PCINT1 
heißt
   PCI1addr

Alle symbolischen Namen der Interrupt Vektoren haben IMMER die Endung 
'addr'.
1
.ORG 0x000
2
  RJMP start
3
RETI
4
RETI
5
RETI
6
.ORG PCI1addr 
7
  RJMP interrupt    ; IRQ1 Handler
8
...

Wenn man sie nicht auswendig weiß, dann hindert einen nichts und niemand 
daran, mal das File M48PAdef.inc im Editor aufzumachen und dort drinnen 
nachzusehen. Mit einem Suchen nach "addr" ist man recht schnell bei der 
Aufzählung der symbolischen Namen für alle Interrupt Vektoren.
Gast #3108376
Lesenswert?

Hi

>.ORG PCINT1

Bei meinem Assmbler ( AVR Studio 4.19 Assembler2) nennt sich das 
'PCI1addr' und nicht PCINT1.

Aus der Include Datei:
.equ  PCI1addr  = 0x0004  ; Pin Change Interrupt Request 0
.equ  PCINT1  = 1  ; Pin Change Enable Mask 1

Da der Assembler dann statt .org. 0x0004 .Org 1 einsetzt kommt natürlich 
das Problem mit dem Overlapping.

MfG Spess
OP #3108759
Lesenswert?

Danke, hat jetzt geklappt :D.

Ein Problem ist da immer noch : Die ISR wird 2x aufgerufen.

Im Tutorial wird ja gesagt :
1
int0_handler:
2
         push temp             ; Das SREG in temp sichern. Vorher
3
         in   temp, SREG       ; muss natürlich temp gesichert werden
4
 
5
         sbi PORTB, 0
6
 
7
         out SREG, temp        ; Die Register SREG und temp wieder
8
         pop temp              ; herstellen
9
         reti
Mit RETI wird die ISR beendet.

Bei meiner ISR :
1
interrupt:
2
CLI
3
PUSH ZL
4
PUSH ZH
5
LDI ZL,LOW (text*2)
6
LDI ZH,HIGH(text*2)
7

8
RCALL LCD_LINE2
9

10
loop:
11
  LPM
12

13
; Testen ob Ende
14
  TST R0
15
  BREQ b
16

17
; Zeichen ausgegeben
18
  MOV INFO,R0
19
  RCALL LCD_DATA
20

21
; Zeiger auf nächstes Byte setzen
22
  ADIW ZL,1
23
  RCALL Wait1000MS
24
  RJMP loop
25

26
b :
27
  RCALL LCD_LINE1
28
  RCALL Wait1000MS
29
  RCALL Wait1000MS
30
  RCALL LCD_CLEAR
31

32
  SEI
33
  POP ZH
34
  POP ZL  
35
  RETI

ist das ja auch so, und sie dauert so ungefähr 10 Sekunden,
d.h. den button habe ich schon längst wieder los gelassen, während die 
ISR läuft, und durch CLI wird ja der erneute Aufruf der ISR während 
dieser ISR verhindert. Komisch ist nur, dass nach der Ausführung von der 
ISR, die ISR nochmal aufgerufen wird, und dann erst wieder zum 
Hauptprogramm springt, was ist denn hier falsch?

Muss mann da den PC manipulieren, oder den Stack, oder soll man in 
diesem Falle einen anderen Befehl als "RETI" verwenden, um die ISR 
wirklich zu verlassen.

Ach ja, ich weiß dass ich sowohl den Z-Pointer für den Interrupt kram 
benutze, als auch für die Textauslese aus dem Flash in der ISR, deshalb 
habe ich ZL und ZH auch erstma im Stack gesichert, damit hinterher alles 
wieder so wie vorher sein sollte.

Warum klappt es aber trotzdem nicht?
Danke,
m.f.G. Developer_X
Gast #3108807
Lesenswert?

Hi

>ist das ja auch so, und sie dauert so ungefähr 10 Sekunden,
>d.h. den button habe ich schon längst wieder los gelassen, während die
>ISR läuft, und durch CLI wird ja der erneute Aufruf der ISR während
>dieser ISR verhindert. Komisch ist nur, dass nach der Ausführung von der
>ISR, die ISR nochmal aufgerufen wird, und dann erst wieder zum
>Hauptprogramm springt, was ist denn hier falsch?

Das ist ein PINCHANGE-Interrupt. Der löst bei jeder Flanke aus. Also 
beim Drücken und beim Loslassen. Außerdem prellt dein Schalter. Da gibt 
es sowieso mehrere Flanken.

Mit dem Cli/sei erreichst du gar nichts. Während des Interrupts passiert 
das automatisch. Aber wenn andere oder auch der gleiche Interrupt 
während der ISR auftreten wird das gespeichert und diese Interrupts 
werden nach Beenden Interruptroutine ausgeführt.

MfG Spess
OP #3108896
Lesenswert?

Spess53 schrieb:
> Mit dem Cli/sei erreichst du gar nichts. Während des Interrupts passiert
> das automatisch. Aber wenn andere oder auch der gleiche Interrupt
> während der ISR auftreten wird das gespeichert und diese Interrupts
> werden nach Beenden Interruptroutine ausgeführt.

Und da ist auch nichts zu umgehen?
Hm tja,
außerdem habe ich diese ISR nur so lang gemacht, um das mal auszutesten, 
und was am Bildschirm auszugeben, war ja nur ein Test.

Naja,
Danke dann nochma Leute!

m.f.G. Developer_X
OP #3109003
Lesenswert?

Justus Skorps schrieb:
> doch natürlich, einfach Flag vorm Rücksprung zurücksetzen...

Gut, habe ich versucht, klappt aber anscheinend nicht, im Datenblatt 
steht :
1
12.2.3 EIFR – External Interrupt Flag Register
2
....
3
• Bit 1 – INTF1: External Interrupt Flag 1
4
When an edge or logic change on the INT1 pin triggers an interrupt request, INTF1 becomes set
5
(one). If the I-bit in SREG and the INT1 bit in EIMSK are set (one), the MCU will jump to the corresponding
6
Interrupt Vector. The flag is cleared when the interrupt routine is executed.
7
Alternatively, the flag can be cleared by writing a logical one to it. This flag is always cleared
8
when INT1 is configured as a level interrupt.
Das heißt ich muss im Byte EIFR das Bit INTF1 setzen.

Jetzt steht in "m48adef.inc" :
1
; EIFR - External Interrupt Flag Register
2
.equ  INTF0  = 0  ; External Interrupt Flag 0
3
.equ  INTF1  = 1  ; External Interrupt Flag 1

Daher war mein Code, da man ja das Bit mit iener logischen 1 setzen 
soll, um das Flag zu löschen:
1
interrupt:
2
CLI
3

4
PUSH ZL
5
PUSH ZH
6
LDI ZL,LOW (text*2)
7
LDI ZH,HIGH(text*2)
8

9
RCALL LCD_LINE2
10

11
loop:
12
  LPM
13

14
; Testen ob Ende
15
  TST R0
16
  BREQ b
17

18
; Zeichen ausgegeben
19
  MOV INFO,R0
20
  RCALL LCD_DATA
21

22
; Zeiger auf nächstes Byte setzen
23
  ADIW ZL,1
24
  RCALL Wait1000MS
25
  RJMP loop
26

27
b :
28
  RCALL LCD_LINE1
29
  RCALL Wait1000MS
30
  RCALL Wait1000MS
31
  RCALL LCD_CLEAR
32

33
  SEI
34
  POP ZH
35
  POP ZL  
36

37
  ldi ZH,high(INTF1)
38
  ldi ZL,low(INTF1)
39
  ldi r16,0b00000011  ; Flags löschen, sodass nicht nochmals der Interrupt ausgelöst wird
40
  st  Z,r16  
41

42
  RETI
Es läuft aber trotzdem wieder.

Was habe ich da falsch verstanden?
OP #3109288
Lesenswert?

Also nur in einem Treffer von mir
https://www.google.de/#hl=de&safe=off&sclient=psy-ab&q=mikrocontroller+isr+wird+zweimal+aufgerufen&oq=mikrocontroller+isr+wird+zweimal+aufgerufen&gs_l=hp.3...347.6107.0.6253.47.38.1.6.6.0.188.5382.1j36.37.0...1.0...1c.1.7.psy-ab.CiolrlryloE&pbx=1&bav=on.2,or.r_qf.&bvm=bv.44442042,d.Yms&fp=6f8d6a216c372f06&biw=1760&bih=832
habe ich das gefunden :
Beitrag "Interrupt wird zwei mal aufgerufen"
GIFR = (1<<INTF1);

Das soll am Ende der ISR stehen, komischer weise habe ich keine Ahnung 
was GIFR ist.
Im Datenblatt und in der inc datei steht nichts.

Wäre wenigstens einer von euch so freundlich mir endlich mal zu 
erklären, wie ich das verdammt nochmal machen soll, ihr könnt doch nicht 
erwarten dass man als Anfänger alles kann. Woher soll ich denn überhaupt 
wissen was GIFR ist, habt endlich mal ein bisschen einsicht, denn das 
bringt mir überhaupt nichts konstruktives.

Ist es so schwer mir endlich zu sagen, wie ich mein Problem lösen kann, 
und das Interrupt zurücksetzen kann??? (IN ASSEMBLER CODE)!!!
#3109308
Lesenswert?

K. R. schrieb:
> Ist es so schwer mir endlich zu sagen, wie ich mein Problem lösen kann,
> und das Interrupt zurücksetzen kann???

es wurde dir schon zig Mal gesagt: Im richtigen Register das richtige 
Bit auf 1 setzen...niemand hier kann was dafür, dass dir anscheinend 
selbst die absoluten Basics fehlen! Der Bitname bringt einem nummal 
nichts, wenn man nicht das passende Register kennt...
OP #3109354
Lesenswert?

In Artikel
Beitrag "Atmega8 Taster an Interrupt löst zweimal aus"

heißt es :
der mechatroniker schrieb:
> Ok, ein Versuch einer Erklärung, was passiert.
>
> 1. Der Interrupt wird ausgelöst. Das interne Flag für die
> Interruptquelle wird zurückgesetzt.

Das heißt, wenn ich dann das flagregister abspeicher, und vor dem Ende 
der ISR wieder in das EIFR lade, dann sollte doch alles klappen?
1
interrupt:
2

3

4
PUSH ZL
5
PUSH ZH
6
LDI ZL,LOW (text*2)
7
LDI ZH,HIGH(text*2)
8

9
  ldi ZH,high(EIFR) ; GELÖSCHTES FLAG SPEICHERN
10
  ldi ZL,low(EIFR)
11
  LD  r16,Z  
12

13
RCALL LCD_LINE2
14

15
loop:
16
  LPM
17

18
; Testen ob Ende
19
  TST R0
20
  BREQ b
21

22
; Zeichen ausgegeben
23
  MOV INFO,R0
24
  RCALL LCD_DATA
25

26
; Zeiger auf nächstes Byte setzen
27
  ADIW ZL,1
28
  RCALL Wait1000MS
29
  RJMP loop
30

31
b :
32
  RCALL LCD_LINE1
33
  RCALL Wait1000MS
34
  RCALL Wait1000MS
35
  RCALL LCD_CLEAR
36

37
  POP ZH
38
  POP ZL  
39

40
  ldi ZH,high(EIFR) ; GELÖSCHTES FLAG WIEDERHERSTELLEN
41
  ldi ZL,low(EIFR)
42
  st  Z,r16  
43

44
  RETI
NEIN TUT ES NICHT.

Und ganz ehrlich, vielleicht hattet ihr ja das Glück diese Sachen zu 
studieren, oder in einer Ausbildung zu lernen, ich nicht, und ich 
verstehs nicht, viele dinge über die ihr redet, werden bei ner 
Googlesuche nicht annähernd erklärt, ok dann hab ich eben keine Basics, 
wo soll ich die denn herbekommen? (Komisch, in meinem Buch brauch ich 
eure "BASICS" nicht)

Und ganz ehrlich, wenn mir jemand den Code endlich geben würde, dann 
könnte ich es auch endlich mal nachvollziehen, falls einer von euch so 
kompetent wäre...
OP #3109362
Lesenswert?

JA schon klar, aber was ist, wenn meine ISR so lange dauert, dass das 
prellen keine rolle spielt, (ICH HABE DAS MIT DEM PRELLEN GELESEN),
und ich einfach am ende der ISR ein Byte ändere, das EIFR, und dann wird 
es nicht mehr aufgerufen.

WARUM KLAPPT ES DANN NICHT; WAS KANN ICH TUN=?
OP #3109413
Lesenswert?

1
interrupt:
2
CLI
3

4
PUSH ZL
5
PUSH ZH
6
LDI ZL,LOW (text*2)
7
LDI ZH,HIGH(text*2)
8

9
RCALL LCD_LINE2
10

11
loop:
12
  LPM
13

14
; Testen ob Ende
15
  TST R0
16
  BREQ b
17

18
; Zeichen ausgegeben
19
  MOV INFO,R0
20
  RCALL LCD_DATA
21

22
; Zeiger auf nächstes Byte setzen
23
  ADIW ZL,1
24
  RCALL Wait1000MS
25
  RJMP loop
26

27
b :
28
  RCALL LCD_LINE1
29
  RCALL Wait1000MS
30
  RCALL Wait1000MS
31
  RCALL LCD_CLEAR
32

33
  SEI
34
  POP ZH
35
  POP ZL  
36

37
  ldi ZH,high(EIFR)
38
  ldi ZL,low(EIFR)
39
  ldi r16,0b00000011  ; Flags löschen, sodass nicht nochmals der Interrupt ausgelöst wird
40
  st  Z,r16  
41

42
  RETI

FUNKTIONIERT AUCH NICHT!

Ob ich r16 jetzt das zweite Bit (also Bit 1) auf 1 oder 0 setze, beides 
klappt nicht.

Ich weiß nicht mehr weiter.
Gast #3109476
Lesenswert?

>
loop:
  LPM

; Testen ob Ende
  TST R0
  BREQ b

; Zeichen ausgegeben
  MOV INFO,R0
  RCALL LCD_DATA

; Zeiger auf nächstes Byte setzen
  ADIW ZL,1
  RCALL Wait1000MS
  RJMP loop
.....................................

Die volle Droehnung was ?

Sowas gibt's nicht. Es gibt weder loops, noch einen Delay in einem 
Interrupt. Dies wurde schon mehrfach erwaehnt. Lass es sein, das wird 
nie was. Pflanze Osterglocken oder sowas. Sorry.

Wenn's denn mit Warten sein soll :
http://www.ibrtses.com/embedded/avrlcd.html
OP #3109483
Lesenswert?

Ich habs ganz pragmatisch hinbekommen,
und ja ich weiß dass interrupts in der regel nicht für langatmige dinge 
gedacht sind :
1
interrupt:
2

3
IN  r18, PINC
4
SBRC r18,0 
5
RETI
6

7
PUSH ZL
8
PUSH ZH
9
LDI ZL,LOW (text*2)
10
LDI ZH,HIGH(text*2)
11

12
RCALL LCD_LINE2
13

14
loop:
15
  LPM
16

17
; Testen ob Ende
18
  TST R0
19
  BREQ b
20

21
; Zeichen ausgegeben
22
  MOV INFO,R0
23
  RCALL LCD_DATA
24

25
; Zeiger auf nächstes Byte setzen
26
  ADIW ZL,1
27
  RCALL Wait1000MS
28
  RJMP loop
29

30
b :
31
  RCALL LCD_LINE1
32
  RCALL Wait1000MS
33
  RCALL Wait1000MS
34
  RCALL LCD_CLEAR
35

36
  POP ZH
37
  POP ZL  
38

39
  RETI
Genauso funktionierst, nichts mit manipulation von bytes sondern einfach 
gucken, bei neustart der ISR ob der button an ist oder nicht, und dann 
sein lassen oder isr durchführen

danke trotzdem, jetzt weiß ich schon ma mehr,
m.f.G. Developer_X

und frohe Ostern
Gast #3109525
Lesenswert?

K. R. schrieb:
> Wie soll ich denn bits in registern setzen, was ich kann, ich kann sie
> sogar auslesen, wenn ich nicht weiß wie sie heißen???

Lesen kannst du ja irgendwie schon. Wieso schaust du nicht einfach im 
Datenblatt nach? Das dauert 2 Minuten und die Wurst ist gegessen.
Gast #3109546
Lesenswert?

Hi

>interrupt:
>CLI
>...
>  SEI
>  POP ZH
>...

Noch mal: Das cli und sei haben in der Interruptroutine nichts zu 
suchen. Das sei vor dem reti bewirkt sogar das Gegenteil von dem was du 
vor hast. Denn damit gibst du anderen Interrupts die Möglichkeit deinen 
Interrupt zu unterbrechen.

>FUNKTIONIERT AUCH NICHT!

Kann auch nicht. Weil

1. PCIFR für den PCINT zuständig ist
2. es auch so auch mit PCIFR nicht funktioniert:

EIFR und PCIFR liegen in dem Speicherbereich der mit in/out adressierbar 
ist. Und der fängt nach den Registern r0...r31 mit Null an. So sind auch 
die Adressen in der 'M48PAdef.inc' definiert.

>  ldi ZH,high(EIFR)
>  ldi ZL,low(EIFR)
>...
>  st  Z,r16

Der damit adressierte Speicher fängt aber bei $0000 (r0) an. Damit ist 
die Adresse die mit EIFR in der 'M48PAdef.inc' definiert ist um $20 zu 
klein. Ein
1
ldi r16,xyz
2
out PCIFR,r16
ist weniger umständlich und trifft das richtige Register.

Noch etwas allgemeines:

Deiner Interruptroutine fehlt das Sichern von SREG. Fällt bei dir nicht 
auf, führt aber bei richtigen Programmen zu mehr oder weniger lustigen 
Effekten.

Statt die IF-Register zu manipulieren ist es bei PCINTs sinnvoller, am 
Interruptanfang den Pegel des Pins abzufragen. Damit kannst du 
feststellen, welche Flanke den Interrupt ausgelöst hat und entsprechend 
reagieren.

MfG Spess
OP #3109876
Lesenswert?

Danke Leute, aber ganz ehrlich ich habe im Datenblatt das Kapitel 
Interrupts und External Interrupts gelesen, ich bin doch noch anfänger 
und in meinem Buch etc. steht nichts von PCIFR, woher soll ich denn 
wissen dass das PCIFR ist, ich weiß ganz ehrlich nicht woher ich das 
hätte wissen sollen, fakt ist es klappt jetzt, und das SREG wird auch 
gesichert.

Danke euch allen, und seid mir nicht böse, aber ich muss mir das alles 
selbst beibringen, und habe nicht so viele quellen und anscheinend auch 
nicht dieses "BASIS" Wissen, um die Dinge zu suchen, die ihr meint.
Gast #3109912
Lesenswert?

Hi

> woher soll ich denn
>wissen dass das PCIFR ist, ich weiß ganz ehrlich nicht woher ich das
>hätte wissen sollen,

Na ja, die Namen der Register, die für die externen Interrupts (INT0/1) 
zuständig sind fangen alle mit 'E' an. Die Namen der für die Pin Change 
Interrupts zuständigen Register sinnigerweise mit PC.

>Danke euch allen, und seid mir nicht böse, aber ich muss mir das alles
>selbst beibringen,

Das habe ich vor 30 Jahren auch gemacht.

>und habe nicht so viele quellen und anscheinend auch
>nicht dieses "BASIS" Wissen, um die Dinge zu suchen, die ihr meint.

Von der Quellenvielfalt, die heute zur Verfügung steht, konnte ich 
damals nur träumen. Man muss sie halt auch nutzen.

MfG Spess

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren