Forum: Mikrocontroller und Digitale Elektronik ATmega328: INT0 geht nur, wenn zu Beginn HIGH


von Roman S. (kadege)


Lesenswert?

Hallo,
unten ein Programm, das eine Variable von einem SPI-Slave zu einem 
SPI-Master überträgt, beides ATmega328. Auf INT0 liegt ein mittels 
NAND-Gatter gebauter entprellter Schalter, der den Interrupt erfolgreich 
auslöst.
Mein Problem: Das Programm läuft nur, wenn beim Start (Anlegen der Vcc) 
der beiden Controller der Schalter auf HIGH liegt. Liegt er auf LOW, 
kann ich so viel schalten, wie ich will, nichts passiert.
Hat jemand eine Idee?

Vielen Dank im Voraus!
RS
1
/*
2
MASTER
3
INT0 (PD2) Interrupt (beide Flanken) löst die Anforderung einer SPI-Botschaft vom Slave aus
4
Die jeweils empfangene Zahl wird an LEDS (C1...C4) ausgegeben.
5
*/
6
7
#ifndef F_CPU
8
  #define F_CPU 16000000                          // Der IC ist mit 16 Mhz getaktet
9
#endif
10
#include <avr/io.h>          
11
#include <avr/interrupt.h> 
12
13
int volatile Anz_LEDs_an = 0;
14
int SS_Pin = PB2;
15
16
int main (void) 
17
  { 
18
  // LED-Port
19
  DDRC |= (1 << DDC1) | (1 << DDC2) | (1 << DDC3) | (1 << DDC4);  // C1...C4 auf "Ausgang", LEDs, Rest auf Eingang, wichtig für INT0 (PD2)
20
  DDRC |= (1 << PC5);                          // PC5 wird nicht gebraucht, kann als Debugpin benutzt werden
21
  PORTC |= (1 << PC5);                        // Init
22
  
23
  sei();                                // Global Interrupts aktivieren  
24
  EIMSK |= (1 << INT0);                        // Enable INT0
25
  EICRA |= (1 << ISC00);                        // Any logical change on INT0 generates an interrupt request.
26
  
27
  // SPI Init
28
  // Port B ist immer SPI-Port; PB3 = MOSI, PB5 = SCK, PB2 = SS
29
  DDRB = (1 << DDB3)|(1 << DDB5)|(1 << DDB2);            // Set MOSI, SS and SCK output, all others input
30
  SPCR = (1 << SPE) | (1 << MSTR) | (1 << SPR0);            // Enable SPI, Master, set clock rate fck/16 = 1 MHz, enable SPI Interrupt  
31
32
  PORTB |= (1 << SS_Pin);                        // SS auf HIGH, Slave wird nicht angesprochen
33
  while(1) 
34
     {
35
     }                      
36
  /* wird nie erreicht */
37
  return 0;   
38
  }              
39
  
40
#ifndef INT0_vect
41
#endif
42
43
ISR (INT0_vect)
44
  {
45
  PORTC ^= (1 << PC5);                        // Invertieren für Debuggen
46
  PORTB &= ~(1 << SS_Pin);                      // SS auf LOW, Slave ansprechen
47
  SPDR = 0x0F;                            // irgendwas schreiben, um Übertragung zu starten
48
  while(!(SPSR & (1 << SPIF)))                    // warten, bis Übertragung fertig
49
  ;
50
  Anz_LEDs_an = SPDR;                         // Übertragene Daten auslesen
51
  
52
  PORTC &= ~(1 << PC1);
53
  PORTC &= ~(1 << PC2);
54
  PORTC &= ~(1 << PC3);
55
  PORTC &= ~(1 << PC4);
56
  PORTC |= ((Anz_LEDs_an & 0x01)<< 1) | ((Anz_LEDs_an & 0x02)<< 1) | ((Anz_LEDs_an & 0x04)<< 1) | ((Anz_LEDs_an & 0x08)<< 1);
57
  
58
  PORTB |= (1 << SS_Pin);                        // SS auf HIGH, Slave wird nicht angesprochen
59
  }

von Karl H. (kbuchegg)


Lesenswert?

1
  sei();                                // Global Interrupts aktivieren  
2
  EIMSK |= (1 << INT0);                        // Enable INT0
3
  EICRA |= (1 << ISC00);                        // Any logical change on INT0 generates an interrupt request.

es ist keine so gute Idee, die Interrupts generell frei zu geben, noch 
ehe alles fertig konfiguriert ist.

Das sei() kommt ganz zum SChluss, wenn alles fertig eingestellt ist, 
unmittelbar vor der Hauptschleife in main().

Denn ansonsten kann es dir passieren, dass mit dem sei() schon die 
ersten Interrupts zu feuern beginnen. Was bei dir natürlich ganz 
besonders schlecht ist, wenn der µC gleich mal in die INT0-ISR geht, in 
der du über SPI etwas auszugeben versuchst, wobei das SPI zu diesem 
Zeitpunkt noch gar nicht konfiguriert ist.

Da kann dann deine Warteschleife auf das SPIF lange warten, ehe sich da 
mal was tut.

von Roman S. (kadege)


Lesenswert?

Hallo Karl-Heinz,

> Das sei() kommt ganz zum SChluss, wenn alles fertig eingestellt ist,
> unmittelbar vor der Hauptschleife in main().

Mit
1
  PORTB |= (1 << SS_Pin);                        // SS auf HIGH, Slave wird nicht angesprochen
2
  sei();

(Rest unverändert) geht es. Vielen Dank für die schnelle Antwort!

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.