Forum: Compiler & IDEs PCINT triggert nicht immer


von Wastl F. (rescuetigerchen)


Lesenswert?

Moin Gemeinde,

ich habe mit meinem Atmega1284P das Phänomen, daß der PCINT0 nicht 
richtig funktioniert.
Ich benutze PA4 und PA5 zum einlesen von Tasten, an den Pins kommt auch 
ein sauber entprelltes Signal an.
In einer Dauerschleife frage ich Änderungen an den Tastern ab, und gebe 
sie auf einem Display aus. Hab es auch schon ohne Display nur mit 
Pin-Toggeln versucht, um Einflüsse anderer Routinen auszuschliessen.
Ich habe einen UART am Laufen, zwei PWM Timer initialisiert, und einen 
Timer der jede ms auslöst.
Parallel zu der Tastenabfrage läuft aber nichts anderes.
Ich poste erst mal nur einen Teilcode, je nach Entwicklung des Threads 
dann noch mehr.
Vielleicht gibt es ja etwas was euch sonst noch einfällt, warum der 
PCINT ab und an oder manchmal gar nicht reagiert.

Gruß
wastlb
1
//init ext. int
2
PCICR |= (1<<PCIE0);
3
PCMSK0 |= (1<<PCINT4)|(1<<PCINT5);
4
5
//ISR PCINT
6
ISR(PCINT0_vect){    
7
  prog++;
8
}
9
10
//INT abfrage
11
do{
12
  lcd_goto(1,10);
13
  itoa(prog,num,10);
14
  lcd_write(num);
15
}while(1);

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

Wastl F. schrieb:
> Ich poste erst mal nur einen Teilcode, je nach Entwicklung des Threads
> dann noch mehr.

Das ist schon mal suboptimal, denn jetzt kommen die ganzen Vermutungen, 
die man bei vollständigem Code erst gar nicht stellen müsste.

Kandidat Nr. 1:

prog ist nicht volatile.

von Wastl F. (rescuetigerchen)


Lesenswert?

muss volatile sein, sonst würde der PCINT gar nicht anspringen, was er 
aber tut.

von Peter D. (peda)


Lesenswert?

Wastl F. schrieb:
> Ich benutze PA4 und PA5 zum einlesen von Tasten, an den Pins kommt auch
> ein sauber entprelltes Signal an.

Das müssen dann aber ganz besondere, teure Tasten sein.

Wastl F. schrieb:
> itoa(prog,num,10);
>   lcd_write(num);

itoa gibt immer die minimal nötige Länge aus.
Für eine bündige Ausgabe muß man links noch mit Leerzeichen auffüllen.


Peter

von Wastl F. (rescuetigerchen)


Lesenswert?

danke peter für den hinweis mit den leerzeichen.
die tasten sind nicht teuer, die entprellung ist per RC tiefpaß. mit 10k 
und 100n.
wenn die tasten prellen würden, wäre es mir in diesem moment aber 
wurscht. mein problem ist ja, daß die ISR nicht immer will. es scheint, 
als ob der µC von irgendwas blockiert wird. hat aber nichts ausser der 
do-while Schleife zu tun (naja, und die timer ISR für den ms-Takt).
meine komplette initialisierung:
1
volatile static double ms;
2
volatile int start=0, prog,progold;
3
4
int pv1=0,pv2=0,valve;
5
char num[6],buffer[6];
6
7
//init ports
8
DDRA  &= ~(1<<PA4)|(1<<PA5);
9
10
DDRD  |= (1<<PD5);
11
12
DDRB  |= (1<<PB0)|(1<<PB2)|(1<<PB3)|(1<<PB4);
13
PORTB |= (1<<PB2)|(1<<PB4);
14
15
//timer2 for timing
16
TCCR2A |= (1<<WGM21);      //CTC mode
17
TCCR2B |= (1<<CS20)|(1<<CS21);
18
TIMSK2 |= (1<<OCIE2A);
19
OCR2A = 250;      //every ms (default 15)
20
21
//timer0 for PWM PV1
22
TCCR0A |= (1<<COM0A1)|(1<<WGM00);
23
TCCR0B |= (1<<CS00);
24
OCR0A = 0;
25
26
//timer1 for PWM PV2
27
TCCR1A |= (1<<COM1A1)|(1<<WGM10);
28
TCCR1B |= (1<<CS10);
29
OCR1A = 0;
30
31
//init uart
32
UCSR0A |= (1<<U2X0);
33
UCSR0B |= (1<<TXEN0)|(1<<RXEN0);
34
UCSR0C |= (1<<UCSZ00)|(1<<UCSZ01);
35
UBRR0 = 25;  
36
37
//ext. int
38
PCICR |= (1<<PCIE0);
39
PCMSK0 |= (1<<PCINT4)|(1<<PCINT5);
40
41
MCUCR = (1<<JTD); 
42
MCUCR = (1<<JTD);

und dann noch die schleife in der ISR wie sie aussehen soll:
1
ISR(PCINT0_vect){
2
    if(PINA & (1<<PINA4)){
3
      PORTB ^= (1<<PB1);
4
      if(prog<9)
5
        prog++;
6
      else if(prog>8)
7
        prog=1;
8
        }
9
    else if(PINA & (1<<PINA5)){
10
      if(start==0)
11
        start=1;
12
      else if(start==1)
13
        start=0;}
14
}

gruß,
wastlB

von Karl H. (kbuchegg)


Lesenswert?

Wastl F. schrieb:

> als ob der µC von irgendwas blockiert wird. hat aber nichts ausser der
> do-while Schleife zu tun (naja, und die timer ISR für den ms-Takt).

Dann kanns ja wohl auch kein Problem sein, endlich mal kompletten 
vollständigen kompilierbaren Code zu zeigen, der das beschriebene 
Fehlverhalten zeigt.

Und wenn du uns (und dir selber) einen Gefallen tun willst, dann speckst 
du den Code erst mal so ab, dass tatsächlich nur noch das für das 
Problem relevante übrig bleibt (und nur das!).
Kein Timer, keine UART, keine anderen Interrupts.

Vor dem posten aber testen, ob sich der Fehler immer noch zeigt. Es ist 
nicht ungewöhnlich, dass dein Fehler ganz woanders sitzt und der so 
bereinigte Code einwandfrei arbeitet. (Und genau aus dem Grund, sind wir 
immer unglücklich, wenn bei seltsamen Fehlern nur COdeausschnitte 
gezeigt werden. Der Fehler sitzt oft ganz woanders. Wäre der Fehler im 
Codeausschnitt hättest du ihn selber auch gesehen)

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

Wastl F. schrieb:
>       if(prog<9)
>         prog++;
>       else if(prog>8)
>         prog=1;

Das zweite if ist hyperfluid. Hier reicht ein:

       if(prog<9)
         prog++;
       else
         prog=1;

Mehr kann man aus Deinen Codeschnippseln nicht herauslesen. Ich habe 
jetzt auch keinen Bock, Glaskugeln etc. noch mehr zu beanspruchen.

von Wastl F. (rescuetigerchen)


Lesenswert?

So. Hab alles zusammengestrichen, nur der PCINT und die Initialisierung 
an.
PCINT klappt beim ersten Tastendruck, danach ist sporadisch mal ein 
toggeln an PB1 zu sehen. Selbst mit einem angelegten Rechteck mit ~100Hz 
gibt es wenig Reaktion. Tasten sind so angeschlossen: 
5V-Widerstand-Taste-Port Controller.
Oder liegt hier der Hund begraben? Sollte ich lieber Richtung Masse 
schalten? Ich denke, ich habe das Problem. Ich werde das gleich mal 
testen.
Vorher aber noch der Code:
1
#include <stdio.h>
2
#include <avr\io.h>
3
#include <avr\interrupt.h>
4
5
int main(){
6
DDRA  &= ~(1<<PA4)|(1<<PA5);
7
DDRB  |= (1<<PB1);
8
9
//ext. int
10
PCICR |= (1<<PCIE0);
11
PCMSK0 |= (1<<PCINT4)|(1<<PCINT5);
12
    
13
sei();
14
15
do{}while(1);
16
17
return 0;
18
}
19
20
ISR(PCINT0_vect){
21
 PORTB ^= (1<<PB1);
22
}

von Karl H. (kbuchegg)


Lesenswert?

Wastl F. schrieb:
> So. Hab alles zusammengestrichen, nur der PCINT und die Initialisierung
> an.
> PCINT klappt beim ersten Tastendruck, danach ist sporadisch mal ein
> toggeln an PB1 zu sehen. Selbst mit einem angelegten Rechteck mit ~100Hz
> gibt es wenig Reaktion. Tasten sind so angeschlossen:
> 5V-Widerstand-Taste-Port Controller.
> Oder liegt hier der Hund begraben? Sollte ich lieber Richtung Masse
> schalten? Ich denke, ich habe das Problem. Ich werde das gleich mal
> testen.

Solltest du.
UNd einen Pullup am Portpin aktivieren.

Man lässt eine Eingangsleitung NIEMALS einfach offen!

von Karl H. (kbuchegg)


Lesenswert?

> PCMSK0 |= (1<<PCINT4)|(1<<PCINT5);

Wo sind die ISR dafür?

freigegebene Interrupts ohne ISR werden bei Auslösen des Interrupts mit 
einem Reset bestraft.

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

Wastl F. schrieb:
> gibt es wenig Reaktion. Tasten sind so angeschlossen:
> 5V-Widerstand-Taste-Port Controller.

Das geht nicht. Du musst jederzeit einen definierten Pegel an den 
µC-Eingang legen. Und zwar einen jeweils verschiedenen für den Zustand 
"Taster ein" und "Taster aus".

> Oder liegt hier der Hund begraben? Sollte ich lieber Richtung Masse
> schalten?

Ja. Wenn der Taster jedoch offen ist, dann sollte ein Pullup den Pin 
hochziehen. Das kann z.B. der interne Pullup des µCs sein.

von Wastl F. (rescuetigerchen)


Angehängte Dateien:

Lesenswert?

>Wo sind die ISR dafür?
Die sind doch mit ISR der PCINT0 abgefrühstückt? IM DB sind PortA 0-7 in 
dem Register eingetragen. In der Interrupt Tabelle sind ausser INT0-2 
keine anderen aufgeführt, und INT0-2 sind ja andere Interrupt-Arten.
Schwingt in meinem System etwas?
Nach dem "Rechtecksignalversuch" bekomme ich wiederholbar nach einem 
Tastendruck (auch nach Reset) ein langes (ca. 2 sec) HI an PB1. Daß der 
solange HI bleibt wie ich gedrückt halte ist klar. Aber: ich hätte ein 
gepulstes Signal erwartet, da ja die PCINT ISR dauerhaft an bleibt, der 
PIN aber getoggelt werden müsste...
Ich poste mal den Schaltplan, möglich ist ein Hardwarefehler ja auch 
noch...

von Wastl F. (rescuetigerchen)


Lesenswert?

>Das geht nicht. Du musst jederzeit einen definierten Pegel an den
>µC-Eingang legen. Und zwar einen jeweils verschiedenen für den Zustand
>"Taster ein" und "Taster aus".

Dann hilft aber doch bei meiner jetzigen Schaltung einfach ein Pulldown 
Widerstand an den Taster zu hängen? So ist bei Nichtdrücken Masse und 
bei Tastendruck 5V am Portpin.

edit: ich korrigier das gleich selber. damit baue ich mir einen super 
spannungsteiler, und die ISR bleibt still.

von Karl H. (kbuchegg)


Lesenswert?

Wastl F. schrieb:
>>Wo sind die ISR dafür?
> Die sind doch mit ISR der PCINT0 abgefrühstückt? IM DB sind PortA 0-7 in
> dem Register eingetragen.

Du hast recht.
Mein Fehler. Da hab ich nicht aufgepasst.

von Wastl F. (rescuetigerchen)


Lesenswert?

Ok. Ich habe jetzt die Tasten über einen Pulldown richtung 5V 
angeschlossen.
Reaktion wie vorher, PB1 geht für etwa 2sec HI, dann wieder LO.
Schließe ich ein Rechteck an, passiert gar nichts. Dachte ich. Man muss 
natürlich auch eine Amplitude einstellen. Jetzt flackert PB1 fröhlich 
vor sich hin, heisst, der ISR tut.
Also: Hardwareproblem. Wie dämlich kann man sich mit Tasten anstellen?
Selbst wenn sie prellen, müsste PB1 doch toggeln. Kein Taster prellt 2 
sec lang. Sooo billig waren die auch nicht.

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

Wastl F. schrieb:
> Also: Hardwareproblem. Wie dämlich kann man sich mit Tasten anstellen?

So wäre es optimal:

            ---
GND    -----   -------- µC
          Taster

Dann noch den internen Pullup einsschalten und Du hast die folgenden 
definierten Pegel:

  Taster gedrückt: LOW
  Taster offen:    HIGH

Dann entprellst Du noch die Tasten über Peters Software (Timer, nicht 
PCINT!) und die Kirsche ist gegessen.

von Wastl F. (rescuetigerchen)


Lesenswert?

Problem gelöst.
Hardware: niemals einen PIN "offen" lassen. Klar, wenn die offene Seite 
des Tasters am Port hängt, dann ist der ja floating. Also Pulldown oder 
Pullup, je nach Eingangsspannung und fertig.
Gruß,
wastlB

von Uwe (Gast)


Lesenswert?

Jup und wenn du nach den Tatser an Masse hängst, kannst du dir den 
externen Pullup sparen und den im µC eingebauten benutzen.

von Bronco (Gast)


Lesenswert?

BTW:
Ich hatte mal ein Projekt von einem Kollegen übernommen, der hatte auch 
einen offenen Pin, der einen Interrupt erzeugt hat.
Das Timing-Verhalten war absolut unberechenbar, weil der Pin gerne 
geschwungen hat und dann der ISR die CPU komplett ausgebremst hat. Wenn 
gutes Wetter war, war er mal stabil, und dann schien alles okay. Muß man 
erstmal draufkommen...

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
Noch kein Account? Hier anmelden.