Forum: PC-Programmierung Serielle Schnittstelle


von Karin (Gast)


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

von Stiefei (Gast)


Lesenswert?

heyhey,

in diesen Links steht eig. alles um eine Schnittstelle programmieren zu 
können in C:

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

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

Jep, du brauchst die Zugriffsrechte und musst die Schnittstelle dann 
öffnen, aber das steht alles im Tutorial

LG

von Blackbird (Gast)


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

von Blackbird (Gast)


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

von Vlad T. (vlad_tepesch)


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.

von Karin (Gast)


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

von Rufus Τ. F. (rufus) Benutzerseite


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 ..

von Raphael B. (helli7)


Lesenswert?

Karin schrieb:
> Dafür habe ich _outp(0x378, 1) verwendendet...

Das ist der parallel port..

Da kannst du an der seriellen lange messen.

von Karin (Gast)


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

von Peter II (Gast)


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.

von Uwe (Gast)


Lesenswert?


von Uwe (Gast)


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

von Uwe (Gast)


Lesenswert?

Ich habe früher alles in TP und Assembler auf Hardwareebene 
programmiert.
Achja die gute alte Zeit...

von Blackbird (Gast)


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

von Karin (Gast)


Lesenswert?

danke schonmal für eure antworten.
@Blackbird: ich offenbare jetzt wohl meine unwissenheit: Aber ich bin 
mir nicht sicher in welchem modus sie betrieben wird. Wie finde ich das 
den raus??

von Uwe (Gast)


Lesenswert?

Indem du guckst was in welcher Reihenfolge in welche Bits wohin 
geschrieben wird.

von Blackbird (Gast)


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

von Karin (Gast)


Lesenswert?

Also bei der initialisierung werden 5 Ports auf 0 gesetzt.
Im restlichen Verlauf werden dann aber nur noch zwei Ports beschrieben.
die Ports werden immer mit hexadezimal werten beschrieben. Also nicht 
nur mit high/low.

danke das ihr mir so stark helft.

von Karin (Gast)


Lesenswert?

das spricht doch für paralle port oder?

von Peter II (Gast)


Lesenswert?

kannst du nicht den code posten?

von Blackbird (Gast)


Lesenswert?

Kommt drauf an, welche Ports es sind und was die gesetzten oder 
gelöschten Bits bei der Initialisierung einstellen.
Beim Schreiben auf die "2 Ports" kann es sich einmal um ein 
Steuerregister und dann um das Datenregister handeln. Aber das weißt nur 
Du.

Blackbird

von Uwe (Gast)


Lesenswert?

WELCHE Ports werden mit 0 beschrieben ? Und WELCHE Ports werden mit 
WELCHEN Hexadezimalen Werten beschrieben in WELCHER Reihenfolge ?
Lade doch einfach den Code hoch.

von Rufus Τ. F. (rufus) Benutzerseite


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.

von Karin (Gast)


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

von Uwe (Gast)


Lesenswert?

Dann brauchst du die Anleitung der Messkarte. Wenn du die nicht bekommst 
dann kannst du nur noch das Pascal Program nachahmen sozusagen Reverse 
Engeneering. Ist aber für ein Anfänger nicht einfach.
Wie Heißt die Messkarte (Firma und Modell) ?
Warum lädst du den Code nicht hoch ?

von Uwe (Gast)


Lesenswert?

Die Firma und das Model stehen normalerweise auf der Messkarte drauf.

von Karin (Gast)


Lesenswert?

ich weiß nicht ob ich den code posten darf. Da er von der Firma ist. 
viellicht ist ein Copyright darauf.

Firma ist polytec und die Karte heißt UPMPC

von Karin (Gast)


Lesenswert?

Gibt es keinen äquivalente code zu:

Port(0x3f8) := 0x1F;
und zu

byte : x;

x := Port(0x3f8)

falls ihr mir das sagen könnten, müsste ich den rest alleine 
hinbekommen.

von Uwe (Gast)


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
}
}

von Uwe (Gast)


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.

von Karin (Gast)


Lesenswert?

ich benutze im moment mingw gcc. kann aber auch wechseln, wenn es was 
besseres gibt.

@uwe: mein compailer erkennt die von dir geschriebenen zeilen leider 
nicht :-( trotzdem danke.

von Rufus Τ. F. (rufus) Benutzerseite


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.

von Uwe (Gast)


Lesenswert?

GCC kann inline assembler benutzt jedoch eine ganz andere Syntax.
Geht aber müßte man sich erst mal einlesen.
http://www.ibiblio.org/gferg/ldp/GCC-Inline-Assembly-HOWTO.html

von Karin (Gast)


Lesenswert?

danke für eure antworten. ich werde mal abklären, ob ich das programm 
posten darf.
Noch eine Frage: wenn ich _outp und _inp verwende, muss ich den port 
vorher öffnen oder geht das so?

nochmal danke an alle

von Peter II (Gast)


Lesenswert?

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

es gibt keine Port wenn du _outp verwendest, du schreibst damit direkt 
auf eine Hardware-IO Adresse. Welchen Port will du denn do öffnen?

von Uwe (Gast)


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.

von Rufus Τ. F. (rufus) Benutzerseite


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.

von Uwe (Gast)


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.

von Rufus Τ. F. (rufus) Benutzerseite


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.

von Uwe (Gast)


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ß.

von Karin (Gast)


Lesenswert?

also in dem Programm sind keine Interrupts enthalten, da bin ich mir 
ganz sicher. Ich werde jetzt jetzt einfach nochmal probieren zu 
übersetzen. Melde mich bestimmt aber später nochmal ;-)

nochmal danke für eure super hilfe!!!

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.