SPI mit ATMEGA328 als Master und X25020 als slave

OP #5031761
Lesenswert?

Ich habe das letztes mal vor 2-3 Jahre, SPI mit fertige Arduino
Libraries programmiert.
Heute habe ich mit ATMEGA328p als Master und X25020P(EEPROM) als Slave
konfiguriert. Ich würde sagen 'auf gut Deutsch'- das ist das billigste
von billigste SPI Programm. :)

Also, das Ziel war ein Byte (0x01) schreiben auf Adresse 0x20 und die
geschriebene Byte wieder lesen. Wenn lesen erfolgreich war, leuchtet ein
LED.

Ich wusste was wo angeschlossen werden muss, also nicht zu viel HW
Aufwand.
Datenblatt von x25020p chip:
http://pdf.datasheetcatalog.com/datasheet_pdf/xicor/X25020P_to_X25020SI-2,7.pdf


C code:
1
#include <avr/io.h>
2
#include <util/delay.h>
3
#include <avr/interrupt.h>
4
#include <string.h>
5

6

7

8
void spi_master_init()
9
{
10
   DDRB = ( (1<<PB2) | (1<<PB3)  | (1<<PB5) );   // /SS as output, MOSI and SCK as output
11
   SPCR = ( (1<<SPE) | (1<<SPR1) | (1<<MSTR)); //SPI Enable, fosc/64, Master mode
12
}
13

14

15
void spi_slave_init()
16
{
17
   DDRB = 0<<PB4;     //MOSI as input
18
   SPCR = 1<<SPE ;
19
}
20

21

22
void SPI_Tx(char data)
23
{
24
   SPDR=data;
25
   while( !(SPSR & (1<<SPIF)) );   //wait until SPIF flag is set, to indicate transmission is complete
26
}
27

28
char SPI_Rx()
29
{
30
   char Rx_char;   
31
   SPI_Tx(0);
32
   while( !(SPSR & (1<<SPIF)) );
33
     Rx_char= SPDR;
34
     
35
   return Rx_char;
36
}
37

38
void write_to_slave()
39
{
40
   PORTB|=1<<PB2;    //take /CS on slave LOW
41
   SPI_Tx(0x06);  //WREN write enable command
42
   PORTB&=~(1<<PB2);    //take /CS on slave HIGH
43
   
44
   PORTB|=1<<PB2;    //take /CS on slave LOW
45
   SPI_Tx(0x02);  //WRITE instruction
46
   SPI_Tx(0x20);  //Address to write data to
47
   SPI_Tx(0x01);  //Data to be written
48
   PORTB&=~(1<<PB2);    //take /CS  on slave HIGH
49
}
50

51
char read_from_slave()
52
{
53
   char recvd_char;
54
   PORTB|=1<<PB2;    //take /CS on slave LOW
55
   SPI_Tx(0x03);  //READ instruction
56
   SPI_Tx(0x20);  //Address to be read from
57
 
58
   recvd_char = SPI_Rx();
59
   return recvd_char;
60
}
61

62
int main (void)
63
{
64
   DDRC=0xff;   //PORTC as output
65
  
66
   
67
   char recvdchar=0;
68
   
69
   spi_master_init();
70
   spi_slave_init();
71
   
72
   write_to_slave();
73
   
74
   recvdchar=read_from_slave();
75

76
   if(recvdchar==0x01)
77
    PORTC=1<<PC0;
78

79

80

81

82
}


Das Problem ist nun, LED leuchtet nicht wie erwartet. Was habe ich 
falsch gemacht!?
Angehängte Dateien:
Gast #5031770
Lesenswert?

In spi_slave_init() steht
> SPCR = 1<<SPE ;
damit wird das
> SPCR = ( (1<<SPE) | (1<<SPR1) | (1<<MSTR));
aus spi_master_init() glatt überschrieben.

> PORTB|=1<<PB2;    //take /CS on slave LOW
> PORTB&=~(1<<PB2);    //take /CS on slave HIGH
Das ist doch jeweils genau umgekehrt, oder hängt ein Inverter 
dazwischen?
OP #5031771
Lesenswert?

S. Landolt schrieb:
> In spi_slave_init() steht
>> SPCR = 1<<SPE ;
> damit wird das
>> SPCR = ( (1<<SPE) | (1<<SPR1) | (1<<MSTR));
> aus spi_master_init() glatt überschrieben.

Das stimmt, muss ich korrigieren!

>> PORTB|=1<<PB2;    //take /CS on slave LOW
>> PORTB&=~(1<<PB2);    //take /CS on slave HIGH
> Das ist doch jeweils genau umgekehrt, oder hängt ein Inverter
> dazwischen?
/CS ist ein active low auf dem IC, und auf dem Master /SS ist active 
low.

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