Port COM w windowsie i ustawianie jego prędkoś

Jakoś je trzeba poznajdować i ponumerować. I w tłumaczeniu nazwano to "wyliczaniem". A Ty trollujesz i to ostro.

Reply to
RoMan Mandziejewicz
Loading thread data ...

OK OK nazwa jak nazwa, tylko po co ładowało się to do pamięci jeszcze przed instalacją czegokolwiek i w ogóle piję raczej do tego, że często jakieś bzdurne programiki i moduły robią tyle zamieszania jakby był to Bardzo Ważny Program Bez Którego Ani Rusz.

To nie karm ;)

Mirek.

Reply to
Mirek

Pokaż fragment kodu odpowiedzialny za otwieranie portu i ustawianie parametrów jego pracy

jp

Reply to
programista

Uwaga: dlugie :P

m_hCom=CreateFile( pComName, GENERIC_READ|GENERIC_WRITE, 0, 0, OPEN_EXISTING, FILE_FLAG_NO_BUFFERING, 0 );

if ( m_hCom == INVALID_HANDLE_VALUE ) { m_hCom = NULL; return false; }

DCB dcb;

FillMemory( &dcb, sizeof ( dcb ),0 );

if ( !GetCommState( m_hCom, &dcb ) ) { CloseHandle(m_hCom); m_hCom = NULL; return ( false ); }

switch( m_eBaud ) { case SBaud::B300: dcb.BaudRate=CBR_300; break; case SBaud::B600: dcb.BaudRate=CBR_600; break; case SBaud::B1200: dcb.BaudRate=CBR_1200; break; case SBaud::B2400: dcb.BaudRate=CBR_2400; break; case SBaud::B4800: dcb.BaudRate=CBR_4800; break; case SBaud::B9600: dcb.BaudRate=CBR_9600; break; case SBaud::B14400: dcb.BaudRate=CBR_14400; break; case SBaud::B19200: dcb.BaudRate=CBR_19200; break; case SBaud::B38400: dcb.BaudRate=CBR_38400; break; case SBaud::B57600: dcb.BaudRate=CBR_57600; break; case SBaud::B115200: dcb.BaudRate=CBR_115200; break; case SBaud::B128000: dcb.BaudRate=CBR_128000; break; case SBaud::B256000: dcb.BaudRate=CBR_256000; break; }

switch ( m_eParity ) { case SParity::EVEN: dcb.Parity=EVENPARITY; break; case SParity::MARK: dcb.Parity=MARKPARITY; break; case SParity::NONE: dcb.Parity=NOPARITY; break; case SParity::ODD: dcb.Parity=ODDPARITY; break; }

switch ( m_eStop ) { case SStop::ONE: dcb.StopBits=ONESTOPBIT; break; case SStop::ONEANDHALF: dcb.StopBits=ONE5STOPBITS; break; case SStop::TWO: dcb.StopBits=TWOSTOPBITS; break; }

dcb.ByteSize = 8; dcb.fBinary = true;

switch ( m_eFlow ) { case SFlow::NONE: { dcb.fOutxCtsFlow=false; dcb.fOutxDsrFlow=false; dcb.fDtrControl=DTR_CONTROL_DISABLE; dcb.fDsrSensitivity=false; dcb.fOutX=false; dcb.fInX=false; }; break; case SFlow::HARDWARE: { dcb.fOutxCtsFlow=true; dcb.fOutxDsrFlow=true; dcb.fDtrControl=DTR_CONTROL_DISABLE; dcb.fDsrSensitivity=false; dcb.fOutX=false; dcb.fInX=false; }; break; case SFlow::XONXOFF: { dcb.fOutxCtsFlow=false; dcb.fOutxDsrFlow=false; dcb.fDtrControl=DTR_CONTROL_DISABLE; dcb.fDsrSensitivity=false; dcb.fOutX=true; dcb.fInX=true; dcb.XoffChar=m_cXOffChar; dcb.XonChar=m_cXonChar; }; break; }

if ( !SetCommState( m_hCom, &dcb ) ) { CloseHandle( m_hCom ); m_hCom = NULL; return ( false ); }

PurgeComm( m_hCom, PURGE_RXABORT ); PurgeComm( m_hCom, PURGE_RXCLEAR ); PurgeComm( m_hCom, PURGE_TXABORT ); PurgeComm( m_hCom, PURGE_TXCLEAR );

return true;

Reply to
Sebastian Bialy

Ja poddam jeszcze jedną ścieżkę, którą możesz sprawdzić, chociaż zastosowanie port monitora sysinternalsów - dla mnie zawsze daje dobre wyniki. Tą ścieżką jest sprawdzenie czy jakiś sterownik np. sterownik drukarki - nie okupuje portu szeregowego. Ja spotkałem się z podobnymi problemami wiele razy.

Napisałeś, że nawet reinstalacja Windy nie dała rezultatu. Niestety tutaj: "ta sama osoba instalująca system 3 razy - 3 razy zainstaluje go tak samo" - mam tu na myśli wszystkie standardowe rzeczy (sterowniki, programy), które potrzebne są Ci na tym konkretnym stanowisku. Oprócz standardowych "okupantów" portów szeregowych takich jak sterowniki drukarek (do etykiet), można wymienić ActiveSync'a - sprawdź jego konfigurację - o ile jest zainstalowany.

Dobrym testem jest wyłączenie portu z poziomu menedżera urządzeń na chwile i ponowne jego włączenie - jeśli po takim zabiegu twój program będzie w stanie wymusić parametry transmisji - to oznacza, że albo winien jest właśnie jakiś sterownik (lub program) lub też może port został uśpiony przez jakiś mechanizm oszczędzania energii.

To tylko dodatkowe wskazówki, które mogą Ci pomóc.

Reply to
PrzemekD

Niby wygląda OK.

Ale jak patrzę na swoje jakieś stare źródła to ustawiałem xonchar i xoffchar na różne wartośći (mimo, że nie korzystałem z xon/xoff (!) ) bo inaczej nie chciało działać (?). No i trochę więcej pól wypełniam; pamiętam miałem kiedyś problemy jeśli jawnie nie wypełniłem rozmiaru dcb. Więcej nie pamiętam :-).

Poniższy kod mi działa zawsze (być może zawiera jakieś nonsensy ale go nie pielęgnuje):

/*********************************************************/ HANDLE CPort::Open(char *p) { HANDLE fd; int il_prob; //ilosc prob otwarcia portu szeregowego #ifdef _WIN32 char port[20]; COMMTIMEOUTS ct; char xxxx[6]; DCB dcb; strcpy(port,p); strncpy(xxxx,port,4);

*(xxxx+4)=0x0; il_prob=30; while ((fd=CreateFile(xxxx,GENERIC_READ | GENERIC_WRITE,0,NULL,OPEN_EXISTING,0,NULL))==INVALID_HANDLE_VALUE && il_prob) { il_prob--; sleep(270); fprintf(stderr,"Konflikt\r\n"); continue; } fprintf(stderr,"--Prób:%d--\r\n",il_prob);

if (fd==INVALID_HANDLE_VALUE) { fprintf(stderr,"nie mořna otworzyĘ portu %s",p); return INVALID_HANDLE_VALUE; } ::GetCommState(fd,&dcb); //EscapeCommFunction(comdi,CLRRTS); if (!::BuildCommDCB(port,&dcb)) { fprintf(stderr,"BŽţd DCB %s",p); ::CloseHandle(fd); return INVALID_HANDLE_VALUE; } //dcb.BaudRate=9600; dcb.DCBlength=sizeof(dcb); dcb.fDsrSensitivity=FALSE; dcb.fBinary=1; dcb.fOutX=FALSE; dcb.fInX=FALSE; dcb.fErrorChar=FALSE; dcb.fNull=FALSE; dcb.fRtsControl=RTS_CONTROL_ENABLE; //14012000 bylo zero dcb.fDtrControl=DTR_CONTROL_ENABLE; //14012000 nie bylo wcale dcb.fAbortOnError=FALSE; dcb.XonChar=0; //muszţ byĘ rŰřne dcb.XoffChar=1; // dcb.fOutxCtsFlow=0; dcb.fOutxDsrFlow=0; if (!SetCommState(fd,&dcb)){ char ss[250]; fprintf(stderr,"Nie mořna ustawiĘ parametrŰw portu %s",p); CloseHandle(fd); return INVALID_HANDLE_VALUE;} EscapeCommFunction(fd,SETRTS); EscapeCommFunction(fd,SETDTR); if (!SetupComm(fd,1000,1000)) { fprintf(stderr,"Nie mořna zarezerwowaĘ pamiÍci na kolejki %s",p); CloseHandle(fd); return INVALID_HANDLE_VALUE; } ct.ReadIntervalTimeout=250; ct.ReadTotalTimeoutMultiplier=1; ct.ReadTotalTimeoutConstant=3000; ct.WriteTotalTimeoutMultiplier=0; ct.WriteTotalTimeoutConstant=2000; if (!SetCommTimeouts(fd,(LPCOMMTIMEOUTS)&ct)){ fprintf(stderr,"BŽţd portu %s",p); ::CloseHandle(fd); return INVALID_HANDLE_VALUE;} #else

Reply to
programista

Może jest to problem z liniami sterującymi RTS, DTR? Spróbuj je ustawić po otwarciu portu. System po otawarciu portu różnie ustawia te linie. Natomiast Hyper Terminal sam z siebie na dzień dobry sam je włącza. Być może urządzenie po drugiej stronie wymaga podniesienia tych linii (odpowiednio CTS i DSR).

Jesli zawodowo zajmujesz się RS-232, to polecam tester linii VT-24 z Yuko. Niezastapiony do sprawdzania, co się dzieje z liniami i do podglądania komunikacji.

Reply to
LukaszS

A sprawdz na jakeijs dziala i na jakiej powinien.

Bo mi tak chodzi po glowie .. masz plyte z kosciami szybszymi niz 115200 ? moze nie ma do niej odpowiednich driverow zainstalowanych ?

Moze MS zna problem i w HT dorzucil cos ustawiajace prawidlowo ?

Ewentualnie .. piszesz "cos blokuje" .. moze jakis faks itp ?

J.

Reply to
J.F.

Będę zerkał, chwilowo do komputera dostępu nie mam.

Czysty win XP z płyty i nic poza moimi programami.

Nie, to odpada. Instaluje tak samo jak inne. To się nie da nic uszkodzić :)

ActiveSynca nie ma. Mam z nim kłopot na laptopie więc doskonale wiem jak debilne ma pomysły co do moich portów szeregowych.

Robione parę razy :)

Dzieki. Ale coś mi się zdaje że i tak wywale to badziewie na rzecz linuxa. Tam jest szansa że jeśli coś nie działą to się dowiem dlaczego.

Reply to
Sebastian Bialy

Sprawdzam łacząc nullmodemem z innym kompem. Na nim pracuje terminal w

1200. Otwieram mój program, każe się połączyć na 9600, API mówi że ok i transmisja leci ... na 1200. Po drugiej stronie odbieram prawidłowe znaki.

Diabli wiedzą, to jakieś VIA z Duronem na pokładzie.

Hmm raczej nie, sprawdzałem na gołej instalce a potem na Via Hyperion czy jakoś tak. Z resztą Linux Live wykrywa je jako normalne porty i tam działają poprawnie (da się ustawiać prędkość bez żadnych sztuczek).

O to to :) Zapewne Hyperterminal zna sztuczkę o kórej nie ma słowa w MSDN.

Nie nie. Nie ma nic. Goły XP + mój program.

Reply to
Sebastian Bialy

A zadaj mu 19200 - skoczy na 2400 czy nie ?

Ale podejrzewam ze 460 czy 920k to one maja. A to sie niestandardowo wlacza .. to i trzeba zadbac o wylaczenie.

No wlasnie - a co windows o tym porcie mowi, jaka predkosc maksymalna ?

Skoro system jej nie zapewnia to i w MSDN nie ma :-)

J.

Reply to
J.F.

Nie :) Sprawdziłęm wszystkie prędkości - po ustawieniu zawsze leci 1200. Do czasu odlapenia i zamknięcia HT. Potem już ładnie się ustawia.

_Być może_ sterowniki widnowsowe mają buga. Nie mam jak sprawdzić, bo to przecież closed source :/

Nie mma już go pod ręką. Nie mam jak sprawdzić.

W MSDNie nie ma paru rzeczy które być powinny. Wcale się nie zdziwie, że MS ma w d... rozwijanie dokumentacji i poprawianie błedów skoro COMów nie uzywa się już praktycznie @home. Jeszcze jeden powód do migracji.

Reply to
Sebastian Bialy

Ale w tym momencie to przestaje to podejrzewac. Raczej jakies blokowanie portu.

J.

Reply to
J.F.

po co zwierac te piny?

Reply to
Q

ograniczasz / kwantyzujesz sobie baud rate ? gdzie tu sens, gdzie logika ? :) /i te zbedne linie kodu.. :)

Reply to
Q

mozna uzyc PortMonitor'a i sprawdzic co robi HT (jakie funkcje odpala, z jakimi parametrami) a potem odpalac te same :)

Reply to
Q

to magiczne okno jest do dupy, bo np. nie mozesz sobie ustawic dowolnego baud rate (np. 10417 bps :)

Reply to
Q

co to za flaga? pierwsze widze taka przy otwieraniu COM'a.... /ponoc COM'a otwiera sie w jednym z dwoch trybow: FILE_FLAG_OVERLAPPED albo 0;

a wypelnic pole dcb.DCBlength nie laska? :) /np. dcb.DCBlength = sizeof(dcb);

oj, chyba nie czytales Serial Communications in Win32:

formatting link

a nie prosciej po prostu wpisac do .BaudRate wartosc? :)

mogles juz dac tak: PurgeComm(m_hCom, PURGE_RXCLEAR | PURGE_TXCLEAR | PURGE_RXABORT | PURGE_TXABORT); :)

a sprobuj wypelnic pola dcb nie wprost tylko funkcja BuildCommDCB();

ps. a moze miales farta, ze dzialalo na innych kompach a nie pecha, ze na tym nie dziala?.. ;)

Reply to
Q

ponoc zakres COM'ow to <1, .., 256>;

Reply to
Q

jakby port byl zajaety to by nie mogl go otworzyc; /no chyba, ze jakos automagicznie sie zawiesil na czyms blizej nieokreslonym...

Reply to
Q

ElectronDepot website is not affiliated with any of the manufacturers or service providers discussed here. All logos and trade names are the property of their respective owners.