Forum: Compiler & IDEs Atmega32 und ATtiny85 über "SPI" kommunizieren lassen


von Paul P. (cesupa)


Lesenswert?

Hallo,

zur Zeit probiere ich mich am USI des ATtiny aus. Ich möchte gerne einen 
Atmega32 und einen ATtiny85 über SPI miteinander kommunizieren lassen. 
Es sollen uint16 daten übertragen werden. Die Kommunikation an sich 
scheint schon zu funktionieren, jedoch "springen" die Werte ständig und 
der eigentliche Wert erscheint nur selten. Ich lasse den Atmega mit 
16MHz laufen und den ATtiny mit internen 8MHz. Der Attiny ist natürlich 
slave:
1
typedef union wu{
2
  uint16_t w;
3
  uint8_t b[2];
4
}word;
5
6
volatile word v;  //ADC-Value of the voltage
7
volatile uint8_t i=1;
8
uint8_t buf=0;
9
10
ISR(USI_START_vect)
11
{
12
  USIDR=v.b[(i++)%2];
13
  if(i>255)
14
    i=1;
15
}
16
17
ISR(USI_OVF_vect)
18
{
19
  USIDR=v.b[0];
20
  buf=USIDR;
21
  //while(!(USISR&(1<<USIOIF)));
22
23
  USIDR=v.b[1];
24
  buf=USIDR;
25
  //while(!(USISR&(1<<USIOIF)));
26
  USISR|=(1<<USIOIF);        //clear 4-bit counter  //|(1<<USISIF);    //clear start bit
27
}
28
29
int main()
30
{
31
//unsigned int res;
32
//uint8_t i=0;
33
34
/*init SPI*/
35
DDRB|=(1<<PB1);                //MISO -> output
36
DDRB&=~(1<<PB0)&~(1<<PB2);        //MOSI,SCK -> input
37
PORTB|=(1<<PB0)|(1<<PB2);        //MOSI,SCK -> pull ups on
38
v.w=4000;
39
sei();
40
while(1);
41
}

Atmega:
1
void initSPI()
2
{
3
  RF_PORT=(1<<CS);
4
  RF_DDR&=~((1<<SDO));
5
  RF_DDR|=(1<<SDI)|(1<<SCK)|(1<<CS);
6
  SPCR=(1<<SPE)|(1<<MSTR);
7
}
8
9
uint16_t transAttinySPI()
10
{
11
  word val;
12
  SPDR = '8';
13
  while(!(SPSR & (1<<SPIF)));
14
  val.b[1]=SPDR;
15
  //uart_putc(val.b[1]);
16
  SPDR = '4';
17
  while(!(SPSR & (1<<SPIF)));
18
  val.b[0]=SPDR;
19
20
21
  //uart_putc((char)val.b[1]);
22
  //      uart_putc((char)val.b[0]);
23
  return val.w;        //return answer
24
}

Der Master fragt in einer Endlosschleife jede Sekunde nach Daten und 
gibt diese am LCD aus. Dabei erscheinen immer wieder die Zahlen ~3642 
und ~7738. Benötige ich ein spezielles Protokoll mit Fehlererkennung 
oder so oder lässt sich das ganze einfacher und dennoch zuverlässig 
realisieren?

von holger (Gast)


Lesenswert?

>  USIDR=v.b[0];
>  buf=USIDR;
  //while(!(USISR&(1<<USIOIF)));

 > USIDR=v.b[1];
 > buf=USIDR;

Wie wärs mit warten bis die Übertragung beendet ist?

von Paul P. (cesupa)


Lesenswert?

mache ich das mit der auskommentierten Zeile

> //while(!(USISR&(1<<USIOIF)));

?

von Peter D. (peda)


Lesenswert?

Paul P. schrieb:
> Benötige ich ein spezielles Protokoll mit Fehlererkennung
> oder so

Ja.
Üblicher Weise braucht SPI noch ein /SS (slave-select). Damit sagt der 
Master, daß ein neues Byte beginnt. Ansonsten kann der Slave ja nicht 
wissen, welches Bit der Master gerade sendet.

Daher braucht SPI insgesamt 4 Leitungen und Dein ATtiny85 hat dann nicht 
mehr viel Pins übrig.


Peter

von Paul P. (cesupa)


Lesenswert?

Könnte ich den RESET-Pin als /SS verwenden? Ich habe sonst wirklich 
keinen Pin mehr frei. Oder ließe sich vielleicht durch Wartezeiten eine 
Abstimmung realisieren?

von Rico (Gast)


Lesenswert?

nimm doch Uart!

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.