seltsames Problem mit SPI und 595

Gast #1897024
Lesenswert?

Hallo,

möchte per 74..595 mehrere 7 Segmentanzeigen ansteuern.
Momentan habe ich erstmal einen 595 angeschlossen.

Momentan bin ich bei 3 Varianten:

1. Über manuelles rüberschieben bekomme ich Daten rein.
2. Hardware SPI klappt dagegen nicht.
3. Software SPI irgendwie auch nicht. Das ist seltsam, zumal 1.) geht.
Hier kommt nur nicht reproduzierbares Chaos rüber, bei jedem µC reset 
etwas anderes.

Das Setup:

Der 595 ist über MISO, SCK und PD7 als RCK (der Pin, der die Register 
auf die Ausgangspins übernimmt) angeschlossen.
µC ist ein Mega32 mit 16Mhz Quarz.
Reset des 595 ist fest auf VCC, Output enable auf GND.

Variante 1 (Jedes Bit manuell rüberschieben):
1
#include <avr/io.h>
2
#include <stdlib.h>
3

4
#define  RCK_DDR DDRD
5
#define RCK_PORT PORTD
6
#define  RCK_PIN  7
7
#define SPI_MOSI   5
8
#define SPI_SCK    7
9
#define SPI_SS    4
10
#define DDR_SPI    PORTB
11

12

13

14
int main(void) {
15

16
  DDRD |= (1<<PD2); //macht eine LED an
17
  PORTD |= (1 << PD2);
18

19
  
20
  DDRB |= (1<<7) |  (1<<5); //sck und mosi
21
  DDRD |= (1<<7); 
22
  PORTB |= (1<<5);
23
  PORTB |= (1<<7);
24

25
  PORTB &= ~(1<<7);
26
  PORTB &= ~(1<<5);
27

28
  PORTB |= (1<<7);  //weitere Clockimpulse
29
  PORTB &= ~(1<<7);
30

31
  PORTB |= (1<<7);
32
  PORTB &= ~(1<<7);
33

34

35
  PORTB |= (1<<7);
36
  PORTB &= ~(1<<7);
37

38

39

40

41
  PORTD |= (1<<7);  //LEDs anmachen
42
  PORTD &= ~(1<<7);
43

44
  while (1)  {
45

46

47
  }
48

49
}

Variante 2: Hardware SPI
1
#include <avr/io.h>
2
#include <stdlib.h>
3

4
#define  RCK_DDR DDRD
5
#define RCK_PORT PORTD
6
#define  RCK_PIN  7
7
#define SPI_MOSI   5
8
#define SPI_SCK    7
9
#define SPI_SS    4
10
#define DDR_SPI    PORTB
11

12
void SPI_MasterInit(void);
13
void display_write(uint8_t dc) {
14

15
  SPDR = dc; 
16

17
  while (!(SPSR & (1 << SPIF)));
18
  
19
  RCK_PORT &= ~(1 << RCK_PIN); //LEDs anmachen
20
  RCK_PORT |= (1 << RCK_PIN);
21

22
}
23

24
int main(void) {
25

26
  SPI_MasterInit();
27
  display_write(0b10101010);
28

29
  DDRD |= (1<<PD2);
30
  PORTD |= (1 << PD2);
31

32
  while (1);
33

34

35
}
36

37
void SPI_MasterInit(void) {
38
  /* Set MOSI and SCK output, all others input */
39
  DDR_SPI = (1 << SPI_MOSI) | (1 << SPI_SCK) | (1 << SPI_SS);
40
  /* Enable SPI, Master, set clock rate fck/2 */
41
  SPCR = (1 << SPE) | (1 << MSTR) | (1 << SPR0) | (1 << SPR1);
42
  //SPSR |= (1 << SPI2X);
43
  
44
  RCK_DDR |= (1<<RCK_PIN);
45
  RCK_PORT |= (1<<RCK_PIN);
46
}

Variante 3: (Software SPI mit SPI Pins)
1
#include <avr/io.h>
2
#include <stdlib.h>
3

4
#define  RCK_DDR DDRD
5
#define RCK_PORT PORTD
6
#define  RCK_PIN  7
7
#define SPI_MOSI   5
8
#define SPI_SCK    7
9
#define SPI_SS    4
10
#define DDR_SPI    PORTB
11

12
void SPI_MasterInit(void);
13
void display_write(uint8_t dc) {
14

15
  unsigned char bits;
16
  for (bits = 8; bits > 0; bits--) {
17
    PORTB &= ~(1<<SPI_MOSI);
18
    if (dc & 0x80) {
19
      PORTB |= (1<<SPI_MOSI);
20
    }
21

22
    dc <<= 1;
23
    
24
    PORTB |= (1<<SPI_SCK);
25
    PORTB &= ~(1<<SPI_SCK);
26
  }
27

28

29
  RCK_PORT &= ~(1 << RCK_PIN);
30
  RCK_PORT |= (1 << RCK_PIN);
31

32
}
33

34
int main(void) {
35

36
  SPI_MasterInit();
37
  display_write(0b10101010);
38

39
  DDRD |= (1<<PD2);
40
  PORTD |= (1 << PD2);
41

42
  while (1);
43

44
}
45

46
void SPI_MasterInit(void) {
47
  /* Set MOSI and SCK output, all others input */
48
  DDR_SPI = (1 << SPI_MOSI) | (1 << SPI_SCK) | (1 << SPI_SS);
49
  
50
  RCK_DDR |= (1<<RCK_PIN);
51
  RCK_PORT |= (1<<RCK_PIN);
52
  PORTB &= ~(1<<SPI_SCK);
53
}

Irgendwas essentielles muss ich übersehen, sonst würde entweder 1 auch 
nicht funktionieren oder aber 3 auch klappen.
Mein Ziel ist es, es per Hardware SPI hinzubekommen.

Der µC wird über Bootloader programmiert, es hängt kein Programmer an 
SPI.
Hat jemand eine Idee?
Gast #1897026
Lesenswert?

also wenn da eine LED dran hängt dann brauchst du aber entweder eine 
high speed kamera oder ein "schnelles" auge:

 RCK_PORT &= ~(1 << RCK_PIN); //LEDs anmachen
  RCK_PORT |= (1 << RCK_PIN);



geht an und auch glecih wieder aus (kommt auf deine CPU Takfrequenc 
drauf an wie schnell aber ich schätze <1us )

bg

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