Forum: Mikrocontroller und Digitale Elektronik Schieberegister IC M74HC595B1R


von Jörg T. (joerg1982)


Lesenswert?

Hallo Forumsgemeinde,

seit einigen Wochen bin ich begeisterter yC Bastler. Gar nicht so 
einfach sich das Ganze im Selfmade Prinzip beizubringen. Nach dem das 
mit den LED rumspielen einigermaßen klappt, benötige ich mehr Ports für 
weitere Funktionen. Aus diesem Grund habe ich mir die im Thema 
angegebenen Schieberegister zugelegt.
Wie ihr euch schon denken könnt, es läuft nicht. Ziel ist es, mit einem 
Atmega8 insgesamt 4 Schieberegister unabhängig voneinander anzusteuern. 
Allerdings scheitert es schon bei einem.
1
void IC (uint8_t Wert)
2
{
3
  PORTD |= (1<<PORT_SCLR);
4
    for (int i = 8; i > 0; i--)
5
        {
6
            PORTD &=~ (1<<PORT_SER);
7
            if (Wert & 0x80)
8
            {
9
                PORTD |= (1<<PORT_SER);
10
            }
11
            Wert <<= 1;
12
            PORTD &=~ (1<<PORT_SCK);
13
            PORTD |= (1<<PORT_SCK);
14
        }
15
    PORTD &=~ (1<<PORT_RCK);
16
    PORTD |= (1<<PORT_RCK);    
17
    PORTD &=~ (1<<PORT_SCLR);
18
}
19
20
int main(void)
21
{
22
23
init();
24
uint8_t Test = 30;    
25
int Zahl = 0;
26
       
27
 while(1)
28
  {  
29
    
30
    IC(Test);
31
    _delay_ms(1000);
32
    Test++;
33
.
34
.
35
.
36
.
37
.


Zur Zeit gibt das Schieberegister nur den vorgegebenen Wert aus(Also 
zeigt 30 binär an). Dieser will ich aber wie im Code verändern und das 
Schieberegister soll sich danach anpassen, tut es aber nicht.

Vielen Dank schon mal im voraus für eure Hilfe.

von Marcus W. (marcusaw)


Lesenswert?

Poste doch mal bitte den ganzen Code. Mit deinem Schnipsel hier läuft 
der uint8_t nach kürzester Zeit über. Die Variable "Zahl" wird überhaupt 
nicht benutzt, etc etc. Da fehlt also etwas, um dir zu helfen.

von Stefan (Gast)


Lesenswert?

Der Code sieht ganz ok aus. Ich denke auch, daß der Fehler ausserhalb 
von dem Code ist, den Du gezeigt hast.
Kann es sein, daß die while (1) Schleife nur 1* durchläuft bzw. nach dem 
ersten Mal irgendwo hängenbleibt?
Kannst Du Deine SPI-Pins messen, ob dort dauerhaft Daten ausgegeben 
werden?

Gruß Stefan

von Jörg T. (joerg1982)


Lesenswert?

1
  if (Test > 250);
2
  {
3
    Test=1;
4
  }
5
        }
6
  return(0);
7
}

Das fehlt noch zum Code...

Ob die dauerhaft ausgeben, dass muss ich heute Mittag mal nachmessen.

Danke schon mal

von Karl H. (kbuchegg)


Lesenswert?

Jörg Tennert schrieb:

> Das fehlt noch zum Code...

Kann ich mir nicht vorstellen.
IN deinem Code wird zb eine Init Funktion aufgerufen, die nicht da ist.

Was ist so schwer daran, einfach das C-File als Anhang anzuhängen?
Antwort: gar nichts.

Auch interessant: wie ist das Schieberegister angeschlossen.
Wo führt zb PORT_SCLR hin? Geht das auf den Clear Anschluss?
Wenn ja, dann lass den Pin in Ruhe. Setz den am Anfang des Programms auf 
seinen notwendigen Pegel und lass ihn dann erst mal in Ruhe. Im Grunde 
braucht den auch keiner. Denn durch das eintakten von 8 neuen Bits, 
werden die vorher dort gewesenen Bits sowieso rausgetaktet. Die sind 
also so und so durch neue ersetzt, egal ob vorher ge-cleared wurde oder 
nicht.

Zur Arbeit mit dem SChieberegister brauchst du im Minimum genau die 3 
Leitungen
Daten
SCK
RCK

Alles andere, wie Clear und Output Enbale sind Zugabe, die man manchmal 
brauchen kann.

von Jörg T. (joerg1982)


Lesenswert?

1
#define PORT_SCK  PD0
2
#define PORT_SER  PD1
3
#define PORT_RCK  PD2
4
#define PORT_SCLR PD3
5
6
void init (void)
7
{
8
9
    DDRD |= (1<<PORT_SER);
10
    DDRD |= (1<<PORT_SCK);
11
    DDRD |= (1<<PORT_RCK);
12
    DDRD |= (1<<PORT_SCLR);
13
}
14
15
void IC (uint8_t Wert)
16
{
17
  PORTD |= (1<<PORT_SCLR);
18
    for (int i = 8; i > 0; i--)
19
        {
20
            PORTD &=~ (1<<PORT_SER);
21
            if (Wert & 0x80)
22
            {
23
                PORTD |= (1<<PORT_SER);
24
            }
25
26
            Wert <<= 1;
27
          
28
            PORTD &=~ (1<<PORT_SCK);
29
            PORTD |= (1<<PORT_SCK);
30
        }
31
   
32
    PORTD &=~ (1<<PORT_RCK);
33
    PORTD |= (1<<PORT_RCK);  
34
  
35
  PORTD &=~ (1<<PORT_SCLR);
36
}
37
38
39
int main(void)
40
{  
41
  DDRB |= (1<<PB1);
42
  DDRB |= (1<<PB2);
43
  DDRB |= (1<<PB3);
44
  
45
  init();
46
  uint8_t Test = 30;    
47
  int Zahl = 0;
48
  while(1)
49
  {  
50
    
51
    IC(Test);
52
    _delay_ms(1000);
53
    Test=Test + 1;
54
55
  if (Test > 250);
56
  {
57
    Test=1;
58
  }
59
  
60
  
61
  }
62
  return(0);
63
}

So schauts komplett aus.

PORT_SER ist am Schieberegister Pin SI angeschlossen

von Dirk K. (dekoepi)


Lesenswert?

Hier mal mein erster Test mit 'nem Schieberegister.
http://pastebin.com/jCD7ufBf

von Karl H. (kbuchegg)


Lesenswert?

Jörg Tennert schrieb:

> So schauts komplett aus.

Müsste funktionieren.

Wie siehts mit Hardware aus.
Blocvkkondensatoren angebracht?

Hast du mal nachgesehen, ob dein µC ständig resettet? (Einfach in main 
als erstes eine unabhängige LED 1 Sekunde lang einschalten und danach 
wieder aus)

von Dirk K. (dekoepi)


Lesenswert?

Der Blockkondensator-Hinweis ist gut - war bei mir das deutlichste 
Beispiel, dass der wichtig ist. Ohne liefen nur 3 LEDs, mit hat dann 
alles geklappt (davor einmal alles komplett stromlos machen war 
ebenfalls nötig ;) ).

von Jörg T. (joerg1982)


Lesenswert?

Blockkondensator???

Nein sowas ist nicht dabei...wo baue ich den ein?

von Dirk K. (dekoepi)


Lesenswert?

Von Vcc zu GND des Schiebregisters einfach einen 100nF Kerko stecken.

von Jörg T. (joerg1982)


Lesenswert?

Leider funktioniert es jetzt auch noch nicht...

von Dirk K. (dekoepi)


Lesenswert?

In deinem programm geht alles etwas durcheinander. Mal ist was an PB1-3, 
dann wieder an PD0-3.

Vielleicht liegt's ja daran. Orientiere dich beim Setup nochmal kurz an 
meiner Quelle weiter oben.

von Karl H. (kbuchegg)


Lesenswert?

Dirk K. schrieb:
> In deinem programm geht alles etwas durcheinander. Mal ist was an PB1-3,
> dann wieder an PD0-3.

Hat mich auf den ersten Blick auch verwirrt.
Ist aber tatsächlich alles korrekt. Die Richtungs-Initialisierung der 
Schiebereigster Pins findet in der Funktion Init statt.

Die Zuweisungen an DDRB am Anfang von main kannst du ignorieren. Die tun 
nichts zur Sache.

von Dietrich L. (dietrichl)


Lesenswert?

Dann wäre jetzt vielleicht ein kompletter Schaltplan + Layout ganz 
interessant ...

von Dirk K. (dekoepi)


Lesenswert?

Ok, stimmt, die PB-Teile dienen nur der Irritation :D

Hängt er sich vielleicht beim if (test>250) auf und rennt einfach nicht 
weiter? Er bleibt durch den kaputten Test immer bei 1.

Ich nutze auch nur 3 Pins des Schieberegisters; du nutzt 4. Vielleicht 
einfach Reset LOW respektive HIGH halten, sowie OE ebenfalls direkt auf 
GND ziehen (oder andersrum); habe grad das Datenblatt nicht zur Hand und 
bin zu faul zum suchen.

von Karl H. (kbuchegg)


Lesenswert?

Ach. Jetzt hab ich ihn gesehen :-)
1
  if (Test > 250);
2
                 ^
3
                 |
4
                 |

Der Nebeneffekt der Sache ist, dass dadurch die Zuweisung von 1 an Test 
ständig gemacht wird. Test zählt dadurch nie hoch.

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.