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
intmain(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
//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
Reinhard P. schrieb:> PINA = 0x03;
Was willst Du hiermit bezwecken?
Ich weiß aus dem Kopf nicht, ob der 2313A diesen Befehl richtig
auswertet, wenn Du aber PORTA = 0x03 schreiben wolltest, solltest Du das
auch so machen.
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
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
}
Hi
>Ich verwende z.B. einen Drehencoder am Port A des 2313A.>Encoderleitung A hängt an PA0 und Leitung B an PA1
Dazu nimmt man keinen Pin-Change-Interrupt:
http://www.mikrocontroller.net/articles/Drehgeber
MfG Spess
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.
Peter Dannegger schrieb:> Und erstmal die fehlenden Defines direkt einfügen, also mit dem> originalen *.h compiliert.
... und insbesondere welche Adresse für PCMSK1 verwendet wurde.
0x04 oder 0x24?
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?
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
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).
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.
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.