Forum: Mikrocontroller und Digitale Elektronik Problem mit SPI zwischen Atmega8 und Attiny2313


von fry (Gast)


Lesenswert?

Hallo,
ich bin noch ziemlich am Anfang was uC angeht und habe Probleme mit 
einer SPI Verbindung zwischen einem Atmega8(Master) und einem 
Attiny2313(Slave).

Eigentlich sollte der Master immer eine 0 oder 1 senden und eine LED am 
Slave ein- bzw. ausschalten, leider passiert nichts. Den Slave Select 
nutze ich noch nicht und auf das ACK soll in meinem Beispiel auch nicht 
reagiert werde.

Die Beispiele unten habe ich abgewandelt. Anregungen zum Code hatte ich 
mir hier geholt: 
http://maxembedded.com/2013/11/the-spi-of-the-avr/#Master_Slave

PS: Ich habe keine Fuses oder ähnliches verändert und verwende nur den 
internen Quarz.

Master:
1
#define F_CPU 1000000UL // 1 MHz
2
3
#define DDR_SPI  DDRB
4
#define PORT_SPI PORTB
5
#define DD_MOSI  DDB3
6
#define DD_MISO  DDB4
7
#define DD_SCK   DDB5
8
#define DD_SS    DDB0
9
#define LED      DDD5
10
11
#include <avr/io.h>
12
#include <util/delay.h>
13
#include <avr/interrupt.h>
14
15
#define ACK 0x7E
16
17
//Initialize SPI Master Device
18
void spi_init_master (void)
19
{
20
  
21
  DDR_SPI = (1<<DD_SCK)|(1<<DD_MOSI); //Set MOSI, SCK as Output
22
  PORT_SPI = (1<<DD_MISO); // Set pull ups
23
  SPCR = (1<<SPE)|(1<<MSTR)|(1<<SPR0); //Enable SPI, Set as Master
24
}
25
26
//Function to send and receive data
27
unsigned char spi_tranceiver (unsigned char data)
28
{
29
  SPDR = data; //Load data into the buffer
30
  while(!(SPSR & (1<<SPIF) )); //Wait until transmission complete
31
  return(SPDR); //Return received data
32
}
33
34
35
int main(void)
36
{
37
  spi_init_master(); //Initialize SPI Master
38
  DDRD |= 0x01; //PD0 as Output
39
  
40
  unsigned char data; //Received data stored here
41
  
42
  while(1)
43
  {
44
    data = 0x00; //Reset ACK in "data"
45
    data = spi_tranceiver('0'); //Send "0", receive ACK
46
    _delay_ms(500);
47
    data = 0x00;
48
    data = spi_tranceiver('1'); //Send "1", receive ACK
49
    _delay_ms(500);
50
  }
51
}

Slave:
1
#define F_CPU 1000000UL // 1 MHz
2
3
#include <avr/io.h>
4
#include <avr/interrupt.h>
5
#include <util/delay.h>
6
7
#define DDR_SPI  DDRB
8
#define PORT_SPI PORTB
9
#define DD_MOSI  DDB5  //DI
10
#define DD_MISO  DDB6  //DO
11
#define DD_SCK   DDB7
12
#define DD_SS    DDB4
13
#define LED      DDD5
14
15
#define ACK 0x7E
16
17
void spi_init_slave (void)
18
{
19
  DDR_SPI |= (1<<DD_MISO); // MISO output
20
  DDR_SPI &= ~(1<<DD_SCK)|~(1<<DD_MOSI); // SCK and MOSI input
21
  PORT_SPI = (1<<DD_SCK)|(1<<DD_MOSI); // Set pull ups
22
  USICR = (1<<USIWM0)|(1<<USICS1); // Enable USI as SPI Slave
23
}
24
25
unsigned char spi_tranceiver (unsigned char data)
26
{
27
  USIDR = data;
28
  while(!(USISR&(1<<USIOIF)));
29
  return(USIDR);
30
}
31
32
int main(void)
33
{
34
   DDRD = (1<<LED);
35
  spi_init_slave(); //Initialize slave SPI
36
  unsigned char data;
37
  
38
  while(1)
39
  {
40
    data = spi_tranceiver(ACK); //Receive data, send ACK
41
    if (data == '0')
42
    {
43
      //set port PD5 HIGH
44
      PORTD &= ~(1<<LED);
45
      _delay_ms(100);
46
    }
47
    if (data == '1')
48
    {
49
      //set port PD5 LOW
50
      PORTD |= (1<<LED);
51
      _delay_ms(100);
52
    }
53
    _delay_ms(20);
54
  }
55
}


Danke!

von Karl M. (Gast)


Lesenswert?

Hi,

zum Ausdruck "internen Quarz", den gibt es leider nicht.

Hast Du mal deine Codes mit Hilfe der beide Datenblätte abgegelichen ?

von fry (Gast)


Lesenswert?

Ah, internen Oszillator...dachte das wäre auch ein Quarz. Laut 
Datenblatt stimmen die Zuweisungen von den Atmega8 und Attiny2313.

von c-hater (Gast)


Lesenswert?

fry schrieb:

> Den Slave Select
> nutze ich noch nicht

Das ist überhaupt keine gute Idee. Der SS-Mechanismus ist nämlich das 
einzige, womit bei SPI eine Wortsynchronisation herbeigeführt werden 
kann.

Übrigens ist das ziemlich wahrscheinlich auch genau der Grund, warum 
dein USI-Receiver nicht funktioniert, es fehlt die (im Original 
vermutlich als Reaktion auf SS ausgeführte) Initialisierung des 
USI-Zählers.

von neuer PIC Freund (Gast)


Lesenswert?

USI als SPI-Slave ist ohne HW-SS ziemlich dumpf.

Sezier mal die AVR319.zip

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

fry schrieb:
> Den Slave Select nutze ich noch nicht
Der gehört aber so zwingend zum SPI wie eine Gangschaltung zum Auto: es 
geht zwar ohne auch, aber nur ganz, ganz schlecht.

Denn der SS ist derjenige, der sagt, wann ein Paket komplett 
übertragen ist (ähnlich wie das Start- und Stopbit beim RS232). Wenn du 
ohne SS arbeitest, dann reicht 1 einziger EMV-Impuls aus und du wirst ab 
diesem Zeitpunkt immer um 1 Bit versetzt sein...

von Peter D. (peda)


Lesenswert?

Lothar M. schrieb:
> dann reicht 1 einziger EMV-Impuls aus und du wirst ab
> diesem Zeitpunkt immer um 1 Bit versetzt sein...

Es reicht schon, wenn der Master einen Tick eher aus dem Reset rauskommt 
und los sendet.
Du wirst keinen Programmierer bei Verstand finden, der /SS nicht 
benutzt.

Generell macht Slave-SPI beim AVR keinen Spaß, da sehr zeitkritisch.
Ein ACK gibt es nicht bei SPI, sondern bei I2C.

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.