Forum: Mikrocontroller und Digitale Elektronik Atmega328p ISR Maske ohne Funktion?


von Hendrik (Gast)


Lesenswert?

Hallo Forum,

ich wundere mich gerade über das Verhalten eines Atmega328p, bei dem ich 
Pin Change Interrupts verwenden will.
Wenn ich das Datenblatt richtig lese, kann jeder Pin in einer bestimmten 
Gruppe den zugehörigen Pin Change Interrupt auslösen. Dazu muss er aber 
über das passende PCMSK Register der ISR zugeordnet werden. Danach macht 
es keinen Unterschied, ob der Pin Input oder Output ist.
Ich möchte aber nun, dass nur meine Eingänge den entsprechenden 
Interrupt auslösen. Bislang scheint aber, trotz der Einstellung des 
Maskenregisters, jeder Pin der Gruppe zum Sprung in die ISR Funktion zu 
führen. Stellt sich mir also die Frage, ob ich das Masken Register 
korrekt anwende?
1
//Includes
2
#include <avr/io.h>
3
#include <avr/interrupt.h>
4
5
//Defines
6
#define ONTIME  10
7
8
//Global variables
9
volatile uint8_t duration = 0;
10
volatile uint8_t brightness = 0;
11
volatile uint8_t switchingthreshold = 0;
12
13
//Function declarations
14
void init_ports(void);
15
void init_timers(void);
16
void init_interrupts(void);
17
18
19
// function name: init_ports()
20
// Overall setup of I/O ports
21
// 
22
void init_ports(void){
23
  //Set pull-ups for inputs active = 1, disabled = 0 (default)
24
  PORTB |= 0b00000000;
25
  PORTC |= 0b00000000;
26
  PORTD |= 0b00000000;
27
28
  //Set direction output = 1, input = 0 (default)
29
  DDRB |= 0b11111011; 
30
  DDRC |= 0b11110000;
31
  DDRD |= 0b11110011;
32
}
33
34
35
36
// function name: init_timers()
37
// configuration of timers for PWM output
38
// and on time duration
39
void init_timers(void){
40
  //PWM for LEDs left and right side 
41
  OCR0A = 64;
42
  OCR0B = 128;
43
  TCCR0A |= (1<<COM0A1) | (1<<COM0B1) | (1<<WGM01) | (1<<WGM00); //Set Fast PWM non inverting, enable OC0A & OC0B
44
  TCCR0B |= (1<<CS02); //256x Prescaler = 240Hz PWM
45
46
  //PWM for LEDs front side
47
  OCR2A = 128;
48
  TCCR2A |= (1<<COM2A1) | (1<<WGM21) | (1<<WGM20); //Set Fast PWM non inverting, enable OC2A
49
  TCCR2B |= (1<<CS22) | (1<<CS21); //8x Prescaler = 240Hz PWM
50
}
51
52
53
54
// function name: init_interrupts()
55
// enables the internal interrupts for
56
// PIR Sensor input on Pin PD2, PD3, PB2 and PC3
57
void init_interrupts(void){
58
  //Set interrupts
59
  EICRA |= 0b00001111; //Rising edge of INT1 and INT0 to trigger
60
  EIMSK |= 0b00000011; //Enable Interrupts INT1 and INT0
61
  PCICR |= 0b00000011; //Enable Pin change interrupt group PCINT7...0 and 8...14
62
  PCMSK0 |= 0b00000100; //Mask out all interrupts beside PCINT2
63
  PCMSK1 |= 0b00001000; //Mask out all interrupts beside PCINT11
64
}
65
66
67
ISR(INT0_vect){
68
  PORTB ^= (1 << PB5); 
69
}
70
71
ISR(INT1_vect){
72
  PORTB ^= (1 << PB5);
73
}
74
75
ISR(PCINT0_vect){
76
  PORTB ^= (1 << PB5);
77
}
78
79
ISR(PCINT1_vect){
80
  PORTB ^= (1 << PB5);
81
}
82
83
84
85
int main(void)
86
{
87
cli();
88
init_ports();
89
init_timers();
90
init_interrupts();
91
sei();
92
    while (1) 
93
    {
94
    }
95
}

Beitrag #5629872 wurde vom Autor gelöscht.
von Felix P. (fixxl)


Lesenswert?

Wie sind denn deine Eingänge hardwaremäßig beschaltet? Ohne 
Pullup/Pulldown (die internen Pullups sind ja nicht aktiviert) 
detektiert der Controller je nach äußerem Einfluss fröhlich 
Flankenwechsel, von denen jeder die Interrupt-Routine triggert.

Das hier ist übrigens in der Init nicht sinnvoll:
1
  //Set pull-ups for inputs active = 1, disabled = 0 (default)
2
  PORTB |= 0b00000000;
3
  PORTC |= 0b00000000;
4
  PORTD |= 0b00000000;
Durch eine Oder-Verknüpfung kannst du kein Bit auf 0 bringen. Es ist 
nicht verwerflich, in der ersten Anweisung eine harte Zuweisung mit "=" 
zu machen.

: Bearbeitet durch User
von Veit D. (devil-elec)


Lesenswert?

Hallo,

ich kann keine Fehler im Code feststellen, kompiliert auch ohne Fehler. 
Mit was gehst du an die Eingänge? Taster? Dann wird vermutlich das 
prellen so schnell sein, dass du das umschalten gar nicht siehst. Nimm 
mal 2 Taster. Einer schaltet ein der andere aus. Oder ausnahmsweise zum 
testen ein delay in die Toggle ISR von 50ms. Das toggle musste natürlich 
umändern in ein oder aus.

von Hendrik (Gast)


Lesenswert?

Stimmt die Zuweisung war nicht geschickt. Ändert aber auch nichts, die 
Register stehen richtig. An den Port Pins sind PIR Sensoren 
angeschlossen, die machen saubere Signale ohne prellen. Per debugger 
sehe ich aber, dass die Routine trotz Maskierung aufgerufen wird, wenn 
ich einen der anderen Pins den Pegel wechseln lasse.

von S. Landolt (Gast)


Lesenswert?

Debugger?

von Stefan F. (Gast)


Lesenswert?

Gebe mal den aktuellen Wert der beiden Masken-Register auf einer 
seriellen Konsole aus oder kontrolliere sie mit einem Debugger.

von c-hater (Gast)


Lesenswert?

Hendrik schrieb:

> Per debugger
> sehe ich aber, dass die Routine trotz Maskierung aufgerufen wird, wenn
> ich einen der anderen Pins den Pegel wechseln lasse.

Debugger oder Simulator?

Wenn's ein echter Debugger ist (also auch echte Hardware) dürfte 
schlicht ein Schaltungsfehler vorliegen.

von Veit D. (devil-elec)


Lesenswert?

Hallo,

mal ne ganz doofe Frage. Taktet dein 328P überhaupt? F_CPU ist irgendwo 
gesetzt?

von Stefan F. (Gast)


Lesenswert?

Veit D. schrieb:
> mal ne ganz doofe Frage.

Allerdings, sehr doofe Frage.

> Taktet dein 328P überhaupt? F_CPU ist irgendwo gesetzt?

Der taktet auch ohne F_CPU. Ohne Takt könnte er nicht einmal sein 
Programm in den Flash Speicher übertragen.

von Veit D. (devil-elec)


Lesenswert?

Naja, ich glaube das erst wenn er bestätigt das sein PWM taktet wie es 
soll. Wenn dieses funktioniert dann funktionieren auch seine PCINTs. 
Anders gefragt, konnte er es denn übertragen? Er sagt es funktioniert 
nur im Debugger bzw. Simulator? Sonst nicht.

von Stefan F. (Gast)


Lesenswert?

Wenn der µC keinen Takt hätte, wie kann er dann (unerwartet oft) in die 
ISR springen?

von S. Landolt (Gast)


Lesenswert?

> Er sagt es funktioniert nur im Debugger bzw. Simulator ...

Er schrieb "debugger", und da wüsste ich eben gerne, wie dieser bei 
einem ATmega328P aussieht.

von Hendrik (Gast)


Lesenswert?

Debugger beim Atmega328p geht über so ziehmlich jedes übliche Atmel 
Tool. Stichwort Debug Wire.

F_CPU kann man auch als Symbol fürs Projekt festlegen. Die Quarzfrequenz 
ändert sich in der Regel ja nicht, außer man wechselt die Hardware. Im 
Quellcode mag es übersichtlicher sein. Ich bevorzuge diesen Weg.

Die PWM läuft ohne Probleme. Einzig in den Kommentaren steckt noch ein 
Fehler. Auch die zweite PWM läuft mit 244 Hz. Also mit Teiler 256.

Knackpunkt ist das Verhalten der Interrupt Eingänge. Mit dem Debugger 
kann ich sehen in welche ISR gesprungen wird. Nehmen wir zum Beispiel 
den Pin PC3. Dieser gehört zur PCINT1 Gruppe und sollte entsprechend 
maskiert sein. Allerdings springt das Programm auch in die PCINT1_vect 
routine wenn ich zum Beispiel PC0 auf Input setze und dann über einen 
10k Widerstand auf Vcc lege. Entsprechend wird auch die LED an PB5 
getoggelt.

Gleiches verhalten, wenn der Pin auf Ausgang steht. So gibt es das 
Datenblatt ja auch vor. Nur sollte der Pin eigenltich durch das Masken 
Register nicht beachtet werden. Von der sinnhaftigkeit einen auf Ground 
schaltenden Push-Pull Treiber über 10k nach Vcc ziehen zu wollen mal 
ganz abgesehen.

Vielleicht noch was zur Hardware. Ausgangsbasis ist ein Arudino Nano den 
ich über die SPI Schnittstelle Programmiere oder per Debug Wire eben 
debugge. An den Pins PD2, PD3, PB2 und PC3 sind PIR Sensoren 
angeschlossen. Die Arbeiten wie der Arduino mit 5V und schalten für 1 
Sekunde auf High, wenn Bewegung erkannt wird. An die Eingänge PC0 bis 
PC3 sollen Potis angeschlossen werden. An den 3 Pins die als PWM laufen, 
werden nacher LEDs angeschlossen, momentan sind sie offen. Genau wie die 
restlichen Pins die zu diesem Zwecke auf Ausgang und Low stehen. Das 
Problem fing halt an, als ich die zum Testen meiner ADC Funktionen 5V 
auf den dann als Eingang konfigurierten PC0 gegeben habe. Aber selbst 
als Ausgang wird die ISR ja trotz maskierung gerufen.

von S. Landolt (Gast)


Lesenswert?

Da fällt mir erstmal nichts weiter ein, außer zu wiederholen:

Stefanus F. schrieb:
> Gebe mal den aktuellen Wert der beiden Masken-Register auf einer
> seriellen Konsole aus oder kontrolliere sie mit einem Debugger.

von MWS (Gast)


Lesenswert?

Hendrik schrieb:
> Stellt sich mir also die Frage, ob ich das Masken Register
> korrekt anwende?

Mach' doch mal diese elenden Veroderungen weg, wer kommt den auf so eine 
Schnapsidee? Ein zuvor startender Bootlader beispielsweise kann Register 
vorbesetzen und die bleiben dann auch so. Eine erstmalige Konfiguration 
macht man grundsätzlich per direkte Zuweisung.

> Allerdings springt das Programm auch in die PCINT1_vect
> routine wenn ich zum Beispiel PC0 auf Input setze und dann über einen
> 10k Widerstand auf Vcc lege.

Selbstgestrickte Platine und vergessen eines der GND, VCC oder gar AVCC 
am ATMega328 anzuschließen?

Außerdem hilft Dir der Debugger nichts, wenn Du nicht auch mit dem Kopf 
debuggen kannst, d.h. Funktionalität des Codes zurückbauen, Code für 
einen PCINT und für einen ADC schreiben, Timer und Rest raus. Und dann 
die Funktionalität Schritt für Schritt erweitern.

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.