Forum: Mikrocontroller und Digitale Elektronik SPI zwischen zwei ATMEGA8A mit SPI-Interrupt


von manhai (Gast)


Angehängte Dateien:

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
}

von M. S. (elpaco)


Lesenswert?

Ich glaube, dass du die Ein/Ausgänge nicht richtig setzt.

Beim Slave sollte MISO = Ausgang, MOSI = Eingang, SCLK = Eingang sein, 
beim Master MISO = Eingang, MOSI = Ausgang, SCLK = Ausgang.

Du setzt nur PB4 / MISO.

von Martin (Gast)


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!

von Martin (Gast)


Lesenswert?

Solange die beiden ICs eine gemeinsame Masse haben, ist deine Skizze mit 
der SPI Verbindung auch richtig.

von Joachim (Gast)


Lesenswert?

Echt?

Müssen MISO/MOSI nicht auch gekreuzt werden?

von spess53 (Gast)


Lesenswert?

Hi

>Müssen MISO/MOSI nicht auch gekreuzt werden?

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

MfG Spess

von c-hater (Gast)


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...

von manhai (Gast)


Lesenswert?

Danke für die Antwort
Ich werde es morgen sofort Probieren und sag dann bescheid ob es 
geklappt hat

mfg
manhai

von manhai (Gast)


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

von Jim M. (turboj)


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.

: Bearbeitet durch User
von manhai (Gast)


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.

von Marc V. (Firma: Vescomp) (logarithmus)


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 ?

: Bearbeitet durch User
von Stefan E. (sternst)


Lesenswert?

Hilfreich wäre auch, wenn init_spi_slave auch mal aufgerufen werden 
würde.

von manhai (Gast)


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)

von manhai (Gast)


Lesenswert?

ich habe heute  den Fehler gefunden
ich habe statt ISR(SPI__STC_vect), ISR(SPI_STC_vect) geschriebne gehabt, 
nachdem ich das geändert habe, hat alles ohne Probleme geklappt.


mfg
manhai

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.