Forum: Mikrocontroller und Digitale Elektronik SPI und I²C zeitgleich benutzen


von Andre K. (round_one)


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!

von Peter D. (peda)


Lesenswert?

SD-Karten wuseln ja ordentlich Daten umher (FAT usw.), da würde ich das 
harte SPI nehmen.

Für die paar Byte des RTC reicht weiches I2C völlig.
Oder viele MCs erlauben direkt den Anschluß eines Uhrenquarzes im 
Stromsparmodus, dann ohne extra RTC-Chip.


Peter

von Andre K. (round_one)


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?

von stephan_ (Gast)


Lesenswert?


von Andre K. (round_one)


Lesenswert?

Die Sprutseiten hab ich auch schon alles durch. Ich würde halt nur gerne 
in C bleiben, da ich mich da etwas "wohler" fühle :)

von Peter D. (peda)


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

von Andre K. (round_one)


Lesenswert?

Vielen Dank für den Code, Peter! Ich werd's direkt mal testen.

von kruemeltee (Gast)


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
*/

von stephan_ (Gast)


Lesenswert?

Andre K. schrieb:
> Die Sprutseiten hab ich auch schon alles durch. Ich würde halt nur gerne
> in C bleiben, da ich mich da etwas "wohler" fühle :)

Inline ASM ???

von ado (Gast)


Lesenswert?

Microchip hat auch noch Funktions-Bibliotheken in denen Software und 
Hardware-Schnittstellen angesprochen werden können.

Keine Ahnung ob die was taugen.


http://ww1.microchip.com/downloads/en/devicedoc/MPLAB_C18_Libraries_51297f.pdf

von Bernd R. (Firma: Promaxx.net) (bigwumpus)


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.

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.