Wie viele NOP für 100NS-Clock? (Software-SPI)

Gast #5745680
Lesenswert?

Wie viele NOP brauchts zwischen SPI_SCK_HIGH() und SPI_SCK_LOW() bei 
18.432MHz (54ns pro Takt), wenn das Datenblatt des IC sagt, dass 
High/Low-Phase der Clock jeweils nicht kürzer als 100NS sein dürfen (4 
Mbit/s SC16IS750)? Hätte gedacht zwei, vielleicht einen, aber es geht 
mit 0?!
1
// 100ns Verzögerung
2

3
#define DELAY_100NS()    \
4
__asm__ __volatile__ (   \
5
  "nop\n"          \
6
  "nop\n"          \
7
)
8

9
#define DELAY_50NS()     \
10
__asm__ __volatile__ (   \
11
  "nop\n"          \
12
)
13

14
#define SPI_SCK_HIGH() PORTD |=  BITMASK4
15
#define SPI_SCK_LOW()  PORTD &= ~BITMASK4
16

17
void
18
softspi_write_byte(uint8_t out)
19
{
20
  uint8_t bitmask;
21

22
  // SCK and /CS must be low when arriving here (setup by caller)
23

24
  for (bitmask = 128; bitmask; bitmask >>= 1)
25
  {
26
    if (out & bitmask)
27
      SPI_MOSI_HIGH();
28
    else
29
      SPI_MOSI_LOW ();
30

31
    DELAY_50NS();
32

33
    SPI_SCK_HIGH();
34

35
    DELAY_50NS();
36

37
    SPI_SCK_LOW();
38

39
    DELAY_50NS();
40
  }
41
}
#5745700
Lesenswert?

Oder häng einfach mal ein Oszi/Logic-Analyzer dran. Dann siehst du wie 
dein Timing ausschaut.

Generell hast du aber eh ein Problem: Dein Code ist nicht auf andere 
Taktfrequenzen portierbar und das Timing kann sich in Abhängigkeit von 
Compiler und der eingestellten Optimierung ändern.
Gast #5746027
Lesenswert?

> Oder häng einfach mal ein Oszi/Logic-Analyzer dran

Gemacht. Statt 100ns-Takt war es ein 800ns low/164ns high-Takt (Version 
W1). Oops. Ziemlich verschätzt. Mit aufgerollter Schleife (Version W2) 
sind es jetzt 162ns low / 108ns high.

Die Lese-Schleife war nicht ganz so schlimm. 380ns low, 162ns high (R1). 
Unrolling brachte 108ns low, 109ns high (Version R2), aber das war wohl 
zu knapp - das hat nicht funktioniert. Version R3 geht (160ns low, 164ns 
high).

--- Anhänge

Version W1: 164ns hi, 760ns bis 814ns low
1
for (uint8_t bitmask = 128; bitmask; bitmask >>= 1)
2
{
3
  if (out & bitmask)
4
    SPI_MOSI_HIGH();
5
  else
6
    SPI_MOSI_LOW ();
7

8
  DELAY_50NS();
9

10
  SPI_SCK_HIGH();
11

12
  DELAY_50NS();
13

14
  SPI_SCK_LOW();
15

16
  DELAY_50NS();
17
}

Version W2: 110ns high, 542ns low
1
for (uint8_t bitmask = 128; bitmask;)
2
{
3
  if (out & bitmask)
4
    SPI_MOSI_HIGH();
5
  else
6
    SPI_MOSI_LOW();
7

8
  SPI_SCK_TOGGLE();                    // clock now high
9

10
  bitmask >>= 1;                       // place here to generate pause
11

12
  SPI_SCK_TOGGLE();                    // clock now low
13
}

Version W3: 108ns high, 162ns low
1
// bit 7
2

3
if (out & 128)
4
  SPI_MOSI_HIGH();
5
else
6
  SPI_MOSI_LOW();
7

8
SPI_SCK_TOGGLE();                    // clock now high
9

10
DELAY_50NS();
11

12
SPI_SCK_TOGGLE();                    // clock now low (idle)
13

14
// bit 6
15

16
if (out & 64)
17
  SPI_MOSI_HIGH();
18
else
19
  SPI_MOSI_LOW();
20

21
SPI_SCK_TOGGLE();                    // clock now high
22

23
DELAY_50NS();
24

25
SPI_SCK_TOGGLE();                    // clock now low (idle)
26

27
// bit 7
28

29
if (out & 32)
30
  SPI_MOSI_HIGH();
31
else
32
  SPI_MOSI_LOW();
33

34
SPI_SCK_TOGGLE();                    // clock now high
35

36
DELAY_50NS();
37

38
SPI_SCK_TOGGLE();                    // clock now low (idle)
39

40
if (out & 16)
41
  SPI_MOSI_HIGH();
42
else
43
  SPI_MOSI_LOW();
44

45
SPI_SCK_TOGGLE();                    // clock now high
46

47
DELAY_50NS();
48

49
SPI_SCK_TOGGLE();                    // clock now low (idle)
50

51
if (out & 8)
52
  SPI_MOSI_HIGH();
53
else
54
  SPI_MOSI_LOW();
55

56
SPI_SCK_TOGGLE();                    // clock now high
57

58
DELAY_50NS();
59

60
SPI_SCK_TOGGLE();                    // clock now low (idle)
61

62
if (out & 4)
63
  SPI_MOSI_HIGH();
64
else
65
  SPI_MOSI_LOW();
66

67
SPI_SCK_TOGGLE();                    // clock now high
68

69
DELAY_50NS();
70

71
SPI_SCK_TOGGLE();                    // clock now low (idle)
72

73
if (out & 2)
74
  SPI_MOSI_HIGH();
75
else
76
  SPI_MOSI_LOW();
77

78
SPI_SCK_TOGGLE();                    // clock now high
79

80
DELAY_50NS();
81

82
SPI_SCK_TOGGLE();                    // clock now low (idle)
83

84
if (out & 1)
85
  SPI_MOSI_HIGH();
86
else
87
  SPI_MOSI_LOW();
88

89
SPI_SCK_TOGGLE();                    // clock now high
90

91
DELAY_50NS();
92

93
SPI_SCK_TOGGLE();                    // clock now low (idle)

Version R1: 162ns high, 380ns low
1
uint8_t bitmask, in;
2

3
for (in = 0, bitmask = 128; bitmask; bitmask >>= 1)
4
{
5
  // read 100NS after clock went low
6

7
  if (SPI_MISO_READ())
8

9
    in |= bitmask;
10

11
  SPI_SCK_HIGH();
12

13
  DELAY_50NS();
14

15
  SPI_SCK_LOW();
16
}

Version R2: 109ns high, 108ns low
1
uint8_t in = 0;
2

3
// bit 7
4

5
if (SPI_MISO_READ())
6

7
  in |= 128;
8

9
SPI_SCK_TOGGLE();                    // clock now high
10

11
DELAY_50NS();
12

13
SPI_SCK_TOGGLE();                    // clock now low (idle)
14

15
// bit 6
16

17
if (SPI_MISO_READ())
18

19
  in |= 64;
20

21
SPI_SCK_TOGGLE();                    // clock now high
22

23
DELAY_50NS();
24

25
SPI_SCK_TOGGLE();                    // clock now low (idle)
26

27
// bit 5
28

29
if (SPI_MISO_READ())
30

31
  in |= 32;
32

33
SPI_SCK_TOGGLE();                    // clock now high
34

35
DELAY_50NS();
36

37
SPI_SCK_TOGGLE();                    // clock now low (idle)
38

39
// bit 4
40

41
if (SPI_MISO_READ())
42

43
  in |= 16;
44

45
SPI_SCK_TOGGLE();                    // clock now high
46

47
DELAY_50NS();
48

49
SPI_SCK_TOGGLE();                    // clock now low (idle)
50

51
// bit 3
52

53
if (SPI_MISO_READ())
54

55
  in |= 8;
56

57
SPI_SCK_TOGGLE();                    // clock now high
58

59
DELAY_50NS();
60

61
SPI_SCK_TOGGLE();                    // clock now low (idle)
62

63
// bit 2
64

65
if (SPI_MISO_READ())
66

67
  in |= 4;
68

69
SPI_SCK_TOGGLE();                    // clock now high
70

71
DELAY_50NS();
72

73
SPI_SCK_TOGGLE();                    // clock now low (idle)
74

75
// bit 1
76

77
if (SPI_MISO_READ())
78

79
  in |= 2;
80

81
SPI_SCK_TOGGLE();                    // clock now high
82

83
DELAY_50NS();
84

85
SPI_SCK_TOGGLE();                    // clock now low (idle)
86

87
// bit 0
88

89
if (SPI_MISO_READ())
90

91
  in |= 1;
92

93
SPI_SCK_TOGGLE();                    // clock now high
94

95
DELAY_50NS();
96

97
SPI_SCK_TOGGLE();                    // clock now low (idle)

Version R3:
1
uint8_t in = 0;
2

3
// bit 7
4

5
if (SPI_MISO_READ())
6

7
  in |= 128;
8

9
SPI_SCK_TOGGLE();                                // clock now high
10

11
DELAY_100NS();
12

13
SPI_SCK_TOGGLE();                                // clock now low (idle)
14

15
DELAY_50NS();
16

17
// bit 6
18

19
if (SPI_MISO_READ())
20

21
  in |= 64;
22

23
SPI_SCK_TOGGLE();                                // clock now high
24

25
DELAY_100NS();
26

27
SPI_SCK_TOGGLE();                                // clock now low (idle)
28

29
DELAY_50NS();
30

31
// bit 5
32

33
if (SPI_MISO_READ())
34

35
  in |= 32;
36

37
SPI_SCK_TOGGLE();                                // clock now high
38

39
DELAY_100NS();
40

41
SPI_SCK_TOGGLE();                                // clock now low (idle)
42

43
DELAY_50NS();
44

45
// bit 3
46

47
if (SPI_MISO_READ())
48

49
  in |= 16;
50

51
SPI_SCK_TOGGLE();                                // clock now high
52

53
DELAY_100NS();
54

55
SPI_SCK_TOGGLE();                                // clock now low (idle)
56

57
DELAY_50NS();
58

59
// bit 3
60

61
if (SPI_MISO_READ())
62

63
  in |= 8;
64

65
SPI_SCK_TOGGLE();                                // clock now high
66

67
DELAY_100NS();
68

69
SPI_SCK_TOGGLE();                                // clock now low (idle)
70

71
DELAY_50NS();
72

73
// bit 2
74

75
if (SPI_MISO_READ())
76

77
  in |= 4;
78

79
SPI_SCK_TOGGLE();                                // clock now high
80

81
DELAY_100NS();
82

83
SPI_SCK_TOGGLE();                                // clock now low (idle)
84

85
DELAY_50NS();
86

87
// bit 1
88

89
if (SPI_MISO_READ())
90

91
  in |= 2;
92

93
SPI_SCK_TOGGLE();                                // clock now high
94

95
DELAY_100NS();
96

97
SPI_SCK_TOGGLE();                                // clock now low (idle)
98

99
DELAY_50NS();
100

101
// bit 0
102

103
if (SPI_MISO_READ())
104

105
  in |= 1;
106

107
SPI_SCK_TOGGLE();                                // clock now high
108

109
DELAY_100NS();
110

111
SPI_SCK_TOGGLE();                                // clock now low (idle)
112

113
DELAY_50NS();
114

115
return(in);
Gast #5746030
Lesenswert?

PS:
1
#define SPI_SCK_HIGH()       PORTD |=  BITMASK4
2
#define SPI_SCK_LOW()        PORTD &= ~BITMASK4
3
#define SPI_SCK_TOGGLE()     PIND   =  BITMASK4 /* setting a bit in PINx (like this, not |=) toggles corresponding bit in PORTx */
4
#define SPI_CS_HIGH()        PORTD |=  BITMASK7
5
#define SPI_CS_LOW()         PORTD &= ~BITMASK7
6
#define SPI_MOSI_HIGH()      PORTD |=  BITMASK5
7
#define SPI_MOSI_LOW()       PORTD &= ~BITMASK5
8
#define SPI_MOSI_TOGGLE()    PIND   =  BITMASK5 /* setting a bit in PINx (like this, not |=) toggles corresponding bit in PORTx */
9
#define SPI_MISO_READ()      PIND   &  BITMASK3

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