ATmega328: INT0 geht nur, wenn zu Beginn HIGH

OP #3408557
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
  }
#3408682
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.
OP #3408764
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!

Antwort schreiben

Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt. Bitte hier nur auf die ursprüngliche Frage antworten, für neue Fragen einen neuen Beitrag erstellen.

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.