SPI und I²C zeitgleich benutzen

OP #1683898
Lesenswert?

Hallo zusammen!
Ich arbeite gerade an einem Projekt, bei dem ich eine RTC (über I²C) und 
eine SD Karte (SPI) zeitgleich an einem 18F458 betreiben muss.
Die RTC soll dabei in bestimmten Intervallen angesprochen werden und 
einen Timestamp auf die MMC schreiben.
I²C und SPI werden bei diesem PIC von den gleichen PINs angeboten. Daher 
hab ich jetzt drei Möglichkeiten:
- RTC über I²C und MMC über Soft-SPI
- RTC über Soft-I²C und MMC über SPI
- RTC über I²C und MMC über I²C-SPI Bridge

Hat jemand von euch schon Erfahrungen damit gesammelt oder einen Tipp, 
welches die einfachste bzw. logischste Lösung ist?

Vielen Dank schon mal im Voraus!
OP #1683946
Lesenswert?

Das mit dem Quarz geht leider nicht, da der µC schon auf einer 
Embeddedplatine sitzt.
Das mit dem Software-I²C lese ich mir jetzt schon die ganze Zeit durch. 
Aber da ich (noch) nicht soo viel Routine im C Programmieren hab, weiß 
ich nicht wirklich, wie ich da rangehen soll. Ein Beispiel in C auf PIC 
bezogen hab ich noch nicht gefunden..
Kenn vielleicht jemand einen guten Link oder hat selbst schon mal eine 
SW-I²C-Routine für PICs geschrieben?
#1684015
Lesenswert?

Ist fürn AVR, sollte aber leicht anzupassen sein.
Beim PIC sind wohl die Directionbits anders rum.
1
#define i2c_delay()     _delay_us( 2.5 / 2 )    // 2.5us = 400kHz
2

3

4
#define ssda_lo()       SSDA_DDR = 1
5
#define ssda_hi()       SSDA_DDR = 0
6
#define sscl_lo()       SSCL = 0
7
#define sscl_hi()       SSCL = 1
8

9

10
void si2c_start( void )                         // input: SDA = 1, SCL = x
11
{
12
  SSCL_DDR = 1;                                 // SCL = output
13
  SSDA = 0;
14
  SSDA_DDR = 0;                                 // SDA = high (input)
15
  sscl_hi();
16
  i2c_delay();
17
  ssda_lo();
18
  i2c_delay();
19
  sscl_lo();
20
}
21

22

23
void si2c_stop( void )                          // input: SDA = 1, SCL = 0
24
{
25
  ssda_lo();
26
  i2c_delay();
27
  sscl_hi();
28
  i2c_delay();
29
  ssda_hi();
30
}
31

32

33
static uint16_t si2c_rw( uint16_t val )         // input: SDA = x, SCL = 0
34
{
35
  for( uint8_t i = 9; i; i-- ){                         // data + ACK
36
    if( val & 0x8000 )
37
      ssda_hi();
38
    else
39
      ssda_lo();
40
    i2c_delay();
41
    sscl_hi();
42
    i2c_delay();
43
    val <<= 1;
44
    if( SSDA_PIN )
45
      val |= 0x80;
46
    sscl_lo();
47
  }
48
  return val;
49
}
50

51

52
uint8_t si2c_r( uint8_t nack )                          // input NACK
53
{
54
  if( nack )
55
    nack = 0x80;                                        // set only bit 7 !
56
  return si2c_rw( 0xFF00 | nack ) >> 8;                 // return data
57
}
58

59

60
uint8_t si2c_w( uint8_t val )                           // input data
61
{
62
  return si2c_rw( 0x00FF | (val<<8)) & 0xFF;            // return NACK
63
}


Peter
Gast #1684072
Lesenswert?

Hier noch ein 8051-C-Code für Software I2C, dort sieht man sehr genau 
und auf den ersten Blick, wann welcher Pin welchen Zustand hat.
1
//-----------------------------------------------------------------
2
void delay(unsigned char warte_wert)
3
{
4
  do
5
  {
6
    warte_wert--;
7
  }
8
  while(warte_wert != 0);
9
}
10
//-----------------------------------------------------------------
11
void i2c_bus_start()
12
{
13
  SCL = 0;
14
  delay(1);
15
  SDA = 1;
16
  delay(1);
17
  SCL = 1;
18
  while(SCL==0);
19
  delay(1);
20
  SDA = 0;
21
  delay(1);
22
  SCL = 0;
23
  delay(1);
24
  SDA = 1;
25
  delay(1);
26
}
27
//-----------------------------------------------------------------
28

29
void i2c_bus_stop()
30
{
31
  SCL = 0;
32
  delay(1);
33
  SDA = 0;
34
  delay(1);
35
  SCL = 1;
36
  while(SCL==0);
37
  delay(1);
38
  SDA = 1;
39
  delay(1);
40
  SCL = 0;
41
  delay(1);
42
}
43

44
//-----------------------------------------------------------------
45
void i2c_bit_write(bit bit_wert)
46
{
47
  SDA = bit_wert;
48
  delay(1);
49
  SCL = 1;
50
  while(SCL==0);
51
  delay(1);
52
  SCL = 0;
53
  delay(1);
54
}
55
//-----------------------------------------------------------------
56
/*
57
bit i2c_bit_read()
58
{
59
  bit bit_wert;
60
  SCL = 0;
61
  delay(1);
62
  SDA = 1;
63
  delay(1);
64
  SCL = 1;
65
  while(SCL==0);
66
  delay(1);
67
  bit_wert = SDA;
68
  SCL = 0;
69
  delay(1);
70
  SDA = 0;
71
  delay(1);
72
  return(bit_wert);
73
}
74
*/
75
//-----------------------------------------------------------------
76
void i2c_ack_slave()
77
{
78
  SCL = 0;
79
  delay(1);
80
  SDA = 1;
81
  delay(1);
82
  SCL = 1;
83
  while(SCL==0);
84
  while(SDA==1);
85
  delay(1);
86
  SCL = 0;
87
  delay(1);
88
}
89
//-----------------------------------------------------------------
90
/*
91
void i2c_ack_master()
92
{
93
  SCL = 0;
94
  delay(1);
95
  SDA = 0;
96
  delay(1);
97
  SCL = 1;
98
  while(SCL==0);
99
  delay(2);
100
  SCL = 0;
101
  delay(1);
102
  SDA = 1;
103
  delay(1);
104
}
105
*/
106
//-----------------------------------------------------------------
107
void i2c_byte_write(unsigned char byte_wert)
108
{
109
  unsigned char i;
110
  bit bit_wert;
111
  for(i=0;i<=7;i++)
112
  {
113
    bit_wert = (byte_wert&0x80)/128;
114
    i2c_bit_write(bit_wert);
115
    byte_wert=byte_wert<<1;
116
  }
117
}
118
//-----------------------------------------------------------------
119
/*
120
unsigned char i2c_byte_read()
121
{
122
  unsigned char i;
123
  unsigned char byte_wert=0;
124
  for(i=0;i<=7;i++)
125
  {
126
    byte_wert=(i2c_bit_read()<<(7-i))+byte_wert;
127
  }
128
  return(byte_wert);
129
}
130
*/
(Firma: Promaxx.net) #1711696
Lesenswert?

Ich habe eine Steuerung gebaut, die I2C- und SPI-Slaves anspricht (und 
das mit 5V und 3,3V!).
Mit einem Analog-Umschalter (4053?) schalte ich die SDA/SCL-Signale auf 
jeweils einen Bus (Pull-Ups bzw -downs intelligent gewählt).
Läuft prima.
Die Software aktiviert immer das benötigte Hardware-Modul und den 
Umschalter und spricht die Geräte an.

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