Forum: Mikrocontroller und Digitale Elektronik Schieberegister Bitweise füllen


von Michael (Gast)


Lesenswert?

Hey Leute,

ich hoffe ich bin hier richtig gelandet, mit dem Thema.

Ich habe folgendes vor. Ich habe mehrere Schieberegister (CMOS 4049) 
hintereinander kaskadiert. Möchte nun diese Bitweise füllen. Also beim 
ersten übertragen der Daten wird 1 Bit übertragen, beim zweiten 
übertragen von Daten wird 1 Bit nach geschoben. Also Bit 1 und 2 bildet 
ein High.

Kann mir jemand helfen wie ich das machen kann?

Habe folgendes versucht zum einen mit Addieren von Binärzahlen also 
&B00000001 + &B00000001 und dann übertragen, klappte nicht.

Danach hab ichs versucht einfach immer wieder &B00000001 zu übertragen, 
klappte auch nicht.

Dann versuchte ich Dezimal 1 zu übertragen, klappte auch nicht.



Nun bin ich so langsam leicht am verzweifeln. Vielleicht kann mir einer 
von euch helfen. Das wichtigste ist auch, dass kein zweites 
Schieberegister nach und nach gefüllt werden soll, solange Register 1 
nicht an ist.

Falls es wen interessiert es sind 8 Register hintereinander und es 
sollen 60 LEDs angezeigt werden. Und nach dem die 60te LED angezeigt 
wurde soll nach nem Timer die Anzeigen wieder gelöscht werden.

Ich hoffe mir sagt nun niemand, ich muss ein Array erzeugen mit 60 
einzellnen Bitzahlen. Hoffe da gibt es eine einfachere Möglichkeit.



Michael

von Sunny (Gast)


Lesenswert?

Die kann man nicht bitweise füllen.Das geht nur mit I2C porterweiterung.
Ausserdem hat der 4049 keine Latch, das bedeutet wenn du die bits 
schiebst ändern sich auch die pinzustände sofort.Das würde dazu füren 
das die Leds der Reihe nach kurz aufleuchten würden bei jedem 
Schiebevorgang.

von Michael (Gast)


Lesenswert?

Da kann ich leicht wiedersprechen. Wenn ich den Strobe auf 0 setze vor 
dem Schreiben und dann wieder auf 1 Setze aktiviert er erst dann alle 
übertragenen Bits. Habe das schon mit 2 Stck. 7 Segmentanzeigen schon 
gemacht. Also er zählte mir so dann die von 0 bis auf 99 Hoch. Und das 
ohne Flackern oder so wärend der übertragung.

Alles lief einwandfrei rüber.

Nur wenn es nicht Bit weise geht, wie kann man sowas am besten machen? 
Also das man Bit 1 bis 60 nach und nach füllt. Also erst Bit 1, dann Bit 
2, dann Bit 3, usw.


Michael

von Sunny (Gast)


Lesenswert?

Ganz einfach, ein byte sind 8 bits.Also nehmen wir an, du wilst bit 3 
setzen.Du schiebs dann 00010000 und dann die Strobe high.

von Sunny (Gast)


Lesenswert?

Ich habe jetzt nachgesehen und 4049 ist überhaupt kein Schieberegister, 
sondern ein hex buffer.

von Steffen H. (avrsteffen)


Lesenswert?

Wenn du doch noch ein richtiges Schieberegister findest, dann kannst du 
dir 8 Byte im SRAM reservieren. Das sind 64Bit.

Falls dass eine Uhr werden soll, dann musst du bei jeder Änderung der 
Zeit immer wieder alle 64Bit ändern und durch alle Register schieben.

Hab auch schon eimal eine Uhr mit 7-Segment Anzeigen aus LED für Minute 
und Stunde gebaut mit einem Sekundenring drumherum. (Studiouhr)

Steffen

von Stefan (Gast)


Lesenswert?

hey,

ich wollte mal nachharken wieso man hier äußert dass es keines wäre. 
Wird doch im dem Onlineshop vom Großen C z.B. Als "speicher und 
schiebebus" definiert. Und für mich hört es sich nach schieberegister 
an. Bzw in der fachliteratur wird der Baustein 4094 auch als 
schieberegister tituliert.

Wenn das keiner wäre. Was wäre den dann einer?

Und wegen dem Bitmuster oben für die 3 muss ich wiedersprechen. Der wert 
würde wie folgt aussehen in Bascom &B00000100 für 3ten bit gesetzt und 
sonst im Binärsystem wäre 00000011 eine 3.


stefan

von Thomas P. (topla)


Lesenswert?

Stefan schrieb:
> Bzw in der fachliteratur wird der Baustein 4094 auch als
> schieberegister tituliert.

Der 4094 schon, oben war aber von einem 4049 die Rede.

> Und wegen dem Bitmuster oben für die 3 muss ich wiedersprechen. Der wert
> würde wie folgt aussehen in Bascom &B00000100 für 3ten bit gesetzt und

Ich habe keine Ahnung von Bascom, aber in der restlichen Welt werden die 
Bits ab 0 gezählt -> b00001000

Thomas

von chick (Gast)


Lesenswert?

Die Verwechslung 4094 und 4049 ist ja schon geklärt.

Ich hab aber Probleme Deine Frage zu verstehen, wo war die eigentlich:

>Möchte nun diese Bitweise füllen. Also beim
>ersten übertragen der Daten wird 1 Bit übertragen, beim zweiten
>übertragen von Daten wird 1 Bit nach geschoben. Also Bit 1 und 2 bildet
>ein High.

Warum bilden Bit 1 und Bit 2 ein High?

von Steffen H. (avrsteffen)


Lesenswert?

chick schrieb:
> Die Verwechslung 4094 und 4049 ist ja schon geklärt.
>
> Ich hab aber Probleme Deine Frage zu verstehen, wo war die eigentlich:
>
>>Möchte nun diese Bitweise füllen. Also beim
>>ersten übertragen der Daten wird 1 Bit übertragen, beim zweiten
>>übertragen von Daten wird 1 Bit nach geschoben.
Das versteh ich jetzt auch nicht ganz. Aber egal was du an 
Bitkombinationen übertragen/ändern willst, du musst immer die ganzen 
60Bit (64Bit) in die Register schieben.
 Also Bit 1 und 2 bildet
>>ein High.
>
> Warum bilden Bit 1 und Bit 2 ein High?
Er meint dass es jeweils eine '1' ist.

von Karl (Gast)


Lesenswert?

Ohne jetzt Dein Schieberegister genau zu kennen....
In Bascom könnte man in etwa so etwas programmieren (ohne Hardware-SPI):

3 Ports: SER, SCK und RCK

siehe:
http://www.mikrocontroller.net/articles/AVR-Tutorial:_Schieberegister
1
...
2
Shiftout SER, SCK, Byte_x, 0 'evtl. auch 1 oder 2, siehe BASCOM_Hilfe 
3
Shiftout SER, SCK, Byte_x-1 
4
...
5
Shiftout SER, SCK, Byte_0, 0 
6
7
RCK = 0
8
RCK = 1
9
RCK = 0
10
....

von Michael (Gast)


Lesenswert?

Danke bis hier hin.

Habe eine Lösung, die ich bei 2 Scheiberegister getestet habe und nur 
diesmal nun zumindest im Code auf 8 Register erweitert.

Und danke Stefan, joa hab mich da irgendwie vertippt, also wegen der 
Chipbezeichnung.

Den Code packe ich gleich unten dran. Den an sich gibt es leider ein 
Problem, dass meine Lösung ein wenig sehr Speicher verbraucht und dabei 
erstmal nur 1 Ring mit Sekunden anzeigt. Also wenn Minuten und Stunden 
noch hinzu kommen müsste ich bei meiner Lösung mindestens ein ATMega16 
nehmen.

Vielleicht kann mir jemand eine Lösung verraten bzw. 
Verbesserungsvorschlag für meine Lösung.


Michael

Und hier der code:
==================

$regfile = "m8def.dat"
$crystal = 9600000
$hwstack = 32
$swstack = 4
$framesize = 4



Config Portb.2 = Output
Config Portb.1 = Output
Config Portb.0 = Output

Strobe Alias Portb.2
Daten Alias Portb.1
Clock Alias Portb.0

Strobe = 0
Daten = 0
Clock = 0

Dim Dis(9) As Byte
Dim Isec As Integer
Dim Imin As Integer
Dim Ihou As Integer

Dim Csec As Integer
Dim Cmin As Integer
Dim Chou As Integer


'Bit-Muster Array
Dis(1) = &B00000001
Dis(2) = &B00000011
Dis(3) = &B00000111
Dis(4) = &B00001111
Dis(5) = &B00011111
Dis(6) = &B00111111
Dis(7) = &B01111111
Dis(8) = &B11111111
Dis(9) = &B00000000


'Schieberegister leeren beim Start
Shiftout Daten , Clock , Dis(9) , 1
Shiftout Daten , Clock , Dis(9) , 1

Shiftout Daten , Clock , Dis(9) , 1
Shiftout Daten , Clock , Dis(9) , 1

Shiftout Daten , Clock , Dis(9) , 1
Shiftout Daten , Clock , Dis(9) , 1

Shiftout Daten , Clock , Dis(9) , 1
Shiftout Daten , Clock , Dis(9) , 1
Strobe = 1

Do
Isec = 1

For Isec = 1 To 16

   Strobe = 0

     Select Case Isec

     Case 1 To 8:      'Sekundenanzeige von 1-8
         Shiftout Daten , Clock , Dis(9) , 1
         Shiftout Daten , Clock , Dis(9) , 1
         Shiftout Daten , Clock , Dis(9) , 1
         Shiftout Daten , Clock , Dis(9) , 1
         Shiftout Daten , Clock , Dis(9) , 1
         Shiftout Daten , Clock , Dis(9) , 1

         Shiftout Daten , Clock , Dis(9) , 1
         Shiftout Daten , Clock , Dis(isec) , 1


     Case 9 To 16:      'Sekundenanzeige von 9-16

         Csec = Isec - 8
         Shiftout Daten , Clock , Dis(9) , 1
         Shiftout Daten , Clock , Dis(9) , 1
         Shiftout Daten , Clock , Dis(9) , 1
         Shiftout Daten , Clock , Dis(9) , 1
         Shiftout Daten , Clock , Dis(9) , 1
         Shiftout Daten , Clock , Dis(9) , 1

         Shiftout Daten , Clock , Dis(csec) , 1
         Shiftout Daten , Clock , Dis(8) , 1

     Case 17 To 24:       'Sekundenanzeige von 17-24
         Csec = Isec - 16
         Shiftout Daten , Clock , Dis(9) , 1
         Shiftout Daten , Clock , Dis(9) , 1
         Shiftout Daten , Clock , Dis(9) , 1
         Shiftout Daten , Clock , Dis(9) , 1
         Shiftout Daten , Clock , Dis(9) , 1

         Shiftout Daten , Clock , Dis(csec) , 1
         Shiftout Daten , Clock , Dis(8) , 1
         Shiftout Daten , Clock , Dis(8) , 1

     Case 25 To 32:    'Sekundenanzeige von 25-32
         Csec = Isec - 24
         Shiftout Daten , Clock , Dis(9) , 1
         Shiftout Daten , Clock , Dis(9) , 1
         Shiftout Daten , Clock , Dis(9) , 1
         Shiftout Daten , Clock , Dis(9) , 1

         Shiftout Daten , Clock , Dis(csec) , 1
         Shiftout Daten , Clock , Dis(8) , 1
         Shiftout Daten , Clock , Dis(8) , 1
         Shiftout Daten , Clock , Dis(8) , 1

     Case 33 To 40:      'Sekundenanzeige von 33-40
         Csec = Isec - 32
         Shiftout Daten , Clock , Dis(9) , 1
         Shiftout Daten , Clock , Dis(9) , 1
         Shiftout Daten , Clock , Dis(9) , 1

         Shiftout Daten , Clock , Dis(csec) , 1
         Shiftout Daten , Clock , Dis(8) , 1
         Shiftout Daten , Clock , Dis(8) , 1
         Shiftout Daten , Clock , Dis(8) , 1
         Shiftout Daten , Clock , Dis(8) , 1

     Case 41 To 48:      'Sekundenanzeige von 41-48
         Csec = Isec - 40
         Shiftout Daten , Clock , Dis(9) , 1
         Shiftout Daten , Clock , Dis(9) , 1

         Shiftout Daten , Clock , Dis(csec) , 1
         Shiftout Daten , Clock , Dis(8) , 1
         Shiftout Daten , Clock , Dis(8) , 1
         Shiftout Daten , Clock , Dis(8) , 1
         Shiftout Daten , Clock , Dis(8) , 1
         Shiftout Daten , Clock , Dis(8) , 1

     Case 49 To 56:    'Sekundenanzeige von 49-56
         Csec = Isec - 48
         Shiftout Daten , Clock , Dis(9) , 1

         Shiftout Daten , Clock , Dis(csec) , 1
         Shiftout Daten , Clock , Dis(8) , 1
         Shiftout Daten , Clock , Dis(8) , 1
         Shiftout Daten , Clock , Dis(8) , 1
         Shiftout Daten , Clock , Dis(8) , 1
         Shiftout Daten , Clock , Dis(8) , 1
         Shiftout Daten , Clock , Dis(8) , 1

     Case 57 To 60:   'Sekundenanzeige von 57-60
         Csec = Isec - 56
         Shiftout Daten , Clock , Dis(csec) , 1
         Shiftout Daten , Clock , Dis(8) , 1
         Shiftout Daten , Clock , Dis(8) , 1
         Shiftout Daten , Clock , Dis(8) , 1
         Shiftout Daten , Clock , Dis(8) , 1
         Shiftout Daten , Clock , Dis(8) , 1
         Shiftout Daten , Clock , Dis(8) , 1
         Shiftout Daten , Clock , Dis(8) , 1

     End Select

   Strobe = 1
   Waitms 100
Next

Loop

von Karl (Gast)


Lesenswert?

Michael schrieb:
> bei meiner Lösung mindestens ein ATMega16
> nehmen.

Bei einem ATmega8 wäre doch ein ATmega328 angebrachter. Im Guloshop für 
2 Euro zu haben.

Da Du sehr oft einfach Nullen durchschiebst, kannst Du ein paar 
Shiftout-Befehle wegrationalisieren. Z.B.:
1
...
2
Dim N as DWORD
3
...
4
Shiftout Daten , Clock , N , 1, 16 'wie 2x Shiftout
5
...
6
Shiftout Daten , Clock , N , 1, 32 'wie 4x Shiftout

Funktioniert der oben angegeben Code? CASE ist bis 60 aber Isec nur 
maximal 16.

von Karl (Gast)


Lesenswert?

PS. Bei Dis(8) sollte das auch funktionieren, dann wäre N=&HFFFFFFFF

von Karl H. (kbuchegg)


Lesenswert?

> Den an sich gibt es leider ein
> Problem, dass meine Lösung ein wenig sehr Speicher verbraucht#

Das wundert mich bei dem Ansatz nicht wirklich

> und dabei
> erstmal nur 1 Ring mit Sekunden anzeigt. Also wenn Minuten und
> Stunden noch hinzu kommen müsste ich bei meiner Lösung mindestens
> ein ATMega16 nehmen.

Aber geh. Du musst das nur ein wenig intelligenter angehen!
Du wirst dir doch wohl noch Formeln ausdenken können, wieviele LED im 
jeweiligen Scheberegister leuchten müssen, wenn du bsp-weise bei Sekunde 
38 stehst. Ja! Das kann man berechnen. Und das ist noch nicht einmal 
schwer. Jeder Grundschüler im 2.ten Schuljahr kann das. Ausser 
Dividieren und Rest bei einer Division braucht man dazu nichts:

8 Kinder stehen in einer Reihe. Eine Mutter hat 38 Torten. Wieviele 
Torten kriegt jedes Kind, wenn die Mutter vorne in der Reihe anfängt und 
jedem Kind erst mal 8 Torten gibt, ehe sie zum nächsten Kind weitergeht.

Wieviele Kinder bekommen 8 Torten (also die volle Anzahl)?
  38 / 8   ->  4          die ersten 4 Kinder bekommen 8 Torten

Wieviele Torten bleiben dann noch zur Verteilung?
  38 - ( 4 * 8 )   ->  38 - 32  ->  6
                          das 5. Kind bekommt 6 Torten

Wieviele Torten kriegen die anderen Kinder?
                          keine. Die Kinder 6 bis 8 gehen leer aus.



Und schon sind deine 3 Bildschirmseiten Code auf 3 Berechnungen, 2 
FOR-Schleifen (mit einer Anweisung innerhalb der Schleife) und noch 
einer Anweisung geschrumpft. Alles in allem weniger als 15 Zeilen Code.

von Karl (Gast)


Lesenswert?

Es sollte sogar noch einfacher gehen. Wenn ich das richtig interpretiere 
und wenn mein Hirn nicht noch unter akutem Kopffeinmangel leidet, so 
müsste man doch immer nur pro Sekunde 1 Bit von 60 ändern.
1
Dim Dis as Dword
2
...
3
Do
4
5
Dis=0
6
7
For x = 0 to 59
8
   Strobe = 0
9
   Toggle Dis.x
10
   Shiftout Daten , Clock , Dis , 1
11
   Strobe = 1
12
   Waitms 100
13
Next
14
15
Loop

von Karl H. (kbuchegg)


Lesenswert?

Karl schrieb:
> Es sollte sogar noch einfacher gehen. Wenn ich das richtig interpretiere
> und wenn mein Hirn nicht noch unter akutem Kopffeinmangel leidet, so
> müsste man doch immer nur pro Sekunde 1 Bit von 60 ändern.

Du hast im Prinzip schon recht.
Ich wollte nur den Helfern von weiter oben nicht ins Handwerk pfuschen, 
die ihn auf "du musst immer alle SR neu beschreiben und dazu teilst du 
dir ..." gebracht haben.
Ausserdem schadet es nicht, wenn man sieht das Mathe dann doch zu etwas 
nütze ist.

Es gibt auch noch andere einfache Lösungen, wie man alle 60 LED auf den 
gewünschten Wert stellt, wenn man weiß, das LED 1 bis n leuchten sollen 
und man jeweils einen Komplettupdate machen will. Zb 2 For-Schleifen 
hintereinander: die erste gibt 60-n mal ein 0 Bit aus, die 2.te gibt n 
mal ein 1 Bit aus.

von Steffen H. (avrsteffen)


Lesenswert?

Karl schrieb:
> Es sollte sogar noch einfacher gehen. Wenn ich das richtig interpretiere
> und wenn mein Hirn nicht noch unter akutem Kopffeinmangel leidet, so
> müsste man doch immer nur pro Sekunde 1 Bit von 60 ändern.

Also kommt drauf an, was er anzeigen will.

Die aktuelle Sekunde als leuchtenden Punkt im Sekundenkreis?
-> dann bei der 1.Sekunde einmal eine '1' raus schieben und dann mit 
jeder Sekunde eimal eine '0' schieben

Die Sekunden als Leuchtband im Sekundenkreis?
-> dann ab der 1.Sekunde je Sekunde eine '1' raus schieben und beim 
zurücksetzen des Sekundencounters (von 60 auf 0) den Sekundenkreis durch 
60x eine '0' raus schieben löschen.

Wie das jetzt in BASCOM gelöst wird kann ich nicht beantworten.

von Peter D. (peda)


Lesenswert?

Karl Heinz Buchegger schrieb:
> Zb 2 For-Schleifen
> hintereinander: die erste gibt 60-n mal ein 0 Bit aus, die 2.te gibt n
> mal ein 1 Bit aus.

Ne, das wäre zu einfach.
Da braucht man ja nur ein Byte SRAM und ganz wenig Code.


Peter

von Karl H. (kbuchegg)


Lesenswert?

Peter Dannegger schrieb:
> Karl Heinz Buchegger schrieb:
>> Zb 2 For-Schleifen
>> hintereinander: die erste gibt 60-n mal ein 0 Bit aus, die 2.te gibt n
>> mal ein 1 Bit aus.
>
> Ne, das wäre zu einfach.
> Da braucht man ja nur ein Byte SRAM und ganz wenig Code.

Auch wieder wahr. Irgendwie muss man den 16-er ja schliesslich auch voll 
kriegen.

von Karl (Gast)


Lesenswert?

Steffen H. schrieb:
> Also kommt drauf an, was er anzeigen will.

> Die Sekunden als Leuchtband im Sekundenkreis?

Wenn ich mir den Code so ansehe, dann genau das.

In der letzten Case Anweisung werden die restlichen 4 Bits zur 1 (alle 
anderen sind es schon).

von Peter D. (peda)


Lesenswert?

Karl Heinz Buchegger schrieb:
> Zb 2 For-Schleifen
> hintereinander: die erste gibt 60-n mal ein 0 Bit aus, die 2.te gibt n
> mal ein 1 Bit aus.

In C könnte das so aussehen:
1
#include "sbit.h"
2
3
#define DOUT    PORT_B0
4
#define CLOCK   PORT_B1
5
#define STROBE  PORT_B2
6
7
8
static void shift( uint8_t n )
9
{
10
  while( n-- ){
11
    CLOCK = 0;
12
    CLOCK = 1;
13
  }
14
}
15
16
17
void display_seconds( uint8_t n )
18
{
19
  DOUT = 0;
20
  shift( 60 );
21
  DOUT = 1;
22
  shift( n );
23
  STROBE = 1;
24
  STROBE = 0;
25
}


Peter

von Michael N. (lwl2012)


Lesenswert?

So hier einmal dann eine Verkleinerte Version. Karl Heinz gab den Anstoß 
dafür und nun ist der Code nach Compilieren sogar schon unter 1kb groß. 
Wenn ich mir weiter so mühe gebe könnte ich meine ganze Uhr sogar per 
ATTiny13 gestalten, zumindest vom Speicher aus.


$regfile = "attiny13.dat"
$crystal = 9600000
$hwstack = 32
$swstack = 4
$framesize = 4



Config Portb.2 = Output
Config Portb.1 = Output
Config Portb.0 = Output

Strobe Alias Portb.2
Daten Alias Portb.1
Clock Alias Portb.0

Strobe = 0
Daten = 0
Clock = 0


Dim Dis(9) As Byte

Dim Sek_1 As Integer
Dim Sek_2 As Integer
Dim Sek_3 As Integer
Dim Sek_4 As Integer

Dim Sek_a As Integer
Dim Sek_b As Integer
Dim Sek_c As Integer



Dis(1) = &B00000001
Dis(2) = &B00000011
Dis(3) = &B00000111
Dis(4) = &B00001111
Dis(5) = &B00011111
Dis(6) = &B00111111
Dis(7) = &B01111111
Dis(8) = &B11111111
Dis(9) = &B00000000



Do
'Sekundenschleife


   For Sek_1 = 1 To 60                                      'Allgemeine 
Sekundenschleife
                                                            'Beispiel 
Sekundenangabe = Sek = 38

      Strobe = 0

      Sek_a = Sek_1 / 8                                     'Teilt die 
Sekunden / 8 -> Ergebnis in -> Sec_a

      Sek_b = 8 * Sek_a 
'Multipliziert Sec_a mit 8 -> Ergebnis in -> Sec_b

      Sek_c = Sek_1 - Sek_b                                 'Zieht Sec_b 
von Sec ab -> Ergebnis in -> Sec_c


      For Sek_2 = 0 To Sek_a                                'Füllt die 
vollen Bits auf solange bis I2 = Sec_a
         Shiftout Daten , Clock , Dis(8) , 1                'Schiebt 
Dis(8) (8-Bits) ins Schieberegister
      Next




      Shiftout Daten , Clock , Dis(sek_c) , 1               'Schiebt den 
Unvollständigen Byte in den         Schieberegister nach


      Sek_4 = Sek_a + 1                                     'Errechnet 
die Fehlenden Bytes um die 8         Schieberegister zu füllen

      For Sek_3 = Sek_4 To 8                                'Füllt 
solange leere Bytes nach bis 8 Byts (ergibt 8         Schieberegister) 
erreicht sind
         Shiftout Daten , Clock , Dis(9) , 1                'Schiebt mit 
0-Bit gefüllte Bytes in die letzten           Register
      Next

      Strobe = 1
Waitms 100
   Next

Loop

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.