Forum: Mikrocontroller und Digitale Elektronik Problem mit SPI-Datenübertragung zwischen Master und Slave


von H. G. (ledi)


Lesenswert?

Ich habe 2 Boards (Controller = ATMEL AT90PWM316) miteinander über die 
ISP-Schnittstelle verbunden und möchte vom Master Daten an den Slave 
senden und diese dort am PORTC ausgeben.

CLK, SS und MOSI habe ich mit dem Oszi am Master gemessen. Hier ist 
alles OK!

Mein Problem ist, dass ich die Übertragung am PORTC nur empfange, wenn 
ich das Programm Schritt für Schritt im Debugger durchsteppe.


Hier mein C-Code für den Master:
1
#include <avr/io.h>
2
#include <util/delay.h>
3
4
void SPI_Master_Init(void)
5
{
6
  SPCR &=  ~(1<<DORD);  // Send MSB first
7
  SPCR |=  (1<<MSTR);  // Controller = Master
8
  SPCR &=  ~(1<<CPOL);  // CLK positiv phase
9
  SPCR |=  (1<<CPHA);  // Sampling data @ rising edge
10
  SPCR |=  (1<<SPR1);  // CLK / 64 = 125kHz
11
12
  DDRB |=  (1<<PB1);  // Set MOSI output
13
  DDRB |=  (1<<PB7);  // Set SCK output
14
15
  DDRD |=  (1<<PD3);  // Set SS output 
16
17
  SPCR |=  (1<<SPE);  // SPI enable
18
}
19
20
void SPI_Master_Transmit(char cData)
21
{
22
  PORTD &= ~(1<<PD3);        // SS = low
23
  SPDR = cData;          // Start transmission
24
  while (!(SPSR & (1<<SPIF)));  // Wait for transmission complete
25
  PORTD |= (1<<PD3);        // SS = high
26
}
27
28
void main(void)
29
{              
30
  SPI_Master_Init();
31
32
    while(1)
33
    {
34
    SPI_Master_Transmit(0b11010010);
35
    _delay_ms(500);         // delaytime between next transmission  
36
    SPI_Master_Transmit(0b00000001); 
37
    _delay_ms(500);
38
    }
39
}

Hier mein C-Code für den Slave:
1
#include <avr/io.h>
2
#include <util/delay.h>
3
4
5
6
void SPI_Slave_Init(void)
7
{
8
  SPCR &=  ~(1<<DORD);  // Send MSB first
9
  SPCR &=  ~(1<<MSTR);  // Controller = Slave
10
  SPCR &=  ~(1<<CPOL);  // CLK positiv phase
11
  SPCR |=  (1<<CPHA);  // Sampling data @ rising edge
12
  SPCR |=  (1<<SPR1);  // CLK / 64 = 125kHz
13
14
  DDRB |=  (1<<PB0);  // Set MISO output
15
  DDRB &= ~(1<<PB1);  // Set MOSI input
16
  DDRB &=  ~(1<<PB7);  // Set SCK input
17
18
  SPCR |=  (1<<SPE);  // SPI enable
19
}
20
21
unsigned char SPI_Slave_Receive()
22
{
23
  while (!(SPSR & (1<<SPIF)));  // Wait for transmission complete
24
  return SPDR;
25
}
26
27
void main(void)
28
{          
29
  DDRC = 0xFF;
30
      
31
  SPI_Slave_Init();
32
33
    while(1)
34
    {
35
    SPI_Slave_Receive();
36
    PORTC = SPI_Slave_Receive();
37
    _delay_us(50);     // delaytime between next transmission   
38
    }
39
}

von Rainer U. (r-u)


Lesenswert?

wofür ist diese Zeile in Spi_slave_receive:

  SPCR |=  (1<<SPR1);  // CLK / 64 = 125kHz

?

von H. G. (ledi)


Lesenswert?

Rainer Unsinn schrieb:
> wofür ist diese Zeile in Spi_slave_receive:
>
>   SPCR |=  (1<<SPR1);  // CLK / 64 = 125kHz
>
> ?

Hat in dem Fall keine Bedeutung (da Slave).
In meiner Software ist die Zeile auch auskommentiert.

von Rainer U. (r-u)


Lesenswert?

und - willst Du nur jedes zweite Zeichen an PortC ausgeben?

und - wofür wartest Du die 50 Mikrosekunden? _delay_us(50);

von H. G. (ledi)


Lesenswert?

Rainer Unsinn schrieb:
> und - willst Du nur jedes zweite Zeichen an PortC ausgeben?

abwechselnd soll nach je 500ms am PORTC
 11010010
und
 00000001
ausgegeben werden.
1
while(1)
2
    {
3
    SPI_Master_Transmit(0b11010010);
4
    _delay_ms(500);  // delaytime between next transmission  
5
    SPI_Master_Transmit(0b00000001); 
6
    _delay_ms(500);  // delaytime between next transmission
7
    }

> und - wofür wartest Du die 50 Mikrosekunden? _delay_us(50);

das ist für nix. Das habe ich auch auskommentiert.

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.