Schieberegister-Kaskade ansprechen

Gast #1040717
Lesenswert?

Guten Abend,
ich hab hier eine Schaltung vor mir, wo 4 Schieberegister kaskadiert 
wurden. Die Ansteuerung der Schieberegister,74HC595D, erfolgt über SPI, 
Controller ist ein AtMega32.
Meine Frage dazu ist, wie steuere ich so was an, ich hatte mir ueberlegt 
das so zumachen:
Das Array ground_tab ist eine Vorgabe, diese Werte muessen ausgegeben 
werden:
1
#include <avr/io.h>
2
.
3
.
4
static uint32_t ground_tab[6] = {0xFD,0x2CF5,B6C95,AB2C55,5AB2663,C5C8A27B};
5
.
6
.
7
void init_spi(void)
8
{
9
  // Set MOSI, SS and SCK output, all others input
10
  DDRB |= (1<<PB4) | (1<<PB5) | (1<<PB7) | (1<<PB0) | (1<<PB1) | (1<<PB2);
11
  
12
  // Enable SPI, Master, set clock rate double
13
  SPCR |= (1<<SPE) | (0<<DORD) | (1<<MSTR) | (1<<CPHA);
14
  SPSR |= (1<<SPI2X);  
15
  SPDR = 0x01;
16
  SR_On;  
17
}
18

19
void spi_split(uint32_t data)
20
{
21
    int8_t i;
22
    uint8_t tmp;
23
    for(i=3;i >= 0; i--){
24
        tmp = (data >> (8*i));
25
        spi_senden(tmp);
26
    }
27
    SR_On();
28
    asm volatile ("nop");
29
    SR_Off;
30
}
31

32
void spi_senden(uint8_t cData)
33
{
34
  SR_Off;
35
  while(!(SPSR & (1<<SPIF)));
36
  SPDR = cData;
37
  while(!(SPSR & (1<<SPIF)));
38
  SR_On;
39
}
40

41
int main(void)
42
{
43
for(;;)
44
{
45
.
46
.
47
for(uint8_t i=0;i<6;i++)
48
{
49
spi_split(ground_tab[i]);
50
}
51
.
52
.
53
}
54
}
Das ist so wie ich mir das vorgestellt habe, kann das so funktionieren, 
hab damit noch keine Erfahrung.
Schon mal Danke,
Roland
Moderator Persönliche Seite #1040760
Lesenswert?

Deine Hardware kennst du selbst am besten.  Ich habe etwas ähnliches
zur Ansteuerung meiner Nixie-Uhr gebaut.  Hier sind die relevanten
Codeschnipsel:
1
static void
2
ioinit(void)
3
{
4
  /* PB0, /SS, MOSI, SCK output */
5
  DDRB = _BV(PB4) | _BV(PB5) | _BV(PB7);
6
  /* Setup SPI */
7
  SPCR = _BV(SPE) | _BV(MSTR);
8

9
...
10
}
11

12
/*
13
 * Transmit a single digit's bits to the shift register chain.  The
14
 * rightmost digit (seconds LSB) is transferred first.
15
 */
16
static void
17
spi_xmit(uint8_t num)
18
{
19
  uint8_t digit;
20

21
  if (num < DIGIT_OFF)
22
    digit = pgm_read_byte(digits + num);
23
  else
24
    digit = B0 | B0_;
25

26
  SPDR = digit;
27
  loop_until_bit_is_set(SPSR, SPIF);
28
}
29

30
/*
31
 * Update the '595 output latches from the values shifted through the
32
 * chain.
33
 */
34
static void
35
load_595_latches(void)
36
{
37
  PORTB |= _BV(PB4);
38
  PORTB &= ~_BV(PB4);
39
}
40
...
41
      if (update_display)
42
        {
43
          int8_t i;
44

45
          for (i = 5; i >= 0; i--)
46
            {
47
              if (display_enabled)
48
                spi_xmit(display_buf[i]);
49
              else
50
                spi_xmit(DIGIT_OFF);
51
            }
52

53
          load_595_latches();
54
        }

Unterschiede, die mir auffallen:

. du setzt CPHA (warum?)
. du setzt SPI2X (OK, hätte ich sicher auch tun können)
. du beschreibst SPDR am Anfang einmal mit 0x01, das löst einen
  Transfer aus, obwohl du doch eigentlich immer 4 Transfers im
  Block brauchst, oder?
. das Initialisieren von DDRB als ODER-Operation kostet eine
  sinnlose Einleseoperation; weise es doch einfach direkt zu

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