Forum: Mikrocontroller und Digitale Elektronik SPI - Attiny25 Master --> Atmega8 Slave


von Cetin A. (exaware)


Lesenswert?

Hallo zusammen,

ich habe folgendes Problem. Habe auf dem Attiny25 per USI einen SPI 
Master realisiert. Dieser schickt jede Sekunde ein Byte an einen Atmega8 
der als SPI Slave eingerichtet ist. Nun kann ich am SCK des Attiny25 
einen takt messen, aber auf dem Atmega8 wird der SPI Interrupt Flag 
(SPIF) nicht gesetzt, das heißt mein Atmega8 springt nie in die 
Empfangsroutine.
Sieht jemand einen fehler in meinem Code?

SPI-Slave auf Atmega8
1
#define F_CPU 8000000UL    // 8 MHz Takt
2
#include <avr/io.h>
3
#include <util/delay.h>
4
#include "lcd.c"
5
#include <stdlib.h>
6
7
#define DDR_SPI DDRB
8
#define DD_MOSI DDB3
9
#define DD_MISO DDB4
10
#define DD_SCK DDB5
11
#define DD_SS DDB2
12
13
void SPI_SlaveInit(void);
14
uint8_t SPI_SlaveTransmit(void);
15
16
int main(void)
17
{
18
  uint16_t keycode=0;
19
  uint8_t daten=0;
20
  char keycode_string[4];
21
22
  lcd_init();
23
  SPI_SlaveInit();
24
  while(1)
25
  {
26
    if((SPSR & (1<<SPIF)))
27
    {
28
      daten = SPI_SlaveTransmit();
29
      keycode = daten;
30
      lcd_init();
31
      itoa(keycode,keycode_string,10);
32
      lcd_pos(0,0);
33
      lcd_text((u8*)"Keycode: ");
34
      lcd_pos(0,9);
35
      lcd_text((u8*)keycode_string);
36
    }
37
  }
38
}
39
40
void SPI_SlaveInit(void)
41
{
42
  /* Set MISO output, all others input */
43
  DDR_SPI = (1<<DD_MISO);
44
  /* Enable SPI */
45
  SPCR = (1<<SPE);
46
}
47
48
uint8_t SPI_SlaveTransmit(void)
49
{  
50
  /* Wait for reception complete */
51
  while(!(SPSR & (1<<SPIF)));
52
  /* Return data register */
53
  return SPDR; 
54
}



SPI-Master auf Attiny25
1
#define F_CPU 2000000UL    // 2 MHz Takt
2
#include <util/delay.h>
3
#include <avr/io.h>
4
#include <stdint.h>
5
6
void SPI_MasterTransmit(void);
7
8
int main(void)
9
{
10
  // DO und USCK als Ausgänge initialisieren
11
  DDRB = (1<<DDB1)|(1<<DDB2);
12
  while(1)
13
  {
14
    SPI_MasterTransmit();
15
    _delay_ms(1000);
16
  }
17
}
18
19
void SPI_MasterTransmit(void)
20
{
21
  USIDR=120;
22
  USISR = (1<<USIOIF);           
23
  do
24
  {
25
                USICR = (1<<USIWM0)|(1<<USICS1)|(1<<USICLK)|(1<<USITC);  
26
  }
27
  while(!(USISR & (1<<USIOIF)));
28
}

von Markus C. (ljmarkus)


Lesenswert?

sei();
vergessen.

von max power (Gast)


Lesenswert?

datenblatt SS Pin Functionality.

von Peter D. (peda)


Lesenswert?

Der Master muß während der Übertragung den /SS Pin des Slave auf low 
setzen, damit der Slave weiß, wann ein Byte anfängt.

SPI mit nem 8-Pinner ist nicht so dolle, da bleiben nur noch 2 IOs 
übrig.


Peter

von Cetin A. (exaware)


Lesenswert?

> sei();
> vergessen.
sei() ändert leider nichts. Funktioniert immer noch nicht.

> datenblatt SS Pin Functionality.

> Der Master muß während der Übertragung den /SS Pin des Slave auf low
> setzen, damit der Slave weiß, wann ein Byte anfängt.
soviel ich weiß, hat der Attiny25 kein SS-Pin. Zudem sind bei mir die 
zwei
Schaltungen lediglich über fünf Leitungen miteinanden verbunden:
MOSI,MISO,SCK,GND,PWR --> also kein SS

das müsste doch auch funktioniern wenn beim Master der SS-Pin dauerhaft 
auf LOW liegt, oder?
Ich hatte vorher das ganze andersrum gehabt, also Attiny25=Slave und 
Atmega8=Master. In dieser konstellation hat alles funktioniert, also 
muss es doch andersrum auch gehen.

> SPI mit nem 8-Pinner ist nicht so dolle, da bleiben nur noch 2 IOs
> übrig.
ich benötige nur ein IO-Pin

von max power (Gast)


Lesenswert?

>das müsste doch auch funktioniern wenn beim Master der SS-Pin dauerhaft
>auf LOW liegt, oder?
beim slave muss ss auf low liegen.

von Cetin A. (exaware)


Lesenswert?

> beim slave muss ss auf low liegen.
sorry, mein Fehler. So war das natürlich gemeint. Aber der Attiny25 hat
doch kein SS-Pin.

von Peter D. (peda)


Lesenswert?

Cetin A. schrieb:
> das müsste doch auch funktioniern wenn beim Master der SS-Pin dauerhaft
> auf LOW liegt, oder?

Dann braucht man ne andere Synchronisation.
Z.B. wenn ne größere Pause ist, resettet der Slave sein SPI.

Man kann auch den Slave später einschalten (großes Delay nach Reset), 
nachdem der Master sein SPI schon initialisiert hat.
Ist der Slave aber vor dem Master enabled, kann er sich auf der 
floatenden SCK-Leitung Störpulse einfangen und ist dann für immer 
asynchron.

Die sauberste Lösung ist aber, der Master steuert auch die /SS-Leitung 
des Slave.


Peter

von Cetin A. (exaware)


Lesenswert?

> Dann braucht man ne andere Synchronisation.
> Z.B. wenn ne größere Pause ist, resettet der Slave sein SPI.
wie soll die Pause erkannt werden?

> Die sauberste Lösung ist aber, der Master steuert auch die /SS-Leitung
> des Slave.
Denke ich auch, aber meine Schaltung ist schon verbaut. Leider muß ich 
den
unsauberen Weg gehen.

von Cetin A. (exaware)


Lesenswert?

Ich habe hier noch ein Problem bemerkt, der SS-Pin am Slave (Atmega8) 
liegt ja auf PB2. Aber PB2 wird bereits von der LCD-Routine für die 
RS-Leitung benutzt. Kann ich das ganze nicht ohne SS programmieren?

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


Lesenswert?

> Kann ich das ganze nicht ohne SS programmieren?
Nimm eine RS232 Schnittstelle. Die ist per Definition asynchron und 
braucht nur 2 Leitungen zwischen den Controllern.

von Cetin A. (exaware)


Lesenswert?

> Nimm eine RS232 Schnittstelle. Die ist per Definition asynchron und
> braucht nur 2 Leitungen zwischen den Controllern.
Mein Fehler, ich hätte es am Anfang genauer erzählen sollen. Meine zwei
Schaltungen haben beide eine ISP-Programmierbuchse. Da ich keine 
möglichkeit habe zusätzlich Leitungen anzuschließen, habe ich die zwei 
Schaltungen über die Buchsen 1:1 verbunden. Deshalb wollte ich das ganze 
mit SPI realisieren, da diese auf der Buchse liegen. I²C und USART 
liegen beim Atmega8 auf anderen Pins.

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.