Bin jetzt nach 2 Tagen erfolgloser Suche soweit, dass ich dringend auf Eure geneigte Expertise angewiesen bin. Ich betreibe einen Atmega168 bei ext. 20MHz und benötige zur Steuerung vier externe Interrupts, die aufgrund der Layoutvorgaben nur an Pins PCINT8/ PCINT9/ PCINT10/ PCINT11 angelegt werden können. Die Signale dort kommen auf TTL-Pegel mit einem Abstand von ca. 1 bis 100ms. Ich verwende als Entwicklungsumgebung BASCOM-AVR in der Version 1.11.8.4. und kann damit nur Routinen bis ENABLE INT7 definieren (Handbücher und Datenblätter habe ich schon rauf, runter und durch). So wie ich es bisher verstanden habe, muss man für die "höheren" Interrupts so etwas wie Vektoren und/oder Masken ensetzen - und hier liegt mein Problem -> Wie definiert man in BASCOM AVR BASIC die Routinen für Interrupts oberhalb von PCINT7? Für einen kleinen Hirnschubser in die richtige Richtung wäre ich schon dankbar. Rolf
Erstmal sind die Pin Change Interrupts etwas anderes als die "normalen" externen Interrupts, da sie erstens grundsätzlich auf jeden Pegelwechsel reagieren (also nicht konfigurierbar sind) und da jeder Pin Change Interrupt von einer bestimmten Anzahl von Pins ausgelöst werden kann (externe Interrupts nur durch jeweils einen einzigen Pin). Um zu definieren, auf welche Pins der Interrupt reagieren soll, muss man die Pins maskieren. INT0 usw. bezieht sich auf die externen Interrupts, und davon hat der ATMega168 nur zwei Stück, nämlich INT0 und INT1. INT2...INT7 gibt es da gar nicht. Die Pins PCINT7...0 sind dem Interrupt PCI0 zugeordnet. Steht aber alles im Datenblatt...
Rolf S. wrote: > Ich betreibe einen Atmega168 bei ext. 20MHz und benötige zur Steuerung > vier externe Interrupts, die aufgrund der Layoutvorgaben nur an Pins > PCINT8/ PCINT9/ PCINT10/ PCINT11 angelegt werden können. Dann mußt Du einen Handler für PCINT1 definieren und natürlich die entsprechenden Enablebits in PCMSK1 setzen. Und in dem Handler mußt Du die 4 Inputs testen und mit dem vorherigen Zustand vergleichen, um zu sehen, auf welchem die Flanke war und in welche Richtung. Du hast also nur einen Handler für alle 4 Eingänge und mußt darin entscheiden, was bei welchem zu tun ist. Schau einfach mal ins Datenblatt, da steht alles drin. Peter
Besten Dank für Eure schnellen Hints -> ich ahne schon etwas Licht am Ende des Tunnels....
> Besten Dank für Eure schnellen Hints -> ich ahne schon etwas Licht am > Ende des Tunnels.... Nachfolgend mein Ansatz zur Lösung -> funktioniert leider nur zu 99%. Es ist mir letzendlich nicht gelungen zu ermitteln, welcher der Pins in einem Port den PCINT ausgelöst hat...
1 | ' ----------------------------------------------------------------------- |
2 | ' PIN CHANGE INTERRUPTS / ATMEGA168 / BASCOM |
3 | ' siehe auch ATMEL-Datenblatt Seiten 70 und 345 |
4 | ' ----------------------------------------------------------------------- |
5 | |
6 | $regfile = "m168def.dat" |
7 | $crystal = 20000000 |
8 | $hwstack = 80 |
9 | $swstack = 80 |
10 | $framesize = 80 |
11 | ' ----------------------- |
12 | Dim Countx As Integer |
13 | Dim Iportval As Byte |
14 | Dim Iportvalold As Byte |
15 | Dim Iportdif As Byte |
16 | ' ----------------------- |
17 | Declare Sub Blinksig |
18 | ' ----------------------- |
19 | Config Lcdpin = Pin , Db4 = Portb.0 , Db5 = Portb.1 , Db6 = Portb.2 , Db7 = Portb.3 , E = Portb.4 , Rs = Portb.5 |
20 | Config Lcd = 16 * 1a ' LCD-Modul 1x16 |
21 | |
22 | |
23 | ' ------------------------ |
24 | ' Port-Settings (Beispiel) |
25 | ' ------------------------ |
26 | Sensor_1 Alias Portc.3 ' PCINT 11 |
27 | Sensor_2 Alias Portc.2 ' PCINT 10 |
28 | Sensor_3 Alias Portc.1 ' PCINT 9 |
29 | Sensor_4 Alias Portc.0 ' PCINT 8 |
30 | Config Sensor_1 = Input |
31 | Config Sensor_2 = Input |
32 | Config Sensor_3 = Input |
33 | Config Sensor_4 = Input |
34 | Sensor_1 = 1 ' Pullups |
35 | Sensor_2 = 1 |
36 | Sensor_3 = 1 |
37 | Sensor_4 = 1 |
38 | ' ------------------------ |
39 | Actor_1 Alias Portc.5 |
40 | Config Actor_1 = Output |
41 | ' ------------------------ |
42 | |
43 | |
44 | |
45 | ' --------------------------- |
46 | ' Interrupt settings mit |
47 | ' Besonderheiten in Bascom |
48 | ' --------------------------- |
49 | ' PCINT1 ist NICHT der IC-Pin "PcInt1", |
50 | ' sondern der "reaction Block" für logiclevel-changes |
51 | ' an PortC (aktive Pins siehe PCMSK1) |
52 | |
53 | On Pcint1 Isr_1 |
54 | Enable Pcint1 |
55 | |
56 | ' PCINT8..11 als ext. Interrupt-Pins maskieren. |
57 | ' Wenn an einem dieser Pins ein Logiklevel WECHSELT, |
58 | ' dann wird der Interrupt "Pcint1" ausgelöst |
59 | |
60 | Pcmsk1 = &B00001111 |
61 | |
62 | |
63 | |
64 | ' PCIE1-Block enable |
65 | ' Die Pins PCINT8..14 werden hier als Block freigeschaltet |
66 | |
67 | Pcicr = &B00000010 |
68 | |
69 | |
70 | |
71 | |
72 | ' ----------------------- |
73 | ' Initialisieren |
74 | ' ----------------------- |
75 | Countx = 0 |
76 | Iportval = 0 |
77 | Iportvalold = 0 |
78 | ' ----------------------- |
79 | |
80 | ' +++++++++++++++++++++++++++++ |
81 | ' Main loop |
82 | ' +++++++++++++++++++++++++++++ |
83 | Cls |
84 | Lcd "<Bereit>" |
85 | Enable Interrupts |
86 | Do |
87 | ' godot... |
88 | Loop |
89 | End |
90 | ' +++++++++++++++++++++++++++++ |
91 | |
92 | |
93 | ' ----------------------- |
94 | ' Subroutine |
95 | ' ----------------------- |
96 | Sub Blinksig |
97 | Actor_1 = 0 |
98 | Waitms 5 |
99 | Actor_1 = 1 |
100 | End Sub |
101 | ' ----------------------- |
102 | |
103 | |
104 | ' ---------------------------******************************************* |
105 | ' Interrupt service routine |
106 | ' ---------------------------******************************************* |
107 | Isr_1: |
108 | |
109 | Disable Interrupts |
110 | |
111 | ' Wert vom Port holen und Mögl. betroffene Bits ausfiltern |
112 | Iportval = Portc And &B00001111 |
113 | |
114 | ' Änderungen zum vorherigen Wert ermitteln |
115 | Iportdif = Iportvalold Xor Iportval |
116 | |
117 | ' Info |
118 | Call Blinksig |
119 | Countx = Countx + 1 |
120 | If Countx > 299 Then |
121 | Countx = 0 |
122 | End If |
123 | Cls |
124 | Lcd ">" ; Bin(iportdif) ; " >" ; Countx |
125 | |
126 | ' Aktuellen Portwert für nächsten Interrupt merken |
127 | Iportvalold = Iportval |
128 | |
129 | Enable Interrupts |
130 | |
131 | Return |
132 | |
133 | ' ----------------------- |
Rolf S. wrote:
> Nachfolgend mein Ansatz zur Lösung -> funktioniert leider nur zu 99%.
Darunter kann sich niemand etwas vorstellen.
Was wird erwartet, was ist die Abweichung dazu?
Der Code sieht prinzipiell o.k. aus, außer den riesigen Wartezeiten im
Interrupt drin (lahme LCD-Ausgabe + 5ms Warten).
Interrupts sollten kurz sein, langsame Sachen sollte man nur im Main
machen.
Wenn Du für über 5ms sämtliche CPU-Aktivität im Interrupt blockierst,
kanns Du natürlich nie Pulse mit 1ms Abstand erkennen.
Peter
Danke für die Response... 1. Die 100% Lösung wäre, wenn ich erkennen könnte, an welchem Pin der Level-Change stattgefunden hat. Dies habe ich bisher noch nicht hinbekommen. 2. Die LED war nur zu Testzwecken dabei. Natürlich darf keine Bremse in der ISR bleiben. Rolf
Hallo, definiere parallel zu den PCINT-Pins die gleichen Pins als normale Input-Eingänge und frage Sie in der Interrupt-Routine auf Low ab und setze dann entsprechenden Flags, die Du auswerten kannst. So gelangst Du zu den auslösenden PCINT. MfG Bert
Bert schrieb: > Hallo, > definiere parallel zu den PCINT-Pins die gleichen Pins als normale > Input-Eingänge und frage Sie in der Interrupt-Routine auf Low ab und > setze dann entsprechenden Flags, die Du auswerten kannst. So gelangst Du > zu den auslösenden PCINT. > MfG > Bert Sonst gehts noch???
Vielleicht nicht elegant aber es funktioniert. Bei mir sieht das so aus:
1 | char test (void){ |
2 | int_mask = PCMSK0; |
3 | temp = PINB; |
4 | temp &= int_mask; |
5 | return temp; |
6 | }
|
und im Interrupt:
1 | ISR(PCINT0-vect){ |
2 | char x=0,y=0; |
3 | temp_old = temp; |
4 | test(); |
5 | x = temp; |
6 | x &= 4; |
7 | y = temp_old; |
8 | y &= 4; |
9 | |
10 | if (x==y) |
11 | {
|
12 | // Code falls es PB3 war...
|
13 | }
|
14 | }
|
Und nach dem veröffentliche erst gesehen, wie alt der Post ist....
:
Bearbeitet durch User
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.