SPI-Datenübertragung Problem /SS-Leitung

OP #965662
Lesenswert?

Hallo,
habe eine SPI-Master-Slave Schnittstelle zwischen zwei AVR aufgebaut.

Die Daten für den Master (ATMega8) kommen von der RS232 und sollen an 
den Slave (ATMega32) versendet werden. Damit der Master weiß, wann die 
Ausführung am Slave abgeschlossen ist und ein datenbyte zurückgelesen 
werden kann, habe ich eine zusätzliche /ACK-Leitung eingebaut. Diese ist 
für 50us LOW und wechselt dann wieder auf HIGH. Anschließend schreibt 
der Master eine 0x00 an den Slave um die Antwortdaten über MISO zu 
empfangen.

Nun mein Problem: Der Master erkennt nicht wann er die 8Bit übertragen 
hat und nimmt dann zu früh das /SS zurück.
1
#define F_CPU 16000000L                    //CPU-Frequenz
2
#define BAUD 9600L                      //Baudrate
3
#define UBRR_VAL ((F_CPU+BAUD*8)/(BAUD*16)-1)        //Runden für Prescaler
4
#define BAUD_REAL (F_CPU/(16*(UBRR_VAL+1)))          //reale Baudrate
5
#define BAUD_ERROR ((BAUD_REAL*1000)/BAUD-1000)        //Fehler in Promille
6
//Compilerausgabe bei Fehler
7
#if ((BAUD_ERROR>10)||(BAUD_ERROR<-10))
8
#error Systematischer Fehler der Baudrate ist größer 1% und damit zu hoch!
9
#endif
10

11

12

13
#include<avr/io.h>
14
#include<avr/interrupt.h>
15

16
unsigned char temp=0;
17

18

19
int main(void)
20
{PORTB = (1<<PORTB2)|(1<<PORTB0);                //PB0,PB2 ist 1
21
 DDRB = 0x2C;                          //SCK,MOSI,/SS = Ausgang
22
  //UART Initialisierung
23
 UCSRC = (1<<URSEL)|(1<<USBS)|(3<<UCSZ0);            //8 Bit + 2 Stoppbit
24
 UBRRL = UBRR_VAL;                        //Baudrate setzen
25
 UBRRH = (UBRR_VAL>>8);
26
 //SPI-Initialisierung
27
 SPSR = (0<<SPI2X);
28
 SPCR = (1<<SPE)|(1<<MSTR)|(2<<SPR0);              //SPI-Mode 0; 250kHz
29
  
30

31
 //Hauptprogramm
32
 UCSRB = (1<<RXCIE)|(1<<RXEN)|(1<<TXEN);            //RX-IRQ enable;TX & RX enable
33
 sei();
34
 while(1);
35
   {};
36

37
 };
38

39

40
ISR(USART_RXC_vect)
41
{cli();
42
 PORTB &= ~(1<<PORTB2);                      //slave select = low
43
 SPDR=UDR;                            //daten von RS232 an SPI schreiben
44
                         
45
 while(PINB&(1<<PINB0))                      //warte auf ACK = low
46
      {};
47
 while(!(PINB&(1<<PINB0)))                    //warte auf ACK = high
48
      {};
49
 SPDR=0x00;
50
 while(!(SPSR & (1 << SPIF)));      //Warte bis daten gesendet 
51
 
52
 PORTB |=(1<<PORTB2);
53
 UDR = SPDR;                          //daten von SPI an RS232 schreiben
54
 while(!(UCSRA&(1<<UDRE)))                    //TxD complete
55
           {};
56
 sei();
57
}

Anbei noch eine Messung...siehe data2 da sollte /SS noch low sein.
Angehängte Dateien:
Gast #965678
Lesenswert?

Hi,

versuch mal das Flag SPIF im Register SPSR zurückzusetzen, bevor Du mit 
der While-Schleife auf das Ende der Übertragung wartest. Was genau Du 
zum Zurücksetzen tun musst, findest im Datenblatt bei der Beschreibung 
des Flags.

Bye
  Deejay
OP #965689
Lesenswert?

Danke, habs gerade gefunden.
Im Datenblatt ist nichts genaues geschrieben. In ner APP von Atmel steht 
drinne, dass man erst SPSR und dann SPDR auslesen muss um das Flag zu 
löschen.
1
ISR(USART_RXC_vect)
2
{cli();
3
 PORTB &= ~(1<<PORTB2);                      //slave select = low
4
 SPDR=UDR;                            //daten von RS232 an SPI schreiben
5
                         
6
 while(PINB&(1<<PINB0))                      //warte auf ACK = low
7
      {};
8
 while(!(PINB&(1<<PINB0)))                    //warte auf ACK = high
9
      {};
10
 temp=SPSR;
11
 temp=SPDR;
12
 SPDR=0x00;
13
 while(!(SPSR & (1 << SPIF)));
14
 
15
 PORTB |=(1<<PORTB2);
16
 UDR = SPDR;                          //daten von SPI an RS232 schreiben
17
 while(!(UCSRA&(1<<UDRE)))                    //TxD complete
18
           {};
19
 sei();
20
}

So geht's jetzt.

Trotzdem Danke.

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