Unix (Linux)-os portkezelés Windows (XP)-n C-ben

Unix (Linux)-os portkezelés Windows (XP)-n C-ben
2013-06-04T17:10:33+02:00
2013-06-06T09:10:22+02:00
2022-11-29T04:30:39+01:00
jbalint
Sziasztok!

Egy C-ben készült Linuxon futó kis programot mely soros porton kommunikál a külvilággal át kell írnom Windowsra.

A programot CodeBlocks-ban írom, a GUI-ja GTK-ban Glade-el készült.

A Windows-os Codeblocks-al beépített MinGW használatával sikerült (nagyobb) gond nélkül lefordítanom.

A program a soros kommunikáció kivételével tökéletesen működik, de ha bennhagyom akkor a MinGW-s GCC nem tudja lefordítani.

Cygwin használatával lefordul a soros kommunikációs rész, de akkor a program nem tudja megnyitni a soros portot és a GUI-s rész nem működik CygWin-el (még nem jöttem rá miért, lefordul de nem működik).

A soros kommunikációs részből csináltam egy teszt programot.

#include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <termios.h> #include <stdio.h> #include <stdlib.h> void nonblock(int command) { struct termios ttystate; tcgetattr(1, &ttystate); if(command==1) { ttystate.c_lflag &= ~ICANON; ttystate.c_cc[VMIN] = 0; } if (command==0) { ttystate.c_lflag |= ICANON; } tcsetattr(1, TCSANOW, &ttystate); } int open_szerial(char *port_name,int baudrate) { int fd=-1; struct termios newtio; char buf=0; char buf2=0; fd = open(port_name, O_RDWR | O_NOCTTY | O_NDELAY); if(fd < 0) { return(-1); } fcntl (fd, F_SETFL, 0); bzero(&newtio, sizeof(newtio)); switch(baudrate) { case 110: newtio.c_cflag = B110| CS8 | CREAD; break; case 2400: newtio.c_cflag = B2400| CS8 | CREAD; break; case 9600: newtio.c_cflag = B9600| CS8 | CREAD; break; } newtio.c_iflag = ICRNL; newtio.c_lflag &= ~ICANON; newtio.c_cc[VTIME] = 0; newtio.c_cc[VMIN] = 0; tcflush(fd, TCIFLUSH); tcsetattr(fd, TCSANOW, &newtio); return(fd); } int main(int argc, char **argv) { char c; int File_Azonosito=-1; File_Azonosito=open_szerial("COM1",9600); if(File_Azonosito==-1) { printf("Hiba, nem sikerül a soros port megnyitása\n"); printf("Ellenőrizd a port elérési útját, és a megnyitáshoz rendszergazdai jogokra is szükség lehet\n"); return(-1); } nonblock(1); while(1) { c=getchar(); if(c!=-1)write(File_Azonosito,&c,1); if(c=='q')break; } c=0; write(File_Azonosito,&c,1); nonblock(0); return 0; }

Ez Linux alatt tökéletesen működik!

Windowson MinGW-vel nem fordul le, termios.h-t hiányolja, Cygwin-el lefordul, de nem sikerül megnyitni a portot.

Virtualbox-al teszteltem, és a többi alkalmazás (hyperterminal, arduino serial port monitor) rendesen kezeli a com1-et (ami a host gépen futó Linuxon a /dev/ttyACM0 -ra van irányítva és egy arduino-val kommunikál)

Van ötletetek hogyan lehetne MinGW-vel vagy esetleg Cygwin-el működésre bírni?

Hosszútávon úgyis érdemesebb cygwin-re áttérni, ha végkép nem tudom elindítani rajta a GTK-s Glade-s GUI-t akkor nyitok neki egy másik témát.

Segítségeteket előre is köszönöm.
Mutasd a teljes hozzászólást!
port_name lehetne más. pl. "\\\\.\\COM1". Cygwin esetén "/dev/ttyS0" vagy "/dev/com1"
Mutasd a teljes hozzászólást!

  • Tök másképp van Windows alatt:(
    About Communications Resources
    Mutasd a teljes hozzászólást!
  • dev-c
    találsz benne egy olyat, hogy MS windows socket.chm és van hozzá péda program is.
    Ahogy NevemTeve irta: a Windows tök más
    Mutasd a teljes hozzászólást!
  • Hosszútávon úgyis érdemesebb cygwin-re áttérni, ha végkép nem tudom elindítani rajta a GTK-s Glade-s GUI-t akkor nyitok neki egy másik témát.


    Linux-osan gondolkodol, de win programot akarsz irni. Mit gondolsz hány Win felhasználónak van feltelepítve a GTK? Megírhatod benne, de akkor bele kell gyömöszölnöd a setup.exe fájlba, és akkor már szép mérete lesz a kis programodnak.
    de ha ráérsz és tudsz egy kicsit angolul nézd meg


    Hosszútávon úgyis érdemesebb cygwin-re áttérni,
    Nem szeretnélek kiábrándítani, de hosszú távon LINUX, GCC és VIM.
    Mutasd a teljes hozzászólást!
  • port_name lehetne más. pl. "\\\\.\\COM1". Cygwin esetén "/dev/ttyS0" vagy "/dev/com1"
    Mutasd a teljes hozzászólást!
  • Ez az! köszi

    Pedig ezt próbáltam ki először, de nem volt /dev/ttyS0 ... Aztán hirtelen megjelent és jó is.

    Azóta sikerült a GTK-t is lefordítani, bár fordításnál hibát dob... Valahogy a karter kódolás nem jó mert a kódban kis négyzetek meg kínai karakterek jelennek meg(főleg a gyári heder fájlokban) így lefordul de nem minden funkció működik.

    A GTK-s GUI futás közben kivétel nélkül minden karakter helyett üres négyzetet rajzol, mindenhol a beviteli mezőkben az ablak és gombnevekben stb...

    A soros programnál is néhány fv névben megjelentek ezek a furcsa karakterek, azt a pár sort újragépeltem.

    A másik baj hogy nem állítja be a port baud rate-t szerintem 2400-on van alapból, és csak úgy lehet jelenleg beállítani ha nyitok pl egy hyperterminal ott beállítom majd kilépek és újra futtatom a programot...

    Szerintem már közel a megoldás.
    Mutasd a teljes hozzászólást!
  • Nem fogom bele tenni a GTK telepítőt a programban és nem is teszem mellé. a readme.txt ben lesz két link:

    Az egyik az ubuntu.com / debian.org / linuxmint.com közül valamelyik

    A másik pedig vagy a gtk.or vagy a Google "gtk+ runtime" keresőkifejezésre...

    Azt mindenki dönt ahogy akar... Azért írom egyébként GTK-ra hogy lassan fokozatosan a Labviewt WinXP párost C Linux-ra cseréljük.

    KB 6-8 hónapig kell hogy Windowson is fussanak a programok, utána remélhetőleg fokozatosan egyre kisebb igény lesz a Windows támogatásra.

    1-2 felhasználói programon kívül akkor már semmit nem szeretnék Windowsra fejleszteni, ha mégis valami Windowsra is kell le lehessen fordítani ha nagyon muszáj.

    A programok egy rész nyílt forrású lesz azt majd ha valakinek kel lefordítja Windowsra magának
    Mutasd a teljes hozzászólást!
  • Sikerült végül megoldani

    A kód így módosult:
    #include <sys/types.h> #include <sys/stat.h> #include <sys/time.h> #include <termios.h> #include <unistd.h> #include <fcntl.h> #include <ctype.h> #include <stdio.h> #include <string.h> #include <math.h> #include <stdlib.h> #include <malloc.h> int posix_com_close(int port) { int rtnval = 0; if (port != -1) { rtnval = (int) close(port); } return(rtnval); } int posix_com_open( char *devicename, int rate, char parity, int databits, int stopbits, int options ) { int rtnval = 0; struct termios t; int local_databits = 0, local_stopbits = 0, local_parity = 0, local_rate = 0; char upper_parity = 0; upper_parity = toupper(parity); if (((databits == 5) || (databits == 6) || (databits == 7) || (databits == 8)) && ((stopbits == 2) || (stopbits == 1)) && ((upper_parity == 'N') || (upper_parity == 'O') || (upper_parity == 'E')) && ((rate == 50) || (rate == 75) || (rate == 110) || (rate == 134) || (rate == 150) || (rate == 200) || (rate == 300) || (rate == 600) || (rate == 1200) || (rate == 1800) || (rate == 2400) || (rate == 4800) || (rate == 9600) || (rate == 19200) || (rate == 38400) || (rate == 57600) || (rate == 115200))) { rtnval = open(devicename,O_RDWR); if (rtnval != -1) { switch(databits) { case 5 : local_databits = CS5; break; case 6 : local_databits = CS6; break; case 7 : local_databits = CS7; break; case 8 : local_databits = CS8; break; } if (stopbits == 2) local_stopbits = CSTOPB; else local_stopbits = 0; switch(upper_parity) { case 'E' : local_parity = PARENB; break; case 'O' : local_parity |= PARODD; break; } } t.c_iflag = IGNPAR; t.c_oflag = 0; t.c_cflag &= ~CSIZE; t.c_cflag = CLOCAL | local_databits | local_stopbits | local_parity | options; t.c_lflag = IEXTEN; switch(rate) { case 50 : local_rate = B50; break; case 75 : local_rate = B75; break; case 110 : local_rate = B110; break; case 134 : local_rate = B134; break; case 150 : local_rate = B150; break; case 200 : local_rate = B200; break; case 300 : local_rate = B300; break; case 600 : local_rate = B600; break; case 1200 : local_rate = B1200; break; case 1800 : local_rate = B1800; break; case 2400 : local_rate = B2400; break; case 4800 : local_rate = B4800; break; case 9600 : local_rate = B9600; break; case 19200 : local_rate = B19200; break; case 38400 : local_rate = B38400; break; case 57600 : local_rate = B57600; break; case 115200 : local_rate = B115200; break; } if ((cfsetispeed(&t,local_rate) != -1) && (cfsetospeed(&t,local_rate) != -1)) { if (tcsetattr(rtnval,TCSANOW,&t) == -1) rtnval = -1; } else rtnval = -1; } else rtnval = -1; return(rtnval); } char posix_com_read(int port, char *dst) { if (port != -1) return(read(port,dst,1) == 1); else return(0); } char posix_com_write(int port, char src) { if (port != -1) return(write(port,&src,1) == 1); else return(0); } void nonblock(int command) { struct termios ttystate; tcgetattr(1, &ttystate); if(command==1) { ttystate.c_lflag &= ~ICANON; ttystate.c_cc[VMIN] = 0; } if (command==0) { ttystate.c_lflag |= ICANON; } tcsetattr(1, TCSANOW, &ttystate); } int main(int argc, char **argv) { int myport = 0; struct termios *settings = NULL; char key = 0, funckey = 0, done = 0, inchar = 0; myport = posix_com_open("/dev/ttyS0",9600,'N',8,1,0); if (myport == -1) { printf("Hiba, nem sikerül a soros port megnyítása\n"); printf("Ellenőrizd a port elérési utját, és a megnyitáshoz rendszergazdai jogokra is szükség lehet\n"); return(-1); } nonblock(1); while (1) { key=getchar(); if(key!=-1) { printf("ezt nyomtad le%c\n",key); posix_com_write(myport,key); } if(key=='q')break; } nonblock(0); }


    Így már tökéletesen működik Linuxon és Windowson is.

    Valószínűleg kellet neki hogy minden paramétert beállítsak azt is ami alapértelmezetten van.

    Már "csak" a karakterkódolási hibával szenvedek, ha MinGW-vel fordítok akkor jó, ha meg Cygwin-el akkor mindenféle furcsa írásjel meg négyzetek kínai karakterek stb-k fordulnak a kódba.
    Van hogy csak figyelmeztetéseket ad de lefordul és fut a program, van hogy lefordul de nem fut de a legtöbbször le sem fordul Cygwin használatával.

    A fájlban nem látszik a Codebocks-ban sem látom, csak a fordító dobálja a hibákat hogy pl a "Éß$@&&#8364;serial_open&#8364;&@$ßÉ" függvény nem található, persze a kérdéses sorba a "serial_open()" van írva...

    Mindegy ez már másik téma.


    Köszönöm a segítséget

    Üdv
    Mutasd a teljes hozzászólást!
  • Ez igy nem fog menni, megmondom miért, mert van benne tapasztalatom, a legtöbb win felhasználó setup.exe klikk klikk majd program.exe és ha nem működik a readme.txt fájlodat nem fogja elovasni.
    Egy javaslat: a setup.exe-be tegyél bele egy ellenőrző kódot
    pl GTK-hoz, ha nincs meg akkor full setup (megjegyzés a wx kisebb, az igaz hogy lassúbb, de kisebb) vagy miként irtam win32API

    már van egy idelye hogy win32 api programot irtam
    Mutasd a teljes hozzászólást!
  • Igazad lehet sajnos .

    Ezt a konkrét program, egy berendezést fog működtetni így csak egy gépre kell telepíteni szerintem még setup.exe-t sem csinálok neki.

    Az általam írt programok elsősorban nem az "egyszerű felhasználókat" célozzák meg de lehet hogy sok embert elrettent ha nem lehet "next -> next -> next -> finish" el telepíteni.

    Lehet hogy tényleg beleteszem a GTK+ runtime telepítőt, "csak" 8Mb és akkor a Windowsosokkal sem tolok ki.

    A GTK-t nem akarom lecserélni, nagyon tetszik ez az ablakozó és Linuxon csodálatosan fut ez pedig az elsődleges szempont, a Windowsos támogatás mondhatni mellékes fontosabb hogy Raspberry-n fusson mint hogy Windowson.

    Ezt még párszol át kell gondolnom, köszönöm a tanácsokat.
    Mutasd a teljes hozzászólást!
Tetszett amit olvastál? Szeretnél a jövőben is értesülni a hasonló érdekességekről?
abcd