SPI zwischen zwei ATMEGA8A mit SPI-Interrupt

Gast #3842979
Lesenswert?

Hallo
Ich hab jetzt angefangen mich mit SPI Übertragung zu befassen, jedoch 
klappt es nicht. Für den Anfang wollte ich eine einfache Zahl senden.
Wenn ich das Buch bzw Datenblätter richtig verstanden habe, wird bei 
SS-low beim Slave (wenn SPI aktiviert ist) das Daten Byte automatisch 
ins Register geladen und anschließend (wenn SPIF 1 wird) ein Interrupt 
ausgeführt. Um Fest zustellen das dieser auch ausgeführt wird will ich 
zuerst einfach die Leds anders Leuchten lassen, jedoch wird dieser 
Interrupt nie ausgeführt und ich weis nicht wieso.
Mit den Oszi hab ich MOSI, PB1/SS sowie SCK gemessen und die Signale 
machen genau das was erwartet. (SS geht low für den Zeitraum der 
Übertragung, SCK Takted und MOSI sendet).
Ich weis nicht was ich noch Versuchen kann bzw. Wo mein Fehler liegt und 
ich hoffe das mir jemand von euch helfen kann?

Zum Aufbau, ich  Verwende Zwei ATMEGA8A, mit 8MHZ interner Oszillator 
getaktet, einer (der Slave) in STK500 der auf die Leds über PORTC 
angeschlossen ist. Der Master ist an einem Experimentier Board und mit 
kable verbunden. (ich habe einen skizzenhaften Schaltplan angehängt an 
den die SPI Verbindungen ausgezeichnet sind)

Besten Dank für die Hilfe
manhai

Slave
1
/*
2
 * SPI_comunicatin_test_master.c
3
 *
4
 * Created: 13.10.2014 12:55:19
5
 *  Author: manhai
6
 */ 
7

8

9
#include <avr/io.h>
10
#include <avr/delay.h>
11
#include <avr/interrupt.h>
12
#define F_CPU 8000000
13
volatile char zyklus;
14

15
//SPI Transfer Complete Interrupt starting on page 124 in datasheet
16
ISR(SPI_STC_vect){
17
    
18
  PORTC = 0xf0;
19
  zyklus = SPDR;
20
  
21
    
22
  }    
23
  
24

25
void init_spi_slave()
26
{
27
  SPCR |= ((1 << SPIE) | (1 << SPE) | (0 << DORD) | (0 << MSTR) | (1 << CPOL) | (1 << CPHA) | (0 << SPR1) | (0 << SPR0));
28
}
29

30

31
void init_Ports_slave()
32
{
33
  
34
  DDRB |= (1 << 4);
35
    
36
  DDRC = 0xFF;   //für die led ausgabe
37
  PORTC = 0x00;  //alle aus
38
  
39
}
40

41

42

43
int main(void)
44
{
45
    unsigned char ubertrag = 0;
46
  init_Ports_slave();
47
  sei();
48
  while(1)
49
    {
50

51
  }
52
}


Master
1
/*
2
 * SPI_comunicatin_test_master.c
3
 *
4
 * Created: 13.10.2014 12:55:19
5
 *  Author: manhai
6
 */ 
7

8

9
#include <avr/io.h>
10
#include <avr/delay.h>
11
#include <avr/interrupt.h>
12
#define F_CPU 8000000
13

14

15
void init_spi_master()
16
{
17
  SPCR |= ((0 << SPIE) | (0 << SPE) | (0 << DORD) | (1 << MSTR) | (1 << CPOL) | (1 << CPHA) | (1 << SPR1) | (1 << SPR0));  
18
}
19

20
void spi_master_aktiv()
21
{
22
  SPCR |= ((1 << SPE));  //aktiviert SPI
23
}
24

25
void init_Ports()
26
{
27
  DDRB = 0xFF; 
28
  DDRB &= ~(1 << PB4);
29
  
30
  PORTB = 0x00;
31
  PORTB |= ((1 << PB1));  //setzt select auf high
32
}
33

34
void senden8bit(unsigned char wert)
35
{
36
  PORTB &= ~(1 << PB1); 
37
  SPDR= wert;  //daten in Buffer schreiben
38
      //Wait until transmission complete
39
  while(!(SPSR & (1<<SPIF)));  
40
  wert = SPDR ; //Pseudolesen
41
  PORTB |= (1 << PB1);  //setzt select auf high
42

43
}
44

45

46

47
int main(void)
48
{
49
   
50
      init_Ports();
51
  init_spi_master();
52
  spi_master_aktiv();
53
  
54
  while(1)
55
    {
56
       
57
   senden8bit(52);
58
  _delay_ms(50);
59
  senden8bit(150);
60
  _delay_ms(50);
61

62
    }
63
}
Angehängte Dateien:
Gast #3843036
Lesenswert?

Slave Init:
1
void init_spi_slave(void)
2
{
3
  SPCR &= ~(1<<MSTR);           //Slave Modus wird aktiviert
4
  DDRB |= ((1<<4));          //MISO als Ausgang
5

6
  SPCR |= ((1<<CPOL)|(1<<CPHA));//SPI MODE 3
7

8
  SPCR &= ~(1<<DORD);           //MSB Bit first
9

10
  SPCR |= ((1<<SPE)|(1<<SPIE)); //Hier wird der SPI und und die SPI Interrupt Behandlung aktiviert
11
  sei();                        //Hier werden die Interrupts global aktiviert
12
}

Master Init:
1
void init_spi_master(void)
2
{
3
  SPCR |= (1<<MSTR);          //Master Modus wird aktiviert
4
  
5
  PORTB |= (1<<2);          //SS Pin aus high schalten um Gerät erstmal zu deselektieren
6
  DDRB |= ((1<<2)|(1<<3)|(1<<5));  //Schaltet alles als Ausgang
7

8
  //Deinen SlaveSelect Pin zusätzlich einstellen
9
  DDRB |= (1<<1);
10
  PORTB |= (1<<1);
11
    
12
  SPCR |= ((1<<CPOL)|(1<<CPHA));    //SPI Mode 3
13
  
14
  SPCR &= ~(1<<DORD);          //MSB first
15
  
16
  SPSR &= ~(1<<SPI2X);
17
  SPCR |= ((1<<SPR0)|(1<<SPR1));    //Teiler 128
18
  
19
  SPCR |= (1<<SPE);          //Hier wird der SPI aktiviert
20

21

22
}

Damit sollte es klappen!
Gast #3844028
Lesenswert?

spess53 schrieb:

> Nein. MOSI(Master) an MOSI(Slave) und MISO(Slave) an MISO(Master).

Nomen est omen.

*M*aster*O*ut*S*lave*I*n

vs.

*M*aster*I*n*S*lave*O*ut

Ganz klar, daß da mal wieder irgendwer das Datenblatt nicht gelesen hat. 
Und spess53 war nicht der, der das nicht getan hat...
Gast #3845425
Lesenswert?

Es hat leider nicht geklappt.
Mir ist aber aufgefallen das sobald SCK verbunden ist sofort alle Leds 
Leuchten (obwohl sie dies nicht tun sollten). Es macht hier keinen 
Unterschied ob SCK schon beim Einschalten des ICs verbunden ist oder 
nachträglich angeschlossen wird. Ich weis einfach nicht wieso er so 
etwas tut.

Anmerkung: Beide ICs liegen auf der gleichen Versorgungspannung sowie 
GND
#3845445
Lesenswert?

manhai schrieb:
> Mir ist aber aufgefallen das sobald SCK verbunden ist sofort alle Leds
> Leuchten (obwohl sie dies nicht tun sollten)

Wenn die aktive Low geschaltet sind: SCK auf dem Slave NICHT als Ausgang 
setzen, siehe DDRx Register. Die DDR Bits der SPI Pins müssen auf dem 
Slave genau umgekehrt zum Master gesetzt werden.

Hintergrund:
Low Out auf dem SCK des Masters erzeugt mit dem High Out des Slave einen 
Kutzschluss der Betriebsspannung, die auf dem Slave stark absinkt - bis 
die LEDs über die ESD Dioden anfangen zu leuchten.
Gast #3845914
Lesenswert?

Danke für die schnelle Antwort

So weit klingt alles logisch, jedoch sind die Pins (SCK, sowie SS, und 
MOSI) vom Slave bereits als Ausgang geschalltet(DDRB ist überall "0" 
außer auf pin 4 (MISO)) deshalb weis ich ja nicht wo der Fehler liegt.
(Firma: Vescomp) #3845920
Lesenswert?

manhai schrieb:
> So weit klingt alles logisch, jedoch sind die Pins (SCK, sowie SS, und
> MOSI) vom Slave bereits als Ausgang geschalltet(DDRB ist überall "0"
> außer auf pin 4 (MISO)) deshalb weis ich ja nicht wo der Fehler liegt.

 Umgekehrt.
 DDRB.x = 0  / Pin ist Eingang.
 DDRB.x = 1  / Pin ist Ausgang.

 Und auch falsch, sollte sein:
 Slave:
 MISO = Ausgang
 MOSI = Eingang
 SCK  = Eingang

 Master:
 MISO = Eingang
 MOSI = Ausgang
 SCK  = Ausgang

 Ist das so schwer ?
Gast #3846157
Lesenswert?

Marc Vesely schrieb:
> Umgekehrt.
>  DDRB.x = 0  / Pin ist Eingang.
>  DDRB.x = 1  / Pin ist Ausgang.
>
>  Und auch falsch, sollte sein:
>  Slave:
>  MISO = Ausgang
>  MOSI = Eingang
>  SCK  = Eingang
>
>  Master:
>  MISO = Eingang
>  MOSI = Ausgang
>  SCK  = Ausgang

Genau diese DDR Belegung habe ich. Ich habe es auch noch einmal 
zusätzlich Überprüft im ATMEL Studio 6 - Simulation, nur Verstehe ich 
nicht wieso diese Einstellung falsch ist. In einer Antwort vorher wurde 
mir diese genannt, ebenso steht sie im Datenblatt zu ATmega8, im Buch 
und auch in allen anderen Quellen die ich gefunden habe.


Stefan Ernst schrieb:
> Hilfreich wäre auch, wenn init_spi_slave auch mal aufgerufen werden
> würde.

Ich habe es selber gestern gesehen, und bereits korrigiert. (ist leider 
Passiert da ich das ganze schon min 4 mal neu geschrieben habe (mit 
Vorlage verschiedenster Seite/Bücher/Datenblätter) um den Fehler 
möglichst  alleine zu finden zu können bevor ich andere frage)

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren