Serielle Schnittstelle

Gast #2387823
Lesenswert?

Hi,

ich muss ein Progamm in C schreiben und damit eine serielle 
Schnittstelle ansprechen. Ich wollte jetzt erstmal ein Testprogramm 
schreiben und alle Pins auf High setzen und das mit dem Multimeter 
überprüfen.
Dafür habe ich _outp(0x378, 1) verwendendet und das in einer 
Endlosschleife laufen lassen. Leider gehen die Pins (habe es mit 
mehreren gemacht) nicht auf High. Das ganze läuft unter win98, also 
sollte Windows mit dem Befehl kein problem haben.

Muss ich den Port im Programm noch öffnen?
Was ist sonst mein Fehler?

Viele Grüße

Karin
Gast #2387863
Lesenswert?

???
1
/*******************************************
2
** Pin5 ist Masse, Pin7 ist +10V (== AUS)
3
**                 Pin7 ist -10V (== EIN)
4
** Version 1 mit Funktion 'warte ()'
5
*******************************************/
6
#include <windows.h>
7
#include <time.h>
8

9
#define SWITCH_ON  3     // Minuten
10
#define SWITCH_OFF 57
11

12
void warte (int sekunden) 
13
{ 
14
  clock_t start; 
15
  sekunden *= CLOCKS_PER_SEC; 
16
  start = clock (); 
17
  while (clock() < start + sekunden); 
18
}
19

20
int main (void)
21
{
22
  HANDLE hPort; 
23

24
  hPort =  CreateFile (TEXT("COM1"), GENERIC_WRITE, 
25
                       0, NULL, OPEN_EXISTING, 0, NULL);
26

27
  for (;;)
28
  {
29
    EscapeCommFunction (hPort, SETRTS); // RTS setzten Pin7
30
    warte (SWITCH_ON * 60);
31
    EscapeCommFunction (hPort, CLRRTS); // RTS rücksetzten Pin7
32
    warte (SWITCH_OFF * 60);
33
  } 
34

35
  CloseHandle (hPort);
36
  return (0);
37
}
38

39
/*******************************************
40
** Pin5 ist Masse, Pin7 ist +10V (== AUS)
41
**                 Pin7 ist -10V (== EIN)
42
** Version 2 mit Funktion 'Sleep ()'
43
*******************************************/
44
#include <windows.h>
45

46
#define SWITCH_ON  3     // Minuten
47
#define SWITCH_OFF 57
48

49
int main (void)
50
{
51
  HANDLE hPort; 
52

53
  hPort =  CreateFile (TEXT("COM1"), GENERIC_WRITE, 
54
                       0, NULL, OPEN_EXISTING, 0, NULL);
55

56
  for (;;)
57
  {
58
    EscapeCommFunction (hPort, SETRTS); // RTS setzten Pin7
59
    Sleep (SWITCH_ON * 60 * 1000);
60
    EscapeCommFunction (hPort, CLRRTS); // RTS rücksetzten Pin7
61
    Sleep (SWITCH_OFF * 60 * 1000);
62
  } 
63

64
  CloseHandle (hPort);
65
  return (0);
66
}

Empfangen von seriellen Daten geht besser mit Threads.

Blackbird
Gast #2387879
Lesenswert?

Hier noch die simple Eingabe:
1
/*******************************************
2
**    Nur Demo der Funktionen
3
**
4
** Button an RTS und CTS anschließen:
5
** An RTS wird Spannung gelegt ("ON"), CTS liest 
6
** noch "LOW", solange der Button nicht gedrückt
7
** wird.
8
**
9
** RTS (Ausgang): Pin7 ist +10V (== AUS)
10
**                Pin7 ist -10V (== EIN)
11
** CTS (Eingang): Pin8 wird abgefragt
12
*******************************************/
13
#include <windows.h>
14
                      
15
int main (void)
16
{
17
  HANDLE hPort; 
18
  DWORD  CtsStatus;
19

20
  // COM1 öffnen:
21
  hPort =  CreateFile (TEXT("COM1"), GENERIC_READ | GENERIC_WRITE, 
22
                       0, NULL, OPEN_EXISTING, 0, NULL);
23

24
  EscapeCommFunction (hPort, SETRTS); // RTS setzen (= -10V = ON)
25
  //EscapeCommFunction (hPort, CLRRTS); // rücksetzen geht so
26

27
  // Button abfragen:
28
  GetCommModemStatus (hPort, &CtsStatus);
29

30
  if ((CtsStatus & MS_CTS_ON))
31
  {
32
    // irgendwas machen wenn Button gedrückt wurde ...
33
  }
34

35
  // ...
36

37
  CloseHandle (hPort);
38
  return 0;
39
}

Blackbird
#2388172
Lesenswert?

Karin schrieb:
> ich muss ein Progamm in C schreiben und damit eine serielle
> Schnittstelle ansprechen. Ich wollte jetzt erstmal ein Testprogramm
> schreiben und alle Pins auf High setzen und das mit dem Multimeter
> überprüfen.

Was soll dieses Testprogramm bringen?
Das ist in etwa wie:

"ich muss lernen mit meinem Fahrrad zu fahren, will aber erst mal 
probieren, ob die Räder auch an meinen Roller passen."

Das OS stellt Funktionalität bereit, mit der man über die Serielle 
Schnittstelle kommunizieren kann.
Daran vorbei irgendwelche Pins zu setzen bringt überhaupt keinen 
Erkenntnisgewinn für ersteren Anwendungszweck.
Gast #2388566
Lesenswert?

Hi,

danke für die antworten. Ich habe jetzt erstmal probiert mit diesem 
Verfahren zu arbeiten:

http://www.mikrocontroller.net/articles/Ports_benutzen_%28Windows%29

Dazu habe ich noch zwei Fragen:

1. da das Programm unter 98 laufen soll muss ich giveio ja nicht 
einzubeziehen oder? Was muss ich stattdessen in createfile einfügen?

2. Mit outb kann ich dann ja einfach die pins ansprechen oder? Müsste 
ich das auch messen können, wenn ich einen auf High setze oder geht der 
so schnell wieder runter, dass es nicht messbar ist mit einem 
multimeter?

@ vlad(oder soll ich dich besser dracul nennen ;-)): Da ich blutige 
anfängerin bin probiere ich immer möglichst in kleinen schritten mich 
voran zu arbeiten. Da ich für das spätere programm die pins einzeln 
ansprechen muss, will ich als erstes überprüfen, ob ich sie einzelnt auf 
high setzen kann.

danke schonmal für die hilfe

karin
Persönliche Seite #2388664
Lesenswert?

> Mit outb kann ich dann ja einfach die pins ansprechen oder?

Prinzipiell: Serielle Schnittstellen werden NICHT über direkte 
I/O-Befehle angesteuert. Auch nicht unter den Frickel-Versionen von 
Windows.
Das macht man auch unter den Frickel-Versionen mit den Funktionen der 
Win32-API.

Für das "Bit-Banging" (also willkürliches Gewackel an 
Handshakeleitungen) sind serielle Schnittstellen ziemlich ungeeignet.

Außerdem hat eine serielle Schnittstelle nur zwei dedizierte 
Handshake-Ausgänge (DTR und RTS), damit lässt sich eh' nicht allzuviel 
anfangen.

Die wesentlichen Punkte kannst Du dem Beispielprogramm von "Blackbird" 
entnehmen, das funktioniert unter jeder Windows-Version seit NT3.1.


Was soll denn insgesamt erreicht werden? Nicht, daß Du Dich in 
technische Fehlentscheidungen verrennst ..
Gast #2388798
Lesenswert?

Hi,

also ich muss ein altes Turbo Pascal programm in C schreiben. 
Ausgangsport ist eine DB 15 (Com Port mit 15 pins). Das TB programm ist 
nicht besonders kompliziert. Nur das die Pins direkt angesprochen werden 
und dies anscheinend mit C nicht soleicht geht. Insgesamt muss ich acht 
Pins ansprechen ( Adresse 3f8-3ff).

danke nochmal
Gast #2388803
Lesenswert?

Karin schrieb:
> Nur das die Pins direkt angesprochen werden
> und dies anscheinend mit C nicht soleicht geht.

das hat nichts mit C zu tun sondern mit den aktuellen Betriebssystemen. 
Wenn du nur ein USB-Serielle schnittstelle hast dann gibt es überhaupt 
keine IO-Adresse dafür mehr.

Es geht auch normalerweise ab Win2000 nicht mehr mit Turbopascal.
Gast #2388822
Lesenswert?

> Insgesamt muss ich acht
> Pins ansprechen ( Adresse 3f8-3ff)

Die Acht Pins liegen in dem Byte an Adresse 0x378 im IO-Raum wobei jedes 
Bit in diesem Byte einem Pin am Parallelport enspricht.Die 
dahinterliegenden Adressen sind für was anderes zuständig oder auch 
nicht.

3f8 ist ein Comport der hat keine 8 Pins zum ansprechen
guck mal hier
http://www.stanislavs.org/helppc/8250.html

Falls es doch der Parallelport sein soll dann so:

der 1. Paralleport liegt an adresse 378
Port 378 printer data output  (readable)

   |7|6|5|4|3|2|1|0|  ports 278, 378, 3BC
    | | | | | | | `---- data bit 0, hardware pin 2
    | | | | | | `----- data bit 1, hardware pin 3
    | | | | | `------ data bit 2, hardware pin 4
    | | | | `------- data bit 3, hardware pin 5
    | | | `-------- data bit 4, hardware pin 6
    | | `--------- data bit 5, hardware pin 7
    | `---------- data bit 6, hardware pin 8
    `----------- data bit 7, hardware pin 9

  Port 379 printer status register   (Parallel Printer Port)

   |7|6|5|4|3|2|1|0|  ports 279, 379, 3BD
    | | | | | | | `---- 1 = time-out
    | | | | | `------- unused
    | | | | `-------- 1 = error,  pin 15
    | | | `--------- 1 = on-line,  pin 13
    | | `---------- 1 = out of paper,  pin 12
    | `----------- 0 = Acknowledge,  pin 10
    `------------ 0 = busy,  pin 11

  Port 37A printer control register   (Parallel Printer Port)

   |7|6|5|4|3|2|1|0|  ports 27A, 37A, 3BE
    | | | | | | | `---- 1 = output data to printer,  (pin 1)
    | | | | | | `----- 1 = auto line feed,  (pin 14)
    | | | | | `------ 0 = initialize printer,  (pin 16)
    | | | | `------- 1 = printer reads output,  (pin 17)
    | | | `-------- 0 = IRQ disable,1=IRQ enable for ACK
    `------------- unused
Gast #2388832
Lesenswert?

>> ... Insgesamt muss ich acht Pins ansprechen ( Adresse 3f8-3ff).

Das sind aber keine Pins, sondern Register: Steuerregister, 
Datenregister, usw.
Die Serielle Schnittstelle hat nur 3 Ausgänge (TxD, RTS, DTR) und 5 
Eingänge (RI, RxD, DCD, DSR, CTS).

Wird sie denn als serielle Schnittstelle betrieben oder als 
Ersatz-Parallel-Port?


Blackbird
Gast #2388853
Lesenswert?

Nur an Hand der Arbeitsweise des vorhandenen Programms. Jetzt weißt Du 
ja, was die Register bedeuten und kannst nachvollziehen, was, und an 
welche Stelle, da reingeschrieben wird.

TxD der COM-Schnittstellen wurde auch unter Turbo Pascal Byteweise 
beschrieben. Also kein achtmal Bit-nacheinander-Rausschieben. Das sollte 
im Programm schon irgendwie erkennbar sein.

Blackbird
Persönliche Seite #2388898
Lesenswert?

Karin schrieb:
> also ich muss ein altes Turbo Pascal programm in C schreiben.
> Ausgangsport ist eine DB 15 (Com Port mit 15 pins).

An PCs gibt es eigentlich nur zwei Möglichkeiten für 15polige 
Anschlüsse, das ist der VGA-Anschluss (mit drei Reihen à 5) und das ist 
der Gameport (zwei Reihen mit 8 und 7).

Serielle Schnittstellen haben 9 Anschlüsse, selten begegnet man welchen 
mit 25. Die unterscheiden sich von Druckerschnittstellen dadurch, daß 
sie Stecker (Ding mit Stiften) und keine Buchsen (Ding mit Löchern) 
sind.

Kläre also doch bitte erstmal, was Du da wirklich tun sollst.


Und poste den Code Deines Pascal-Programmes, dann können wir hier besser 
erahnen, was Du da anzustellen versuchst.
Gast #2388899
Lesenswert?

Also es handelt sich bei dem PC um ein spezielle Messkarte, kein 
standard.
Es gibt acht Ports:
1. Data Port
2. Data+ interrupt port
3. kontroll port
4. Trigger port
5. Modus kontroll
6. status port
7. digital input port
8. output controll port.

angesprochen werden die ports immer

Port(baseadr+offste) :=$17; (beispiel)

nochmal danke
Gast #2388981
Lesenswert?

Kommt auf deinen C compiler an.
Manche haben sowas wie outp oder so drin. Ansonsten der Inline Assembler 
oder sich ein paar Assembler funktionen dazulinken.
Welchen C Compiler benutzt du denn ?

Viele können sowas wie :
void outport(unsigned short int port,unsigned char out)
{
_asm{
mov al,out
mov dx,port
out dx,al
}
}

unsigned char inport(unsigned short int port)
{
_asm{
mov dx,port
in al,dx
return al
}
}
Gast #2389021
Lesenswert?

Falls dein Compiler keinen Inline Assembler hat. Nimm einen Assembler 
deiner Wahl, exportiere die beiden funktionen und compiliere als 
objectfile. Danach mußt du diese funktionen nur noch als extern c in 
deinem compiler deklarieren und deinem linker mitteilen wo er deine 
objectfiles findet.
Du mußt natürlich im assembler die Variablenübergabe noch regeln 
(Calling conventions) und nach diesem Aufrufschema auch die beiden 
Assemblerfunktionen Programmieren (z.b. Variableübergabe über stack oder 
über Register, wer räumt den Stack auf, wie wird der Rückgabewert 
zurückgegeben ).
Alles in allem höchstens ne Stunde Arbeit.
Persönliche Seite #2389030
Lesenswert?

Karin schrieb:
> Gibt es keinen äquivalente code zu:
>
> Port(0x3f8) := 0x1F;
> und zu
>
> byte : x;
>
> x := Port(0x3f8)

So etwas gibt es zwar, und das ist auch nicht sonderlich kompliziert, 
_inp und _outp für Byte-Zugriffw, _inpw und _outpw für Word-Zugriffe:
1
#include <conio.h>
2

3
_outp(0x3f8, 0x1f);
4

5
x = _inp(0x3f8);

So ist das beispielsweise bei Microsoft-C-Compilern gelöst. Unter den 
ernstgemeinten Windows-Versionen geht so etwas jedoch nur mit giveio.sys 
und ähnlichen Verfahren; aber Du willst ja ein Frickel-Windows 
verwenden, da ist das nicht erforderlich.


Aber

Sollte die Messkarte Interrupts verwendet, geht das auf diese Art und 
Weise nicht, denn einen Interrupthandler (das ist die Routine, die 
aufgerufen wird, wenn die Karte über den Interrupt dem System 
signalisiert, daß etwas geschehen ist), kann man auch unter 
Frickel-Windows nicht in einem normalen Usermode-Programm unterbringen.


Ob sie das tut, ist nur mit einem Blick in Dein Pascalprogramm oder in 
die Dokumentation der Karte möglich.


Und ob das Programm wiederum irgendwelchen Copyrightbeschränkungen 
unterliegt, sollte da in Form eines Kommentares drinstehen. Wenn da kein 
solcher Kommentar drin ist, dann solltest Du den hier posten können.

Da ohne die Karte der Code völlig nutzlos ist, schätze ich eine 
Veröffentlichung als nicht so kritisch ein, wie der von Software, die 
einen breiteren Nutzen erfüllt.

Außerdem ist das Programm gnadenlos veraltet, DOS-Programme in Pascal 
hat man in der ersten Hälfte der 90er Jahre vielleicht noch geschrieben, 
spätestens seit dem Jahrtausendwechsel sollte man sich sowas abgewöhnt 
haben.
Gast #2389883
Lesenswert?

Wenn diese Funktionen implementiert sind dann hast du schon Alles was du 
brauchst. Diese kannst du genauso einsetzen wie die Pascal Funktionen 
(natürlich andere Syntax). Das mit dem Assembler war nur gedacht falls 
"_inp" und "_outp" in deinem gcc version nicht implementiert sind. Ich 
glaube diese müßten in der conio.h definiert sein.
Persönliche Seite #2389889
Lesenswert?

Karin schrieb:
> Noch eine Frage: wenn ich _outp und _inp verwende, muss ich den port
> vorher öffnen oder geht das so?

Du kannst den Port gar nicht vorher öffnen, weil Deine Karte eben 
KEINE serielle Schnittstellenkarte ist, und solange zur Karte kein 
Devicetreiber gehört, gibt es auch kein Device, das vom Betriebssystem 
angesprochen werden kann.

Und selbst wenn es das gäbe, darfst Du auf gar keinen Fall Zugriffe 
über den Devicetreiber und Zugriffe am Devicetreiber vorbei mischen.
Gast #2389934
Lesenswert?

Ich denke das ist nur ein verständnisproblem wegen der bezeichnung 
IO-Port bzw outp(ort). IO-Ports haben nichts mit Comports oder 
Parallelports zu tun.
Wie kann man das jetzt erklären ohne dich weiter zu verwirren.
Hmmm.
Also um Geräte und Arbeitsspeicher zu trennen wurden zwei getrennt 
Adressräume geschaffen. Um auf den IO-Raum zuzugreifen benutzt man die 
CPU Befehle "in" und "out". Dahinter gibt man die IO-Adresse an die oft 
auch als IO-Port bezeichnet wird jedoch mit einer Schnittstelle nichts 
zu tun hat außer das auch Schnitstellen über IO-Ports angesprochen 
werden.
Persönliche Seite #2390095
Lesenswert?

Und wie ich schon erwähnt habe: Ohne zu klären, ob das DOS-Programm die 
Karte mit Interruptbetrieb ansteuert, ist jede weitere Untersuchung 
witzlos.

Erst wenn mit Sicherheit ausgeschlossen ist, daß die Karte Interrupts 
verwendet, kann die Untersuchung, wie die Karte mit _inp/_outp 
anzusteuern ist, fortgesetzt werden.
Gast #2390148
Lesenswert?

Naja die Karte scheint ja vorher mit Pascal auch über reine IO Zugriffe 
funktioniert zu haben. Wenn die Software nun einfach nach C konvertiert 
wird muß man noch nicht mal wissen wofür welcher Zugriff ist bzw. nur 
das lesen oder schreiben der Daten interresiert. Was genau in den Status 
und Controllregistern passiert braucht mich nicht zu kümmern solange ich 
keine Bugs korrigieren oder Features hinzufügen muß.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren