mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik AVR, Externer Interrupt 11 beim Atmega168 -> Howto-Problem


Autor: Rolf S. (rollo)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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

Autor: Johannes M. (johnny-m)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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...

Autor: Peter Dannegger (peda)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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

Autor: Rolf S. (rollo)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Besten Dank für Eure schnellen Hints -> ich ahne schon etwas Licht am 
Ende des Tunnels....

Autor: Rolf S. (rollo)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> 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...
' -----------------------------------------------------------------------
' PIN CHANGE INTERRUPTS / ATMEGA168 / BASCOM
' siehe auch ATMEL-Datenblatt Seiten 70 und 345
' -----------------------------------------------------------------------

$regfile = "m168def.dat"
$crystal = 20000000
$hwstack = 80
$swstack = 80
$framesize = 80
' -----------------------
Dim Countx As Integer
Dim Iportval As Byte
Dim Iportvalold As Byte
Dim Iportdif As Byte
' -----------------------
Declare Sub Blinksig
' -----------------------
Config Lcdpin = Pin , Db4 = Portb.0 , Db5 = Portb.1 , Db6 = Portb.2 , Db7 = Portb.3 , E = Portb.4 , Rs = Portb.5
Config Lcd = 16 * 1a                                        ' LCD-Modul 1x16


' ------------------------
' Port-Settings (Beispiel)
' ------------------------
Sensor_1 Alias Portc.3                                      ' PCINT 11
Sensor_2 Alias Portc.2                                      ' PCINT 10
Sensor_3 Alias Portc.1                                      ' PCINT  9
Sensor_4 Alias Portc.0                                      ' PCINT  8
Config Sensor_1 = Input
Config Sensor_2 = Input
Config Sensor_3 = Input
Config Sensor_4 = Input
Sensor_1 = 1                                                ' Pullups
Sensor_2 = 1
Sensor_3 = 1
Sensor_4 = 1
' ------------------------
Actor_1 Alias Portc.5
Config Actor_1 = Output
' ------------------------



' ---------------------------
' Interrupt settings mit
' Besonderheiten in Bascom
' ---------------------------
' PCINT1 ist NICHT der IC-Pin "PcInt1",
' sondern der "reaction Block" für logiclevel-changes
' an PortC (aktive Pins siehe PCMSK1)

On Pcint1 Isr_1
Enable Pcint1

' PCINT8..11 als ext. Interrupt-Pins maskieren.
' Wenn an einem dieser Pins ein Logiklevel WECHSELT,
' dann wird der Interrupt "Pcint1" ausgelöst

Pcmsk1 = &B00001111



' PCIE1-Block enable
' Die Pins PCINT8..14 werden hier als Block freigeschaltet

Pcicr = &B00000010




' -----------------------
' Initialisieren
' -----------------------
Countx = 0
Iportval = 0
Iportvalold = 0
' -----------------------

' +++++++++++++++++++++++++++++
' Main loop
' +++++++++++++++++++++++++++++
Cls
Lcd "<Bereit>"
Enable Interrupts
Do
   ' godot...
Loop
End
' +++++++++++++++++++++++++++++


' -----------------------
' Subroutine
' -----------------------
Sub Blinksig
   Actor_1 = 0
   Waitms 5
   Actor_1 = 1
End Sub
' -----------------------


' ---------------------------*******************************************
' Interrupt service routine
' ---------------------------*******************************************
Isr_1:

   Disable Interrupts

   ' Wert vom Port holen und Mögl. betroffene Bits ausfiltern
   Iportval = Portc And &B00001111

   ' Änderungen zum vorherigen Wert ermitteln
   Iportdif = Iportvalold Xor Iportval

   ' Info
   Call Blinksig
   Countx = Countx + 1
   If Countx > 299 Then
      Countx = 0
   End If
   Cls
   Lcd ">" ; Bin(iportdif) ; " >" ; Countx

   ' Aktuellen Portwert für nächsten Interrupt merken
   Iportvalold = Iportval

   Enable Interrupts

   Return

' -----------------------

Autor: Peter Dannegger (peda)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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

Autor: Rolf S. (rollo)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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

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.