Forum: Mikrocontroller und Digitale Elektronik seltsames Problem mit SPI und 595


von Dantor (Gast)


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?

von ggg (Gast)


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

von Dantor (Gast)


Lesenswert?

Okay,

es muss natürlich statt
1
#define DDR_SPI    PORTB
1
#define DDR_SPI    DDRB

heißen und so läufts dann auch!
Ich sitze da echt seit 5 Stunden dran :)

von Dantor (Gast)


Lesenswert?

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

Das ist der "enable" Pin (Storage Clock), der die internen Flip Flops 
nach außen auf die Pins schaltet.

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.