Forum: Compiler & IDEs Schieberegister-Kaskade ansprechen


von Roland (Gast)


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

von Ja mann (Gast)


Lesenswert?

>kann das so funktionieren,
Keine Ahnung, warum testest Du das nicht erst mal und fragst dann 
nochmal spezifischer wenn das Problem bekannt ist ?

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


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

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.