Seite 2 von 3

Verfasst: 11.07.2007 17:41
von Thomas
Hey, ihr wisst doch wie es gemeint ist!
ich will keine, die extra bei meinem Programm dann dabei sein müssen!

Wo ist der Unterschied von seriell und parallel?! :cry:


Wie kann ich z.B. eine 1-Kanal-Relais-Karte aufbauen (Schaltplan)?

Kann mir mal jemand ein Code-Beispiel machen?

Verfasst: 11.07.2007 18:50
von Falko
Hier ist erst einmal eine einfache Schaltung.

http://www.franksteinberg.de/erel.htm

Entgegengesetzt der dll und LPT nimmst du dann RS232.
Da die Ansteuerung von -15 bis + 15 Volt sein darf kann man die
serielle Schnittstelle direkt anschliessen.
Dazu installierst du einmal MVCom welche keine DLL ist ! Diese Lib
mit ihren Funktionen wird dann in dein fertiges Programm compiliert.
Also keine externe Datei damit dein Programm das macht, was du willst.

Weiteres steht in der MVCom beschrieben.

LPT ohne DLL :lol: in PB , viel Spass. Wenn du dich mit Sys-Treibern
auskennst, kannst es gern versuchen. Aber dann ist schon eine DLL,
die alles bietet einfacher.

Der Unterschied der LPT und RS232, ich hoffe du hast dir mal unter Googlesuche (am besten Bilder auswählen) mal über LPT als auch über RS232 umgesehen.

RS232 arbeitet mit +-12V. LPT dagegen mit Digitallogik 0-5V.
Zusätzlich bietet die LPT ein Controllregister, Steuerregister und ein Datenregister,
welche du direkt mittels Treiber ansteuern kannst. Dazu
die DLL. Mit dem Datenregister kannst du die Datenleitungen D0 bis D7
ein bzw. ausschalten. Soweit ich weiß kann man sogar die Richtung durch
die Einstellung im Bios beeinflussen, sodas man nicht nur senden, sondern auch
empfangen kann. Am besten beschreibt es das Buch von B.Kainka,
welches ich dir aus Copyrightgründen hier nicht kopieren darf!

Einige Tips und dazu Links hatte ich hier gepostet :roll: .

MfG Falko

Verfasst: 12.07.2007 20:02
von Falko
Hallo Thomas,
hier habe ich noch was gefunden, was die RS232 mit Beispielen von Schaltungen und Sourcen anzeigt.

http://www.o-bizz.de/qbtuts/com-port/index.htm

Eine einfache Relaisschaltung direkt an Com ist dort auch als Schaltplan
angezeigt. Also mir gefallen die Sachen sehr gut. Die Programme müsste
man in PB anpassen und minimalen Änderungen anstatt der Portansteuerung
per DLL über die installierte MVCOM-Library ansprechen können,
sodass du ein einziges Programm ohne Extras hast.

Wenn du dazu noch Fragen hast im Bezug zu MVCOM-Lib die auch über
PureArea.net zu laden ist, frag ruhig.

Es wäre schöner, wenn sich noch mehr begeisterte hieran beteiligen würden. Schließlich muss hier der Thread noch richtig wachsen :wink:

[Edit]
Achja, wegen der LPT habe ich hier auch was schönes gefunden,
wie dort Relais angschlossen werden. Nur so einfach ansteuern, wie es
unter MVCOM-Library möglich ist, geht leider nicht.
Dazu ist man auf die oben besagten DLLs abhängig. Früher unter
16-Bit Basic wie Quickbasic oder GFA-Basic war es kein Problem unter
DOS als auch unter Windows 9x die Registeradressen direkt
anzusprechen, sodas man ebenfalls ein kleines Programm hatte.

Ab Windows 2000 wird es verhindert, da nun diese IO-Adressen nur noch
indirekt über DLLs (nachgemachter Systemtreiber) angesprochen werden
dürfen.
In Delphi gibt es online irgendwo ein Beispiel wie so eine DLL funktioniert.
Eigentlich ist diese DLL das, was früher die Programme direkt mit Out und Inp über Basic innerhalb der DLL ausführen, wenn das aufrufende Programm
die Funktionen der DLL anspricht. Deswegen oben der Spruch indirekter Treiber. :lol:

Hier kann man mehr darüber lesen :

http://members.inode.at/anton.zechner/az/Parallel.htm
Hier eine Beschreibung in Deutsch zur RS232 (Com)
http://www.goblack.de/desy/digitalt/ser ... index.html

[/Edit]

Gruß, Falko

Verfasst: 14.07.2007 14:48
von Thomas
Hi,
ich habe mal einen Code für eine 2-Kanal-Relaiskarte (Ausgänge am Port: DTR, RTS), die auch zwei Eingänge (DSR, CTS) hat, erstellet.
Der Code funktioniert gut (Schaut ihn aber bitte troztdem auf Fehler durch), aber mit dem Thread bin ich mir nicht ganz sicher, ob das so richig ist.
Denn diesen Befehl "KillThread(...)" soll man ja nicht verwenden; aber wie soll ich es dann machen?

Code: Alles auswählen

;{**********-Konstanten, Variablen, Strings, ...; laden von Fonts, Bildern,...-**********

;*****-Konstanten für Fenster-*****
Enumeration
  #HauptFenster
EndEnumeration
#HauptFensterWidth = 365
#HauptFensterHeight = 165
#HauptFensterFlags = #PB_Window_SystemMenu | #PB_Window_ScreenCentered | #PB_Window_MinimizeGadget

;*****-Konstanten für Gadgets-******
Enumeration
  #GadgetFrame3D1
  #GadgetFrame3D2
  #GadgetTextInput1
  #GadgetTextInput2
  #GadgetTextRelais1
  #GadgetTextRelais2
  #GadgetImageInput1
  #GadgetImageInput2
  #GadgetButtonRelais1Ein
  #GadgetButtonRelais1Aus
  #GadgetButtonRelais2Ein
  #GadgetButtonRelais2Aus
  #GadgetButtonBeenden
EndEnumeration

;*****-Konstanten für Bilder-*****
Enumeration
  #ImageInput1
  #ImageInput2
EndEnumeration

;*****-Sonstige Konstanten, Variablen, Strings, ...-******
#AnwendungName = "2 Relais-Relaiskarte"
#VersionName = "2 Relais-Relaiskarte 1.0"

Global ComPort.l
Global Thread.l

;*****-Bilder erstellen-*****
CreateImage(#ImageInput1, 30, 30)
CreateImage(#ImageInput2, 30, 30)

;}

Procedure ReChargeInputs()

  If ComGetDSR(ComPort) = 0
    If StartDrawing(ImageOutput(#ImageInput1))
        Box(0, 0, 30, 30, RGB(228, 48, 27))
      StopDrawing()
    EndIf
  Else
    If StartDrawing(ImageOutput(#ImageInput1))
        Box(0, 0, 30, 30, RGB(136, 207, 78))
      StopDrawing()
    EndIf
  EndIf

  If ComGetCTS(ComPort) = 0
    If StartDrawing(ImageOutput(#ImageInput2))
        Box(0, 0, 30, 30, RGB(228, 48, 27))
      StopDrawing()
    EndIf
  Else
    If StartDrawing(ImageOutput(#ImageInput2))
        Box(0, 0, 30, 30, RGB(136, 207, 78))
      StopDrawing()
    EndIf
  EndIf

  SetGadgetState(#GadgetImageInput1, ImageID(#ImageInput1))
  SetGadgetState(#GadgetImageInput2, ImageID(#ImageInput2))

EndProcedure

Procedure Thread()

  Repeat
    ReChargeInputs()
    Delay(250)
  ForEver

EndProcedure

Procedure HauptFenster()

  If OpenWindow(#HauptFenster, 0, 0, #HauptFensterWidth, #HauptFensterHeight, #AnwendungName, #HauptFensterFlags)

    ;{*****-Gadgets erstellen-*****
    If CreateGadgetList(WindowID(#HauptFenster))
      TextGadget(#GadgetTextInput1, 20, 20, 60, 15, "Eingang 1", #PB_Text_Center)
      ImageGadget(#GadgetImageInput1, 35, 40, 30, 30, 0, #PB_Image_Border)
      TextGadget(#GadgetTextInput2, 20, 90, 60, 15, "Eingang 2", #PB_Text_Center)
      ImageGadget(#GadgetImageInput2, 35, 110, 30, 30, 0, #PB_Image_Border)
      Frame3DGadget(#GadgetFrame3D1, 100, 15, 2, 140, "", #PB_Frame3D_Single)
      TextGadget(#GadgetTextRelais1, 130, 20, 70, 15, "Relais 1", #PB_Text_Center)
      ButtonGadget(#GadgetButtonRelais1Ein, 130, 40, 30, 30, "Ein")
      ButtonGadget(#GadgetButtonRelais1Aus, 170, 40, 30, 30, "Aus")
      TextGadget(#GadgetTextRelais2, 130, 90, 70, 15, "Relais 1", #PB_Text_Center)
      ButtonGadget(#GadgetButtonRelais2Ein, 130, 110, 30, 30, "Ein")
      ButtonGadget(#GadgetButtonRelais2Aus, 170, 110, 30, 30, "Aus")
      Frame3DGadget(#GadgetFrame3D2, 230, 15, 2, 140, "", #PB_Frame3D_Single)
      ButtonGadget(#GadgetButtonBeenden, 260, 105, 80, 35, "Beenden")
    EndIf
    ;}

    ReChargeInputs()
    Beenden_HauptFenster = 0

    Thread = CreateThread(@Thread(), 0)

    Repeat

      Event_HauptFenster = WaitWindowEvent()

      If Event_HauptFenster = #PB_Event_Gadget
        Select EventGadget()
          Case #GadgetButtonRelais1Ein
            ComSetDTR(ComPort, 1)
          Case #GadgetButtonRelais1Aus
            ComSetDTR(ComPort, 0)
          Case #GadgetButtonRelais2Ein
            ComSetRTS(ComPort, 1)
          Case #GadgetButtonRelais2Aus
            ComSetRTS(ComPort, 0)
          Case #GadgetButtonBeenden
            Beenden_HauptFenster = 1
        EndSelect
      EndIf

      If Event_HauptFenster = #PB_Event_CloseWindow
        Beenden_HauptFenster = 1
      EndIf

    Until Beenden_HauptFenster <> 0

  Else
    MessageRequester("Fehler", "Fenster konnte nicht geöffnet werden.", #MB_ICONERROR)
    End
  EndIf

  KillThread(Thread)
  CloseWindow(#HauptFenster)
  ComClose(ComPort)

  End

EndProcedure

ComPort = ComOpen("COM1: baud=9600 parity=N data=8 stop=1", #HandShakeModeNone, 0, 0)
ComSetDTR(ComPort, 0)
ComSetRTS(ComPort, 0)

HauptFenster()

Verfasst: 14.07.2007 19:47
von Falko
>>> Denn diesen Befehl "KillThread(...)" soll man ja nicht verwenden; aber wie soll ich es dann machen?

Wo steht das?

In der Hilfe steht was anderes:
Purebasic-Hilfe hat geschrieben:Wenn möglich, sollte ein Flag (z.B. eine globale Variable) verwendet werden, welcher dem Thread mitteilt, sich selbst zu beenden (und das benötigte "Aufräumen" zu erledigen). Und dieser Befehl sollte nur verwendet werden, wenn dies auf irgendwelchen Gründen nicht möglich ist.
Schließlich muss man eben wissen, solange das eigene Programm läuft,
welcher thread beendet werden soll .

Gruß Falko

Verfasst: 14.07.2007 22:32
von Thomas
Wird ein Thread automatisch bei dem Befehl "End" RICHTIG beendet?
Und wie soll ich das Problem eurer Meinung nach lösen?

Das mit dem Transistor hat sich erledigt; ich benutze einen anderen. :mrgreen:

Verfasst: 15.07.2007 00:07
von Falko
Hallo Thomas,
du kannst ja folgendes zum Thread gerne ausprobieren. Evt. mal im Taskmanager schauen, ob dein Programm korrekt beendet wird.

Gruß, Falko

Code: Alles auswählen

Procedure Beeper()
   Repeat 
   For a= 1 To 4 
     For i= 1000 To 3000 Step 500
     Beep_(i,40)
     Next i
     For i= 2000 To 1000 Step -500
     Beep_(i,40)
     Next i
   Next a
     Delay(2000)
   ForEver
EndProcedure

CreateThread(@Beeper(),0)
MessageRequester("Info", "It will beep every 3 seconds."+Chr(10)+"Click To finish the program", 0) 
End ; Beendet das Programm ordentlich, wie in der Hilfe steht.
Wegen dem Bildchen. Link und Bild sind ok, da man daraus erkennen
kann woher es kommt.

Gruß, Falko

Verfasst: 16.07.2007 11:18
von Thomas
Heißt das, dass ich nur "End" verwenden muss, um den Thread und das Programm RICHTIG zu beenden? Oder ist eine Globale Variable besser (Wie mache ich es dann?)?
Und "KillThread" sollte ich nicht verwenden?! :?

Verfasst: 16.07.2007 12:12
von Tafkadasom2k5
Wie es scheint, weißt du immer noch nicht, wo der Unterschied von Seriell zu parallel ist. Da du aber in diesem Fall eh "nur" die Handshake-Leitungen nutzt, ist es wohl egal.

Falls du wirklich am Unterschied interessiert bist, schau dir mal den Wiki-Artikel darüber an. Ansonsten muss ich mal nach meinem Referat kramekn, da ist das ganz ordentlich beschrieben.

Gr33tz
Tafkadasom2k5

Edit: habe unser altes Referat wiedergefunden. Es ist nicht ideal, aber es erklärt ganz gut mit Worten, was da eigentlich passiert. Es ist aber nich 100%ig das, was auch beim Com-Port tatsächlich passiert, da ich dort eine synchrone, serielle Übertragung beschreibe. Der Sprung zur Asynchronen ist aber nicht so schwer, und es reicht, wenn man das Prinzip erstmal verstanden hat.
Mein altes Referat hat geschrieben:Parallelbusse, wie zum Beispiel der Centronics- Parallel-Bus, den wir auch als LPT- oder
Druckeranschluss kennen, übertragen Ihre Binärcodes, wie der Name des Bustyps schon sagt, parallel. Jede Ader wird also, je nach Wert, mit einer bestimmten Spannung belegt, oder eben nicht.

So kann eine bestimmte Menge an Binärzahlen, begrenzt durch die Anzahl der Datenadern, gleichzeitig von A nach B ‚gebracht’ werden. Tatsächlich werden diese Daten nicht befördert, da ein ‚Übermitteln’ nicht zwangsläufig den Verlust dieser Daten auf der Senderseite bedeutet. Durch ein bestimmtes Signal, oder einer bestimmten Datenader, wird dem Empfänger jetzt mitgeteilt, dass die Daten jetzt vollständig und korrekt an den Eingängen anliegen. Jetzt liest der Empfänger den Signalbestand aus und interpretiert daraus die Daten. Ein Zyklus dieses Vorgangs nennt man „Takt“. Die Taktrate ist also die Anzahl dieser Vorgänge innerhalb einer Sekunde. Hertz.

Doch physikalisch gesehen trifft man mit der Datenbreite bei Parallelbussen irgendwann auf seine Grenzen: Da man nur begrenzt Material und Platz zur Verfügung hat, würden die immer breiter werdenden Busse irgendwann zu üppig. Noch viel problematischer ist aber das “Überspringen”. Wenn man einen parallelen Bus hat, welcher auf jeder Datenleitung ein Bit überträgt, und die Hertz-Zyklen dabei sehr hoch einstellt, so kann es sein, dass durch die Spannung und die hohe Frequenz ein Nebenanliegendes Kabel beeinflusst wird. Haben wir also 3 Leitungen, und nur die mittlere soll eine Binär-1 darstellen, so kann bei einer hohen Frequenz das anliegende Kabel auch zur Binär-1 interpretiert werden. Da das auf physikalischen Gesetzen beruht, ist es nur durch dickere Abschmirmung möglich, diesem entgegenzuwirken. Da der Daten und Leistungshunger der Menschen aber nie wirklich gestillt sein wird, wurde irgendwann ein anderes Kabel-System, entwickelt, welches bis heute immer weiter optimiert und ergänzt wurde: Das seriell- System. Serielle Kabel und Busse haben gegenüber Parallelbussen mittlerweile nicht nur platz- sondern auch leistungsbezogene Vorteile. Daten, die vorher über 24-adrige Kabel geschickt werden mussten, sind plötzlich auch über 4-adrige Kabel verfügbar. Durch immer schneller werdende Hardware, wie zum Beispiel Multi- und Demultiplexer und Schieberegister, werden serielle Busse auch bei zeitkritischen Anwendungen immer interessanter. Das Prinzip der binären Übertragung ist nach wie vor dasselbige. Doch wie werden so große Datenbreiten über ein so schmales Kabel geschickt?

Wir werden das Prinzip an einer synchronen seriellen Datenübertragung erklären:
Das Sendergerät legt an einem parallelen Ausgang seinen zu übertragenden Wert an. Dieser Ausgang ist mit einem so genannten Demultiplexer verbunden. Ein Demultiplexer hat (jetzt nur um die Funktionsweise zu erklären) 3 Eingänge, und einen Ausgang. Am Ersten Eingang liegt das zu übertragende, noch parallele Signal an. Am zweiten Eingang sitzt ein Binärzähler, der auf eine bestimmte Größe angepasst ist. Zum Beispiel 9 (um genau 1 Byte + Freigabebyte zu übertragen). An dem Binärzähler ist wiederum ein Taktgeber, welcher dem Zähler in einer bestimmten Hertz-Zahl sagt, wann er „weiter zählen“ soll. Am Ausgang des Demultiplexers ist eine einzelne

Datenader angeschlossen, welche zum Eingang eines so genannten Schieberegisters führt.
Der Sender der Daten legt nun also das Signal an den Demultiplexer an, und setzt den Binärzähler zurück. Der Binärzähler fängt jetzt an zu „zählen“, und legt die aktuelle Zählposition an den

zweiten Eingang des Demultiplexers. Der Demultiplexer legt das jeweilige Signal an seinen Ausgang an: Ist der Binärzähler bei 1, so wird das erste Signal des parallel anliegenden Signals an den einzelnen Ausgang angelegt. Ist der Binärzähler bei 2, so wird das zweite Signal des parallel anliegenden Signals an den Ausgang gelegt- und so weiter. Auf der Gegenseite passiert ähnliches: Jedes Mal, wenn der Taktgeber ausschlägt, wird das Signal am Eingang des Schieberegister weitergegeben. Ein Schieberegister kann ein Signal, welches gerade anlag „verschieben“. Dadurch ist es möglich, binäre Daten, wie in einer Schlange an der Einkaufskasse zu verarbeiten. So „schiebt“ sich das Gesamtsignal immer weiter. Kommt der Binärzähler bei 9 an, so wird auf der Senderseite der Demultiplexer zurückgesetzt, und auf der Empfängerseite der Ausgang des Schieberegisters freigegeben. Am Ausgang des Schieberegisters liegt jetzt also das parallele Signal an, welches anfangs am Eingang des Demultiplexers lag.
Zur Veranschaulichung noch 2 Kleine Pics:
http://img379.imageshack.us/img379/8184/parallelbz4.png
http://img170.imageshack.us/img170/5825/seriellbo9.png

Verfasst: 16.07.2007 12:24
von Falko
Hallo Thomas

Stell dir mal vor du benutzt nicht nur einen Thread.
Beispiel, einen unabhängigen für ein Beep und einen für
einen Timer. Da Killthread nun nicht weiß, welcher was oder wo ist, benötigst
du eine Variable, die dann beim Killthread den korrekten Thread beenden wird.

Wenn du aber nur einen Thread benutzt, der über die gesamte Laufzeit
des Programms im Hintergrund tätig sein soll, wäre der Killthread überflüssig,
da ein End am Ende des Programms die Programme ordentlich beenden wird.

Müssen musst du garnichts, aber besser ist es :wink:
Sonst "könnte" es mal sein, das bei mehreren erneuten Programmstarts
plötzlich kein Speicher mehr zur Verfügung steht.

Gruß Falko