PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Portexpander mit Schieberegister 4094



pete1612
09.01.2012, 11:41
Hallo!
Hab mich jetzt zum ersten Mal an den SPI-Bus getraut.
Ich habe eine Porterweiterung mit 3 Schieberegistern 4094 aufgebaut.
Die Programmierung der ersten beiden Schieberegister klappte wunderbar!
Als ich das dritrte Schieberegister eingefügt habe, erscheinen alle Ausgänge, die auf den Expander 3 geschrieben werden auf dem Expander 1 und umgekehrt.
Ich habe vieles probiert =9 nichts klappt. Bitte helft mir =)
Danke

Hier ein Programmausschnitt:

Config Spi = Hard , Interrupt = On , Master = Yes , Clockrate = 16
Spiinit
Enable Spi
....
Do
....
....
Expander1 = Low(speicherwort)
Expander2 = High(speicherwort)
.....
.....
Expander3 = 0

Spiout Expander1 , 1
Spiout Expander2 , 2
Spiout Expander3 , 3

Loop


habe den Expander 3 schon extra auf null gesetzt, trotzdem erscheinen die Ausgänge wie auf Expander 1.
Die Expander1 und 2 sind natürlich als Bytes deklariert und im Programm bekommen sie ihre Wertzuweisung aus einem Word.
hat wunderbar geklappt. Aber warum erscheint der erste auf dem dritten Expander?????

pete1612
09.01.2012, 12:32
Die Schaltung habe ich aus diesem Tutorial =)

http://www.rn-wissen.de/index.php/Portexpander_am_AVR

Nur halt aufgebaut mit einem 4094!

MagicWSmoke
09.01.2012, 13:25
Spiout() erwartet als zweiten Parameter die Anzahl der zu sendenden Bytes, da muss also jeweils 1 hin und nicht 2 oder 3.
Kannst Dir doch selbst denken, dass Du keine 2 oder 3 Bytes schicken kannst, wenn die Variable nur 1 Byte enthält.

pete1612
09.01.2012, 14:07
okay, aber wie kann ich es realisieren, dass der expander 1 das byte expander1, der expander 2 das byte expander2 , usw. erhält. wenn ich alle auf eins setze, bekommen doch alle expander die selben daten, oder??

PicNick
09.01.2012, 14:18
Wenn die Expander in serie (1, 2, 3) geschaltet sind, musst du (z.B)


DIM Expander1 as Byte ' daten für expander 1
DIM Expander2 as Byte ' daten für expander 2
DIM Expander3 as Byte ' daten für expander 3


spiout Expander3, 1 ' exp3 daten im expander 1
spiout Expander2, 1 ' exp2 daten im expander 1 ==> exp3 daten im expander 2
spiout Expander1, 1 ' exp1 daten im expander 1 ==> exp2 daten im expander 1 ==> exp3 daten im expander 3

MagicWSmoke
09.01.2012, 14:19
bekommen doch alle expander die selben daten, oder??
Nein. die werden durchgeschoben, vorausgesetzt die Verschaltung ist wie im verlinkten Bild.

Jeweils QH* des vorigen geht in SER des nächsten Bausteins, wenn 3 x 1 Byte geschoben wurde, so hat jeder Baustein seine Daten.
Ggf. solltest Du die zu sendenden Daten in ein Array aus 3 Elementen packen und auf einmal versenden, also:

Dim myArr(3) As Byte
' ... Array füllen
Spiout myArr(1), 3

PicNick
09.01.2012, 14:22
@MagicWSmoke: oops, sry

MagicWSmoke
09.01.2012, 14:25
@MagicWSmoke: oops, sry
Warum ?

Weil schneller ? Kein Problem ;-)

pete1612
09.01.2012, 14:40
okay, danke =) dann werde ich das heute abend mal ausprobieren.
das heißt, die bytes werden praktisch von hinten nach vorne in die expander geschoben.
also das letzte byte zuerst.
gut =)
und den strobe macht das programm dann bei jedem loop? oder wie setzten sich die register wieder auf 0?

PicNick
09.01.2012, 14:48
Den RCK-Strobe kriegen alle Expander gleichzeitig. (nach dem letzen der 3 SPIOUT's)
Auf Null musst du die Expander "manuell" setzen, d.h. lauter 0-en reinschieben.

pete1612
09.01.2012, 23:22
DIM Expander1 as Byte ' daten für expander 1
DIM Expander2 as Byte ' daten für expander 2
DIM Expander3 as Byte ' daten für expander 3


spiout Expander3, 1 ' exp3 daten im expander 1
spiout Expander2, 1 ' exp2 daten im expander 1 ==> exp3 daten im expander 2
spiout Expander1, 1 ' exp1 daten im expander 1 ==> exp2 daten im expander 1 ==> exp3 daten im expander 3
[/QUOTE]

Habe das probiert....
Wenn ich das so in meinen µC lade, dann habe ich auf allen drei Expandern das selbe Byte.
Wenn ich nur zwei expander betrieibe und dann

spiout expander1 , 1
spiout expander2 ,2

im code schreibe, erscheinen alle bits richtig auf den beiden expandern.

bei
spiout expander1 , 1
spiout expander2 , 2
spiout expander3 , 3

geben die ersten beiden expander die richtigen bytes und der dritte zeigt mir das byte vom ersten expander.
wieso ist das so?

PicNick
10.01.2012, 08:52
Wenn die 4094-er richtig in serie geschaltet sind, ist der Effekt sehr seltsam.
Ich denk, du must dein komplettes Programm herzeigen, da ist irgendwo der Wurm drin

pete1612
10.01.2012, 09:03
okay =)
kein Problem... der Code ist noch nicht fertig, daher sind einige deklarierte Variablen noch "unbenutzt" , nicht wundern =)
Außerdem wird das Projekt später auf einem Mega32 laufen, das tut aber jetzt nichts zur Sache.
los gehts:



$regfile = "m8def.dat"
$crystal = 16000000
Baud = 19200

Config Adc = Single , Prescaler = Auto
Start Adc

Config Spi = Hard , Interrupt = On , Master = Yes , Clockrate = 16
Enable Spi
Spiinit

Dim Eingangswort As Word
Dim Speicherwort As Word
Dim Analogwert1 As Word
Dim Analogwert2 As Word
Dim Analogwert3 As Word
Dim Takt As Byte
Dim Takt2 As Word
Dim Takt3 As Word
Dim Takt4 As Word
Dim Takt5 As Word
Dim Folge As Byte
Dim Sensortyp As Byte
Dim Freigeben As Bit
Dim Eingerichtet As Bit
Dim Puls As Bit
Dim Puls2 As Bit
Dim Zweihandimpuls As Bit
Dim Einganga As Byte
Dim Eingangb As Byte
Dim Eingangc As Byte
Dim Expander1 As Byte
Dim Expander2 As Byte
Dim Expander3 As Byte

Config Pind.0 = Input
Config Pind.1 = Input
Config Pind.2 = Input
Config Pinc.3 = Input
Config Pinc.2 = Input
Config Portd.6 = Output
Config Portd.7 = Output
Config Portb.0 = Output
Config Portc.4 = Output

Sensor1a Alias Pind.0
Sensor1c Alias Pind.1
Sensor1b Alias Pind.2
Sensor1d Alias Pind.3
Einrichten Alias Pinc.3
Zweihand Alias Pinc.2
Status1 Alias Portd.6
Status2 Alias Portd.7
Status3 Alias Portb.0
Freigabe Alias Portc.4
Portd.0 = 1
Portd.1 = 1
Portd.2 = 1
Portd.3 = 1
Portc.3 = 1
Portc.2 = 1

Const Sensora1 = 0
Const Sensora2 = 1
Const Sensora3 = 2
Const Sensora4 = 3
Const Sensora5 = 4
Const Sensora6 = 5
Const Sensorb1 = 10
Const Sensorb2 = 11
Const Sensorb3 = 12
Const Sensorb4 = 13
Const Sensorc1 = 6
Const Sensorc2 = 7
Const Sensorc3 = 8
Const Sensorc4 = 9
Const Sensord1 = 14
Const Sensord2 = 15
Const Extrafreigabe = 15
Const Sensorabcd = 0
Const Sensorcaus = 1

Do

Analogwert3 = Getadc(5)
Analogwert3 = Analogwert3 * 20
Analogwert2 = 250
Analogwert1 = 20000

If Zweihand = 1 Then
Takt3 = 0
Takt4 = 0
Takt5 = 0
Reset Zweihandimpuls
Reset Freigabe
Reset Folge.sensorabcd
Reset Folge.sensorcaus
If Einrichten = 1 Then
Expander1 = 0
Expander2 = 0
End If
End If

For Takt = 0 To Sensortyp
Incr Takt2

Select Case Takt2
Case 3000 : Set Puls
Case 5500 : Set Puls2
Case 6000 : Reset Puls
Case 6100 : Reset Puls2
Case 6200 : Takt2 = 0
End Select

If Folge.sensorabcd = 1 Then
Sensortyp = 15
Else
Sensortyp = 9
End If

If Eingerichtet = 0 Then Debounce Einrichten , 1 , Einrichtstatus , Sub

If Einrichten = 0 Then
Reset Freigabe
Reset Zweihandimpuls
Reset Eingerichtet
Expander1 = Low(speicherwort)
Expander2 = High(speicherwort)
Debounce Sensor1a , 0 , Aktiv1a , Sub
Debounce Sensor1b , 0 , Aktiv1b , Sub
Debounce Sensor1c , 0 , Aktiv1c , Sub
Debounce Sensor1d , 0 , Aktiv1d , Sub
Else
Debounce Zweihand , 0 , Zweihandaktiv , Sub
If Zweihand = 0 And Freigeben = 1 And Takt3 > Analogwert1 Then Set Folge.sensorabcd
End If

If Takt = 0 Then Set Freigeben

Eingangswort.sensora1 = Not Sensor1a
Eingangswort.sensorb1 = Not Sensor1b
Eingangswort.sensorc1 = Not Sensor1c

If Einrichten = 1 Then
If Zweihand = 0 And Freigabe = 1 And Folge.sensorcaus = 0 Then Incr Takt5
If Takt5 > Analogwert3 Or Folge.sensorcaus = 1 Then
Set Folge.sensorcaus
Eingangswort.sensorc1 = Speicherwort.sensorc1
Eingangswort.sensorc2 = Speicherwort.sensorc2
Eingangswort.sensorc3 = Speicherwort.sensorc3
Eingangswort.sensorc4 = Speicherwort.sensorc4
End If
If Eingangswort.takt < Speicherwort.takt Then Incr Takt4
If Zweihand = 0 And Takt4 > Analogwert2 Then Reset Freigeben
If Freigeben = 1 Then Incr Takt3
If Zweihand = 0 And Folge.sensorabcd = 0 Then
Expander1 = Low(speicherwort)
Expander1 = High(speicherwort)
Reset Expander2.2
Reset Expander2.3
Reset Expander2.4
Reset Expander2.5
End If
If Zweihand = 0 And Folge.sensorabcd = 1 Then
Expander1 = Low(speicherwort)
Expander2 = High(speicherwort)
End If
If Zweihand = 0 And Folge.sensorcaus = 1 Then
Reset Expander1.6
Reset Expander1.7
Reset Expander2.0
Reset Expander2.1
End If
End If

If Takt = Sensortyp And Einrichten = 1 And Zweihand = 0 Then
Freigabe = Freigeben
End If

Spiout Expander3 , 1
Spiout Expander2 , 1
Spiout Expander1 , 1

Status1 = Folge.sensorabcd
Status2 = Folge.sensorcaus

Next
Loop

End

Einrichtstatus:
Expander1 = 0
Expander2 = 0
Set Eingerichtet
Return

Zweihandaktiv:
Set Zweihandimpuls
Return

Aktiv1a:
If Speicherwort.sensora1 = 0 Then
Set Speicherwort.sensora1
Else
Reset Speicherwort.sensora1
End If
Return

Aktiv1b:
If Speicherwort.sensorb1 = 0 Then
Set Speicherwort.sensorb1
Else
Reset Speicherwort.sensorb1
End If
Return

Aktiv1c:
If Speicherwort.sensorc1 = 0 Then
Set Speicherwort.sensorc1
Else
Reset Speicherwort.sensorc1
End If
Return

Aktiv1d:
If Speicherwort.sensord1 = 0 Then
Set Speicherwort.sensord1
Else
Reset Speicherwort.sensord1
End If
Return

MagicWSmoke
10.01.2012, 09:06
wieso ist das so?
Mit dem gezeigten Code, bzw. der Variablendimensionierung bezweifle ich, dass das überhaupt "so" ist.
Wenn Du nur ein Byte hast, kannst Du keine 3 Bytes schicken, bzw. Du kannst es versuchen und wirst scheitern. Schrieb ich bereits.

Wenn die Variablen in der gezeigten Reihenfolge dimensioniert sind:

DIM Expander1 as Byte
DIM Expander2 as Byte
DIM Expander3 as Byte
dann führt das hier:

spiout expander3 , 3
dazu, dass als erstes das Byte Expander3, als nächstes aber noch 2 nachfolgende Bytes aus dem Speicher rausgeschoben werden. Nach dem Expander3-Byte kommen aber keine weiteren sinnvollen Daten, zumindest nach den gezeigten Codefetzen zu urteilen. Du schreibst also Datenmüll in die Schieberegister.

Wenn man Datenmüll in die Register schreibt, wird aber ganz sicher nicht das hier passieren:

geben die ersten beiden expander die richtigen bytes und der dritte zeigt mir das byte vom ersten expander.
Wie PicNick schrieb, zeig vollständigen und compilierbaren Code, sonst ist das ein Stochern im Nebel. Eine Beschreibung der der Verbindungen 4094 untereinander/mit dem µC, bzw. ein Schaltplan wie die 4094 tatsächlich angeschlossen sind, würde sicher auch weiterhelfen

pete1612
10.01.2012, 09:16
@MagicWSmoke:
Das mit den 3 Bytes habe ich verstanden. Das war einfach Unwissenheit von mir und ein wenig naiv zu glauben, dass es klappt. Bin halt ganz frisch in der SPI-Welt =)
Danke, trotzdem.
Das es so ist, wie ich es beschrieben habe, kannst du mir glauben. Die ganze Zeit habe ich überlegt, wieso das Byte, das an Expander1 ansteht auch an Expander3 auftaucht. Eine sinnvolle Erklärung dazu habe ich auch nicht, sonst hätte ich weniger Probleme eine Lösung zu finden.
Ersteinmal danke ich euch, dass ihr mir bei meinem Problem helft. Das ist nicht selbstverständlich! Danke.
Ich werde mal schnell einen Schaltplan von meiner 4094-er Verschaltung anfertigen....

MagicWSmoke
10.01.2012, 09:37
An Deiner Stelle würde ich den Code auf ein Minimum reduzieren, also die reine SPI-Ausgabe mit einem Delay danach. Sonst kannst Du Seiteneffekte aus dem anderen Code nicht ausschließen. Auch würde ich über ein vernünftiges Einrücken nachdenken, der Code ist im Moment unübersichtlich.
Du brauchst auch kein Interrupt = On und Enable SPI, da Du keinen Interrupt verwendest. Und eine Stack- und Framedefinition im Code wär' sinnvoll.
Teste das dann mal in dieser Weise:

' ...
Dim Expdr(3) As Byte
Expdr(1) = &b10101010
Expdr(2) = &b11110000
Expdr(3) = &b00001111

Do
Spiout Expdr(1) , 3
' ...

pete1612
10.01.2012, 09:38
Hier der Schaltplan:
21134

MagicWSmoke
10.01.2012, 09:55
Warum Q'S ?
Laut DB:

The output of the last stage (QS) can be used to cascade several devices.

PicNick
10.01.2012, 09:56
Wirklich Pete, mach das, was @MagicWSmoke vorschlägt. Die Inhalte der Expanderbytes sind ja von einer Menge Code abhängig, und nur dann vorhersagbar, wenn das alles auch fehlerfrei ist.

Folgendes ist aufgefallen:


If Zweihand = 0 And Folge.sensorabcd = 0 Then
Expander1 = Low(speicherwort) ' ZEILE 157
Expander1 = High(speicherwort) ' ZEILE 158
Reset Expander2.2
...

zweimal Expander1 ?

Expander3 wird nicht gesetzt, ist also offenbar immer NULL. heisst das bei dir, DIe LED's leuchten oder sind sie da finster ?

Ich hab nach den 3 SPIOUT kein Strobe gesehen ?

PicNick
10.01.2012, 10:06
Warum Q'S ?

Beim Zeus, da hat der Mann recht. Auf diese Art ist Müll gesichert. Du musst QS nehmen

MagicWSmoke
10.01.2012, 10:11
PicNick,

Der eigentliche Output Q8 ist ja NACH den Latches, kann man zum Kaskadieren also nicht brauchen ?
meinst Du mich ?
Nicht Q8, sondern QS, aber ohne Apostroph.
Edit:
Zu langsam...

pete1612
10.01.2012, 10:31
So, habe mal den Code so geschrieben wie es smoke mir vorgegeben hat... habe an jedes register 8 leds gehangen... nichts passiert.... diesmal gar nichts...
habe auch QS genommen, was ich auch vorher schon versucht hatte, bevor ich mich an das Forum gewandt habe...
wie mache ich den strobe??
es ist zum verzweifeln, habe auch noch zweimal meine verdrahtung überprüft...... alles okay....

MagicWSmoke
10.01.2012, 10:40
So, habe mal den Code so geschrieben wie es smoke mir vorgegeben hat...
Poste den Code, damit man den kontrollieren kann.

wie mache ich den strobe??
Wird über den SS-Pin von Spiout selbst gemacht.
Ansonsten Soft-SPI verwenden, das bisserl Bitgeschubse könnte man auch noch "zu Fuss" erledigen.

pete1612
10.01.2012, 10:44
Ich nehm alles zurück!
Klappt jetzt... programmiere in bascom und lade das Programm über avr studio in den Controller. Hab ein neues Programm in Bascom geschrieben und unter einem neuen Namen gespeichert.
Musste dann natürlich noch das richtige HEX-File auswählen in AVR-Studio. MagicWSmoke's Programm läuft... Danke.
Allerdings erscheinen die Bytes genau verkehrt herum. Expander3 hat Expander1 sein Byte.... Aber Hauptsache es geht jetzt so ersteinmal...Das krieg ich auch noch raus =)
Wie mache ich denn einen Strobe??

pete1612
10.01.2012, 10:46
Wie mache ich denn einen Strobe??

Wird über den SS-Pin von Spiout selbst gemacht.

Alles klar. Danke!
Versuche das jetzt mal in mein Hauptprogramm zu übernehmen....
Vielen Dank für Eure Hilfe!!

MagicWSmoke
10.01.2012, 10:53
Allerdings erscheinen die Bytes genau verkehrt herum. Expander3 hat Expander1 sein Byte....
Wenn man die Array-Version nimmt, dann wandert Array(1) zuerst raus. Infolge der Schieberei befindet sich das erste Byte nachher im letzten, hier also dritten 4094 der Kette.
Poste dennoch Dein funktionierendes Testprogramm, damit auch nachfolgende Leser was davon haben.

pete1612
10.01.2012, 11:04
Okay, das hattet ihr mir ja erklärt =)
Ich danke Euch noch einmal vielmals! Versuche das heute Nacht nach der Arbeit einmal in mein Projekt zu übernehmen!!

Hier der funktionierende Codeschnipsel:

$regfile = "m8def.dat"
$crystal = 16000000
$hwstack = 32
$swstack = 10
$framesize = 40
Baud = 19200

Config Spi = Hard , Master = Yes , Clockrate = 16
Spiinit

Dim Expander(3) As Byte
Expander(1) = &B10101010
Expander(2) = &B01010101
Expander(3) = &B00110011

Do
Spiout Expander(1) , 3
Delay
Loop
End

pete1612
10.01.2012, 12:31
Kurzes Update, bzw. Themenabschluss:
Ich habe jetzt ein Array in mein Programm integriert, welches die drei Bytes der Portexpander erfasst. Nun schiebe ich über dieses Array und einen einzigen SPIOUT-Befehl meine Daten in die 4094-er.
Natürlich werden die Expander dem Array verkehrt herum zugewiesen, so dass sie dann richtigherum an den Expandern anstehen.
Im Prinzip ist die Lösung meines Problems sehr einfach gewesen und der Programmieraufwand war ebenfalls nur minimal.
Für alle, die es interessiert, füge ich nun noch die entscheidenen Codeschnipsel bei, damit die Nächsten dieses Problem hoffentlich einfacher lösen können!
Vielen Dank für Eure Hilfe!!



$regfile = "m8def.dat"
$crystal = 16000000
$hwstack = 32
$swstack = 16
$framesize = 40
Baud = 19200
.
.
.
Config Spi = Hard , Master = Yes , Clockrate = 4
Enable Spi
Spiinit
.
.
.
Dim Expander(3) As Byte
Dim Expander1 As Byte
Dim Expander2 As Byte
Dim Expander3 As Byte
.
.
Do
.
.
Expander1 = Low(speicherwort)
Expander2 = High(speicherwort)
Expander3 = Low(eingangswort) (Den Expandern kann jeder erdenkliche Wert zugewiesen werden, der in eine Byte-Variable passt z.B. 169 oder es kann heißen Set Expander3.3 , etc.)
.
.
.
Expander(1) = Expander3 (Wie gesagt, hier wird das Pferd von hinten aufgesattelt.)
Expander(2) = Expander2
Expander(3) = Expander1

Spiout Expander(1) , 3 (Nur noch ein Spiout - Befehl. Macht das ganze auch wesentlich übersichtlicher)
.
.
Loop
End



Ich bedanke mich bei allen, die mir geholfen haben, das zu erkennen und zu verstehen!

Gruß
Peter

MagicWSmoke
10.01.2012, 12:58
Im Prinzip ...
An diesem Ausdruck sind schon ganze Königreiche zugrunde gegangen :D