2313A PIN Change Interrupt, zweiter Versuch

OP #3250625
Hallo zusammen,

die PIN Change Interrupts des 2313A bringen mich zur Verzweifelung. Hier 
mal ein Code mit dem ich:
a) den Interrupt INT0 getestet habe
b) mich mit der Sleep funktion auseinander gesetzt habe und....
c) der Pin Change Interrupt
1
#include <avr/io.h>
2
#include <avr/interrupt.h>
3
#include <avr/sleep.h>
4
#include <util/delay.h>
5
#define F_CPU 8000000UL      // 8 MHz (fuer delay.h)
6

7

8

9

10
  ISR (INT0_vect)
11
   
12
   {
13
      PINB = 0x02;
14
      asm("nop"); 
15
    
16
    }
17
    
18
    
19
   ISR (PCINT_B_vect) // für PinChange an Port A in PCINT_A_vect ändern
20
   {
21
      PINB = 0x04;
22
    asm("nop");
23
   }    
24

25
int main(void)
26

27
{
28
  DDRA = 0x00;  // auch ein setzten auf Oxff ( Port auf Ausgang ) bringt nichts
29
  PINA = 0x03; 
30
  DDRB = 0xff;
31
  DDRD = 0x00;
32
  
33
  
34
  
35
  // Interrupt INT0 auf ansteigende Flanke, POwer-down und Sleep mode setzen
36
  MCUCR |= (1<<ISC01) | (1<<ISC00) | (1<<SM0) | (1<<SE) | (1<<SM1);   
37
  
38
  
39
  //externer Interrupt INT0 und Pin-change einschalten
40
  GIMSK  |= (1<<INT0) | (1<<PCIE0);  // hier müßte ich eigentlich lt Datenblatt PCIE1 eintragen
41
  
42
  
43
  // mit PCMSK und PCINT7 ist PB7 der Interruptauslöser  
44
  PCMSK |= (1<<PCINT7);  // hier müßte PMSK1 und PCINT8 stehen
45

46
  sei();
47
  sleep_mode();  // wird durch INT0 ==PD2 oder PCIE0==PB7 wieder geweckt
48
  
49
  
50
  
51
  
52
  while(1)
53
    {
54
     asm("nop");
55
  }
56
  
57
  
58
}

Im Code, so wie er dort steht, funktionieren die Pin Chnage Interrupts 
des kpl. PORTB Registers ( je nach Angabe in PCINT0..PCINT7).
Da ich diverse, fertig bestückte und funktionierende Platinen besitze, 
möchte ich gerne einen PIN Change Interrupt an PA0 und/oder PA1 haben. 
Dazu habe ich im Quellcode mal die Punkte als Kommentar getippelt, die 
geändert werden müßten.
Lt. Datenblatt:

--  Im GIMSK das Bit3 PCIE1 setzen
--  Im PCMSK1 das Bit0, Bit1 PCINT8, PCINT9 setzen

--  den ISR des PIN-Change-Interrupt in PCINT_A_vect ändern

Nun geht der Spuk weiter. PCIE1 und PCMSK1 sind dem Compiler unbekannt. 
Also hier Forum gesucht und gefunden: die Headerdatei iotn2313a.h mit 
Texteditor um die fehlenden Punkte erweitert(#Define XXXXXX ).

Immer noch nada....Der PIN Change Interrupt geht nicht. Der 2313A 
verhält sich so wie sein Vorgänger 2313, mit PCIE nur an PORTB.

Nun weiß ich gar nicht mehr weiter und hoffe auf eure Hilfe. Ich habe 
mich zwar ein wenig in die Materie eingelesen, bin aber noch gaaaanz 
weit am Anfang der CPU Programmierung, daher bitte nicht sofort 
erschlagen....

Glück auf

Reinhard Pfeiffer
Gast
die Datei:  tn2313Adef.inc habe ich auch noch angepasst und zwar unter 
External Interrupt von PCIE nach PCIE1, PCIE2 und PCIE0 erweitert.

; ***** EXTERNAL_INTERRUPT ***********
; GIMSK - General Interrupt Mask Register
.equ  PCIE1  = 3  ;
.equ  PCIE2  = 4  ;
.equ  PCIE0  = 5  ;
.equ  INT0  = 6  ; External Interrupt Request 0 Enable
.equ  INT1  = 7  ; External Interrupt Request 1 Enable


Beitrag "Attiny2313A in AVR Toolchain (noch) nicht unterstützt?"
OP
Hallo tiny, hallo M.N.,

an tiny:

die Änderung/Ergänzung der Datei tn2313Adef.inc brachte leider bei mir 
nicht den gewünschten Erfolg. Hast du vielleicht einen funktionierenden 
Codeschnipsel für mich, oder weitere Ansatzpunkte zum forschen???

an M.N.

das PINA = 0x03 funktioniert beim 2313A wunderbar und stellt die 
logischen Werte der Hardware am Chip da ( PIN4 und PIN5 haben als 
Startwert H-Pegel ).

Glück auf

Reinhard Pfeiffer
Gast
Ich verwende z.B. einen Drehencoder am Port A des 2313A.
Encoderleitung A hängt an PA0 und Leitung B an PA1

Initialisiert habe ich dann beide Port A Pins als Eingang mit Pull-Up.

sowie den Pin-Change-Interrupt:


// Bit PCIE1 setzen (Pin Change Interrupt Enable 1 für PCINT an einem 
der Port A Pins)

GIMSK |= (1 << PCIE1);


// Maskenregister 1 für Pin Change Interrupt an Port A
// Bit PCINT8 setzen (Pin Change Interrupt an PA0 aktivieren) Encoder A

PCMSK1 |= (1 << PCINT8);



und die Interruptroutine sieht wie folgt aus:

// ISR für den Drehencoder Interrupt
ISR (PCINT_A_vect)
// Achtung !!!: PCINT0 -> PCINT_B_vect  PCINT1 -> PCINT_A_vect  PCINT2 
-> PCINT_D_vect
  {
    ***auszuführender Code***

    EIFR |= (1<< PCIF1); //  Flag löschen

  }
Reinhard P. schrieb:
> Im Code, so wie er dort steht, funktionieren die Pin Chnage Interrupts
> des kpl. PORTB Registers

Und warum zeigst Du uns das?

Du mußt schon den exakten Code zeigen, mit dem Du Probleme hast. 
Hellsehen ist nicht unser Ding.
Und erstmal die fehlenden Defines direkt einfügen, also mit dem 
originalen *.h compiliert.
Gast
spess53 schrieb:
> Dazu nimmt man keinen Pin-Change-Interrupt:


im Link über Drehgeber steht, dass die Methode nicht optimal ist, weil 
sie durch einen pendelnden/prellenden Encoder die CPU stark belastet.

Aber genau das fängt doch die Entrpellung auf oder sehe ich das falsch?
OP
Hallo tiny,


rechtz herzlichen Dank für die Codeschnipzel. Leider will weder der 
Debugger des Studio4 noch der des Studio6 den Pin-Change-Interrupt 
auslösen ( mit jeweils zur IDE passend geänderten Dateien ).

Ich werde morgen mal den Code in den Chip übertragen und sehen ob er 
dort seine Dienste verrichtet.

Ich melde mich morgen .....


Glück auf

Reinhard Pfeiffer
Gast
tiny schrieb:
> Aber genau das fängt doch die Entrpellung auf oder sehe ich das falsch?

Sofern die Interrupts direkt als Auf-Ab-Impulse gewertet werden, findet 
keine Entprellung statt. Sofern man keine Drehgeber mit mechanischen 
Kontakten verwendet, prellt allerdings auch nichts.

Wichtig bei der Auswertung per ISR ist, dass diese sehr schnell 
ausgeführt wird und vom Drehgeber keine höhere Impulsfrequenz erzeugt 
wird, als die ISRs diese verarbeiten können.

Meine Erfahrung:
Für schnelle Drehgeber die nicht prellen, ist die direkte Auswertung per 
Interrupt sinnvoll. Der Prozessor wird diesbezüglich nur bei Bedarf 
aktiv.
Bei Drehgebern mit mechanischen Kontakten und relativ niedriger 
Impulsfrequenz (<10kHz) ist das Abtasten der Port-Pins im festen 
Zeitraster und anschließende Auswertung per Software sinnvoll. Die 
Ruhelast durch permantes Abtasten bleibt recht gering (geschätzt <3% bei 
10kHz).
Gast
M. N. schrieb:
> Bei Drehgebern mit mechanischen Kontakten und relativ niedriger
> Impulsfrequenz (<10kHz) ist das Abtasten der Port-Pins im festen
> Zeitraster und anschließende Auswertung per Software sinnvoll.

D.h. in meinem Fall (Drehencoder als Eingabegerät per Handbetrieb) 
müsste ich in regelmäßigen Abständen Leitung A abfragen und mit dem 
Ergebnis der vorherigen Abfrage vergleichen. Bei Unterschied dann 
Leitung B abfragen und auswerten. Das Ganze dann halt deutlich 
schneller, als man den Encoder per Hand verdrehen kann.
Gast
tiny schrieb:
> D.h. in meinem Fall (Drehencoder als Eingabegerät per Handbetrieb)
> müsste ich in regelmäßigen Abständen Leitung A abfragen und mit dem
> Ergebnis der vorherigen Abfrage vergleichen.

Ich weiß jetzt nicht, welchen Drehgeber Du verwendest, aber es ist 
einfacher, Phase-A und Phase-B an einem Port zu betreiben, mit
"neuer_wert = PINx" einzulesen und auf Änderungen abzufragen:
wechsel = alter_wert ^ neuer_wert;
Sofern wechsel == 0, ist nichts passiert und nichts weiter auszuwerten.

Ein Beispielprogramm "Quadrat_CNT45.c" findest Du hier 
http://www.mino-elektronik.de/7-Segment-Variationen/LCD.htm#lcd4
Dort ist es die "ISR (TIMER1_OVF_vect)", die hinreichend schnell 
aufgerufen wird (mit 3,9 bzw. 31 kHz) und die Auswertung aller vier 
Flanken erledigt.

Allerdings weicht unser Gespräch schon deutlich vom eigentlichen Thema 
ab.

Antwort schreiben

Eine eigene Frage? Dieser Thread ist über 13 Jahre alt. Stell sie in einem eigenen Thread – dort lesen mehr Leute mit, und sie wird öfter und schneller beantwortet.

Neuen Thread starten

Eine Lösung, Ergänzung oder Rückmeldung zu diesem Thread? Dann antworte hier.

Formatierung
  • [c]C-Code[/c]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] – Link zu einem Artikel
  • Verweis auf einen anderen Beitrag: Rechtsklick auf dessen Beitrags-ID (#8078628), „Adresse kopieren“, in den Text einfügen

Mehr zur Formatierung

Längeren Sourcecode als Anhang, nicht in den Text. JPG nur für Fotos und Scans; Zeichnungen und Screenshots als PNG oder GIF. Siehe Bildformate.

Schon registriert? Anmelden

Wird nicht angezeigt. Wir schicken dir einen Link; sobald du damit bestätigst, erscheint dein Beitrag.

Mit dem Abschicken legst du einen kostenlosen Account an und erkennst die Nutzungsbedingungen und die Datenschutzerklärung an.