Forum: Mikrocontroller und Digitale Elektronik HC595 ansteuern in C


von TobyTetzi (Gast)


Lesenswert?

Hallo,

ich habe schon einiges über diese HC595 gelesen.
Ob in Assembler, Bascom oder so.

Nur leider weiß ich überhaupt nicht, wie ich diese Schieberegister
in C ansteuern kann.

Ich habe zuerst mal vor, ein oder zwei HCs mit einem Mega8
anzusteuern.
Ich habe mehrere HEX Werte im Ram, und diese möchte ich gerne an den
Ausgängen der HCs anstehen haben.

Könnte mir evtl. jamand weiterhelfen?
Vielleicht sogar mit einer einfachen C Routine?

Gruß Toby

von Michael (Gast)


Lesenswert?

for (j=0;j<8;j++)
{
  if (!(i & 1))
  {
    PORTB = PORTB &~ bit_2;
  }
  else
  {
    PORTB = PORTB | bit_2;
  }
  PORTE = PORTE | bit_7;
  PORTE = PORTE &~ bit_7;
  i = i >> 1;
}
i = bei mir ein unsigned char und enthält den auszugebenden Wert.Das
geht an den Dateneingang.Mit PortE | bit_7 und &~ bit_7 takte ich das
Datum raus. bit_2 von PortB geht an die 14, bit:_7 von PortE ist die
11.
Michael

von TobyTetzi (Gast)


Lesenswert?

Hallo Michael,

welchen Proz verwendest du?

Ein Mega8 hat keinen PortE.

Er Hat nur PORTB, PORTC und PORTD !

Aber ich wollte doch auch die Schieberegister per SPI ansteuern.
Das muß doch irgendwas mit MOSI, SCK und so sein.
Und dann eine Schleife, die pro Schieberegister 8mal durchläuft,
und dabei die Bits rüberschiebt, nicht?

Gruß Toby

von Peter D. (peda)


Lesenswert?

"Aber ich wollte doch auch die Schieberegister per SPI ansteuern."

Da hat wohl Micha vergessen, Deine Gedanken zu lesen.


Peter

von Michael (Gast)


Lesenswert?

Das Ding ist für nen MEGA64 geschrieben. Die Ports sind beliebig. Was
ich dir zeigen wollte ist eine SPI-Nachbildung z.B. für einen 89C2051,
einen 2313 usw. SPI ist die elegantere Lösung.
Michael

von TobyTetzi (Gast)


Lesenswert?

Hallo,

ja ja, da hab ich wohl vergessen, mitzuteilen, das ich die
HCs per SPI ansteuern wollte.

Also nochmal, wie sieht ein C Code aus, mit dem ich 1,2 oder mehrere
HC595 per SPI von Mega8 ansteuern kann?

Desweiteren würde ich gern wissen, wie ich die SPI Schnittstelle
einstellen muß.

Gruß Toby

von Hagen (Gast)


Lesenswert?

Erstmal stellt sich die Frage wie du die HC595 anschließt. Ich habe +MR
auf VCC da ich die Register nicht in einem Rutsch leeren muß. Dann OE
und ST_CP, sprich Output Enable und Storage Clock verbunden. Alle HC595
werden daran paralell geschaltet. Nun noch Q7' mit DS des nachfolgenden
HC595 verbinden, sprich die Register kaskadieren.
Alle SH_CP = Shiftregister Clock der HC595 werden parallel geschaltet.

Das ganze gebilde benötigt dann 5 Leitungen:
GND, Vcc, CLK == Clock == SH_CP, DTA == DS des ersten registers, und CS
= Chip Select == OE/ST_CP. Nun wird CS am AVR zB. an SS = Slave Select
drangehangen, da der AVR sowieso im Master SPI betrieben werden soll
ist dies sinnvoll. Wird der SS Pin als Input benutzt muß man beim SPI
höllisch darauf aufpassen das am SS Pin kein Low anliegt wenn  SPI
aktiv ist. An MOSI --> DTA==DS ran udn an SCLK -> CLK.

Willst du nun Daten übertragen ist SS erstmal immer auf H Pegel. Nun
per SPI einfach die Bytes raus. Wenn alles übertragen wurde ein kurzer
Low Impuls auf den SS Pin damit über die SH_CP Eingänge die
Registerinhalte in die Storage Register geschaltet werden. Nachdem man
SS wieder auf High gesetzt hat wird durch den OE Input der HC595 dieses
Storage Register auf die Ausgänge geleget. D.h. solange SS auf Low ist
sind die Ausgänge automatisch auf Tristate.

Gruß Hagen

von Hagen (Gast)


Lesenswert?

Die Ansteuerung in C/Assembler ist unkritisch. Du kannst den höchsten
Takt nehmen mit SPI2C = doppelter Geschwindigkeit, da du die 27MHz der
HC595 niemals erreichen wirst. Die Phase des SPI Clocks ist
uninteressant,ich habe alle 4 möglichen durchgetestet und die HC595
reagierten immer korrekt. Du solltest den SPI Interrupt benutzen um per
ISR im Hintergund die Bytes an das SPI Datenregister übergeben zu
können. In dieser ISR, nach Übertragung aller Bytes deaktivierst du den
SPI Interrupt und setzt den SS Pin kurz auf Low und gleich wieder auf
High. Solange SS auf Low ist wird der aktuelle Kontext der Register an
deren Ausgängen angezeigt, sprich dein LED Muster. Wenn SS auf Low geht
so werden einerseits die Ausgänge auf High-Z gesetzt, die LEDs gehen
alle aus, und andererseits werden die vorher übertragenen Bytes in die
Storageregister der HC595 übernommen. Dann geht SS wieder auf High und
deine LEDs leuchten im neuen Muster.

Gruß Hagen

von TobyTetzi (Gast)


Lesenswert?

Hallo Hagen,

das hört sich ja gut an, aber wie sieht so eine C Routine nun aus?

Anschließen wollte ich die HCs wie bei der Microcontroller.net
Porterweiterung, dachte ich.

Gruß Toby

von TobyTetzi (Gast)


Lesenswert?

Hier nochmals der Link,
mit dem Schaltplan, so wie ich es verdrahten wollte.

http://www.mikrocontroller.net/wiki/Porterweiterung_mit_SPI

Spricht irgendwas dagegen?

Gruß Toby

von Hagen (Gast)


Angehängte Dateien:

Lesenswert?

Würde ich so nicht anschliesen, da gerade die Fähigkeit die
Shiftregister zu befüllen OHNE das sofort deren Inhalt an die Ausgänge
gelangt, verloren geht. In dieser Beschaltung muß man so lange man die
neuen Daten reinschiebt Enable auf Low setzen, sprich so lange man die
neuen Daten reinschiebt leuchten die LEDs nicht mehr. Oder aber man
würde Enable permanent auf High lassen, aber dann würde man bei
langsammen Takt zusehen können wie man langsame die Shiftregister
durchschiebt.

Schließe sie so an wie im Anhang. An CLOCK der SPI Takt, an DATA den
Datenausgang des SPI und ENABLE an den SS Pin des AVR's. ENABLE muß
auf High stehen damit deine LEDs leuchten. Wird Enable kurzzeitige auf
Low gesetzt so passieren zwei Dinge. 1.) die Ausgänge werden
deaktiviert, auf HighZ, und 2.) werden die Daten der Shiftregister in
die intenrenen Speicherregister übernommen. Danach wird Enable wieder
auf High gesetzt und nun werden die Ausgänge entsprechend der
Speicherregister angesteuert, sprich deine LEDs leuchten im neuen
Muster. Solange nun ENABLE auf High ist kannst du über DATA und CLOCK
die internen Shiftregister mit neuen Daten füllen OHNE das dies
sofortige Auswirkungen auf deine LEDs hat. Somit leuchten deine LEDs im
aktuellen Muster und denoch kannst du im Hintergrung die neuen Daten
senden. Erst wenn diese komplette über DATA/CLOCK gesendet wurden wird
ENABLE wiederum kurz von High nach Low nach Highgepulst,und schon
leuchten die nächste Zeit die LEDs im neuen Muster.

Dies geht mit der Beschaltung aus dem Wiki nicht. Dort müsste man
entwerder ENABLE auf Low setzen und somit alle LEDs aus, solange man
Daten sendet, oder aber man sähe sofort bei jedem CLOCK die neuen Daten
an den Ausgängen. D.h. die Vorteile der 74*595 Chips werden nicht
genutzt.

Falls ich mit diesen Ausssagen absolut falsch liegen sollte so wäre es
schön wenn einer mich darauf hinweist, bin ja kein Profi-Elektroniker
;)

Gruß Hagen

von Hagen (Gast)


Lesenswert?

Achso, Philips wird nur mit einem L geschrieben, habe ich im Schemata
falsch geschrieben (halt quick&dirty).

Gruß Hagen

von Hagen (Gast)


Lesenswert?

Shit natürlich wieder mal falsch erklärt. Enable ist High Aktive, also H
Pegel auf Enable setzt die Ausgäng auf Tristate und überträgt die
Shiftregister in die Storageregister. Low schaltet dann die Ausgänge
mit dem neuen Muster aktiv. Also umgekehrt, aber ist auch schon ne
Weile her das ich damit zu tun hatte.

Gruß Hagen

von Hagen (Gast)


Lesenswert?

Achso, mit der Beschaltung wie ich sie nutze hast du einen zusätzlichen
Vorteil für deine Propeller Clock. Du kannst über Enable deine LEDs
sehr einfach alle ausschalten. Dies ist ja für dich sinnvoll um exakte
Dunkelphasen zwischen deinen Pixeln zu erreichen.
Dazu einfach ENABLE auf High legen. Dann überträgst du deine neuen
Pixel und setzt danach ENABLE auf Low. Nachdem die Leuchtphase der
Pixelzeile vorrüber ist wieder ENABLE aug High, usw.usw.
Somit kannst du ganz gezielt die Leuchtdauer aller LEDs beeinflussen.

Dies geht mit der Schaltung im Wiki nicht ohne das man OE von GND
lösst.

Gruß Hagen

von TobyTetzi (Gast)


Lesenswert?

Hallo Hagen,

vielen Dank für die ausfürliche Hardware Lösung, macht echt Sinn !

Ich habe mittlerweile auch eine Ordentliche Lösung für meine
"Propeller Uhr" in C geschrieben.
Der Erstflug mit 2 Mega16 (der vielen Port Pins wegen),
war auch schon erfolgreich.

Ich habe mit 24 LEDs pro Blatt gearbeitet.
mit 16 Leds habe ich innen einen stehenden Stern,
und mit den aüßeren 8 Leds ein Flugzeug, welches außen drum fliegt
dargestellt.
Es sah schon recht nett aus.

Nun wollte ich aber statt 24 doch 32 LEDs nutzen, diese mit HCs
ansteuern.
Somit habe ich wenige Leitungen durchs Blatt durch, und ich überlaste
den Prozessor nicht so.(24x 40mAh ist schon recht viel)
Desweiteren kann ich einen "kleineren" MC nehmen, da ich ja nur noch
die SPI Pins brauche.

Ich würde mich allerdings weiterhin über ein Codebeispiel in C
sehr freuen.

Gruß Toby

von Hagen (Gast)


Lesenswert?

Ich habe sie damals in Assembler angesteuert, aber es ist echt nicht
schwierig. Beim SPI musst du fast nichts einstellen, einfach nur SPI
aktivieren und SPI-ISR einschalten. Dann sendest du das 1 Byte,und den
Rest sendest du in der ISR. Wenn dann alle Bytes pro LED Zeile
versendet wurden, wird die ISR deaktiviert und der SS Pin von Low nach
High und wieder nach Low gesetzt. Schon leuchtet das neue Muster auf
den LEDs.

Nebenbei: wie schließt du deine LEDs an die HC595 an ? Nutzt du
Treibertransistoren und Vorwiederstände ?

Gruß Hagen

von Dirk (Gast)


Lesenswert?

Hi,

wenn man auf zusaetzliche Treiber verzichten moechte kann man den
"stpic6c595" nehmen. Er wird genauso angesteuert wie der 74HC595 hat
bloss den Vorteil Treiber zubeinhalten.


Mfg

Dirk

von TobyTetzi (Gast)


Lesenswert?

Ich hatte eigentlich vor, nur Wiederstände zu nutzen.
Aber wenns sein muß setze ich noch ULN2803 ein.

Geuß Toby

von Hagen (Gast)


Lesenswert?

@Dirk, danke für diesen Tipp. Der STP16CL596, ein 16 Bit Serial In
Parallel Out Constant Current Shift Register ist ja noch viel
interessanter. Man benötigt dann ja nur noch 1 externen Widerstand um
die Stromstärke der LEDs einzustellen und kann die 16 LEDs direkt
anschließen.

Fragt sich nur noch wo einkaufen als Amateur.

Gruß Hagen

von Hagen (Gast)


Lesenswert?

@Toby, 8mA pro LED sind ein bischen wenig, mehr kannst du nicht
verlangen von einem Standad HC595.

Gruß Hagen

von TobyTetzi (Gast)


Lesenswert?

Hagen,
aber gegen die ULN2803 spricht nichts, oder?

Dirk, wo bekommt man diese Schieberegister?

Gruß Toby

von Dirk (Gast)


Lesenswert?

Hi,

hab mir ein paar per Sample von TI kommen lassen.

Mfg

Dirk

von Hagen (Gast)


Lesenswert?

@Dirk, ich hatte auch schon bei TI nach einem Vergleichstyp zum
STP*CL596 gesucht, leider finde ich da keinen. Auf alle Fälle scheinen
die TI Teile besser lieferbar zu sein.

@Toby: Was soll dagegen sprechen. In meinem Falle habe ich das Problem
das die LEDs mit der Kathode an die Ausgänge müssen. ULN und obige
Register fallen somit aus.

Gruß Hagen

von Hagen (Gast)


Lesenswert?

Falsch, ich muss mit der Anode an die Ausgänge, deshalb kann ich keinen
ULN nehmen. Mann, es ist viel zu heiß heute ;)

Gruß Hagen

von TobyTetzi (Gast)


Angehängte Dateien:

Lesenswert?

Hallo allesamt !

Ich habe nun mal ein Wenig rumgebastelt, und siehe da, es klappt
-fast.

Ich habe den HC595 so angeschlossen, wie Hagen es sagte,
allerdings bin ich der Meinung, das man auch den G enable auf GND
lassen kann.
schiebt man dann die Daten in die Shiftregister, werden die
Daten ja erst sichtbar, wenn man per RCK high die Shiftregister in die
Storageregister übernimmt.
Einziger Nachteil ist dabei, das man eine Dunkelphase nur erreicht,
wenn man den G enable von GND löst, und kurz auf High legt,
oder nur Nullen in die Schiftregister schiebt.
Aber die Verdratung hängt auch immer vom Einsatzzweck ab!

Nun ja, ich hatte den HC halt schon so fertig, wie Hagen es beschrieben
hat !

Das einzigste Problem in meinem Programm ist:
Die erste Position nach einem Reset ist nicht definiert.
Eigentlich sollte pos auf 0 stehen, tuts auch.
Nur wird nicht der richtige Wert ins Schieberegister geschoben.
Schreibe ich statt der 0x01 eine 0xFF wird trotz allen eine 01
oder irgendwelche anderen Werte angezeigt.
Beim zweiten Durchlauf gehts dann alles einwandfrei.
Macht man dann wieder einen Reset, ist die Erste Position wieder
Falsch.

Woran das nun wieder leigt?!    HILFE !!!

Anliegend ist mein Programm.
Ich wäre über jeden Tipp dankbar! Vielleicht sollte man es optimieren?

Gruß Toby,
Großen Dank an Hagen!

von Hagen (Gast)


Lesenswert?

Haste mal mit der SPI Taktflanke experimentiert -> CPOL etc. ?

Gruß Hagen

von TobyTetzi (Gast)


Lesenswert?

Hallo Hagen,

nein, hab ich noch nicht, werd dann aber berichten!
Ich dachte schon daran, das evtl. nach einem Reset in dem SPRD Register
noch alte Daten stehen könnten?!
Daher wollte ich beim Reset dieses Register einmal mit einem Dummy
laden?!

Allerdings hab ich einen Fehler, bzw. eine Anzeige verschiebung um eie
Position in dem Propeller Programm von Perter Degender entdeckt.
Dies könnte der Fehler sein, warum bei 60 (360) Positionen eine fehlt!

Nach dem Ext. Int. wird die berechnung der Spaltenzeit ausgeführt.
Danach wird der Timer zurückgesetzt, und das Programm läuft bis zum
ersten Compare weiter.
D.h. es wird ein Grad nach dem Ext.Int. erst die pos Null angezeigt!
Man müßte also ein Flag nutzen, welches in der Endlosschleife abgefragt
wird.
Man setzt es im Compare Int. und führt dann die Anzeige der Spalte aus.
Danach löscht man das Flag wieder.
Erstens ist man so schneller aus der Compare ISR raus, des weiteren
kann man das Flag direkt nach der Berechnung setzen, und es wird sofort
die pos null angezeigt.

Falls ich damit Falsch liege, bitte um Berichtigung.

Gruß Toby

von TobyTetzi (Gast)


Angehängte Dateien:

Lesenswert?

Hallo alle,
Hallo Hagen !

Ich habe nun alle 4 SPI Modes auprobiert.

Es ändert sich bei drei Modes nichts.
Bei einem, welcher?! Ich glaube Mode 1 oder 2, wird ständig was
Falsches angezeigt.

Mein Problem besteht weiterhin:
Nach der Programmierung auf dem STK500 startet der AVR.
Das Programm startet. Pos0 wird richtig angezeigt.
Drücke ich nun den Reset auf dem STK, ist pos0 undefiniert!
Auch wenn ich den Strom ab und wieder an stelle.
Nach dem ersten Durchlauf stimmt pos0 immer.

Auch wenn ich als Dummy beim Reset 0x00 ins SPDR Register lade,
ändert sich nichts.

Anliegend das Programm mit dem 4 SPI Modes.

Ach, ich lade zum Daten übernehmen (Rck) PortB mit 0xFF,
zum enable (G) den PortB mit 0x00.
Mein Rck und G sind ja auf PB2 (SS Pin),
lade ich nun PortB mit 0x04 und danach wieder mit 0x00
geht seltsamer weise gar nichts, ist das nun ein Denkfehler von mir,
oder stimmt da was nicht?!

Gruß Toby

von TobyTetzi (Gast)


Angehängte Dateien:

Lesenswert?

Hallo Nochmal,

ich habe einen Fehler gefunden!

da ich beim Reset PORTB mit 0xFF und DDRB mit 0x00 geladen habe,
waren alle Pins als Ausgang und alle High.
Damit bekam das HC595 schon einen Falschen Wert.
Anliegend die aktuelle Version.
Nun wird pos 0 immer richtig angezeigt!

Weiterhin würde ich aber gerne wissen, wie ich nur PB2 High und wieder
Low setzen kann.

Gruß Toby

von Hagen (Gast)


Lesenswert?

PinActive = 0 oder 1

PORTB = (PORTB & ~(1 << PB2)) | (PinActive << PB2);

Pin PB2 auf 0

PORTB &= ~(1 << PB2); --> WinAVR gcc macht cbi(PORTB, PB2)

Pin PB2 auf 1

PORTB |= (1 << PB2); --> WinAVR gcc macht sbi(PORTB, PB2)

Pin PB2 toggeln

PORTB ^= (1 << PB2);

Gruß hagen

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.