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
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
???
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
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
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.
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
> 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 ..
Karin schrieb: > Dafür habe ich _outp(0x378, 1) verwendendet... Das ist der parallel port.. Da kannst du an der seriellen lange messen.
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
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.
> 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
Ich habe früher alles in TP und Assembler auf Hardwareebene programmiert. Achja die gute alte Zeit...
>> ... 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
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??
Indem du guckst was in welcher Reihenfolge in welche Bits wohin geschrieben wird.
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
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.
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
WELCHE Ports werden mit 0 beschrieben ? Und WELCHE Ports werden mit WELCHEN Hexadezimalen Werten beschrieben in WELCHER Reihenfolge ? Lade doch einfach den Code hoch.
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.
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
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 ?
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
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.
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 } }
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.
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.
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.
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
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
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?
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.
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.
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.
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.
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ß.
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.