Przekazywanie nazwy portu COM

0

Cześć wszystkim,

W programie do obsługi portu COM używam makra CreateFile(). Makro to przyjmuje jako argument nazwę portu w formacie LPCWSTR, które z kolei jest stałym ciągiem znaków wchar_t.

typedef wchar_t WCHAR;

typedef Null_terminated CONST WCHAR *LPCWSTR, *PCWSTR;

aż w końcu<code class="c">_In_ LPCWSTR lpFileName,

Póki co możliwe było przekazywanie nazwy portu poprzez makro TEXT(quote), dzięki czemu program działa bez zarzutu, jednak wymusza to "zadedykowanie" programu pod dany port poprzez sztywne wpisanie nazwy w kodzie. Chciałbym jednak mieć możliwość wpisania nazwy portu po uruchomieniu programu (przykładowo niech program czeka na jej wpisanie poprzez scanf() ).
Próbowałem przekazać nazwę portu jako ciąg znaków na wiele różnych sposobów kierując się typami zdefiniowanymi na podstawie wchar_t. Nie udało się jednak zrobić tego poprzez żaden ze sposobów, a tylko dwa z wypróbowanych przeze mnie nie kończą się błędem, jednak port nie zostaje otwarty. Sposób ten to po prostu brzydkie rzutowanie:

const char SomeText[] = "COM1";
TCHAR *PortName = (TCHAR*)SomeText;

lub

wchar_t ConstText[] = {(wchar_t)"COM2"};
/*i wszelkie inne kombinacje, których należy się wstydzić*/

Moje pytanie brzmi: jak przekazać nazwę pobraną przez scanf (lub jako argument main() ) do makra CreateFile() ? Nie mogłem nigdzie tego znaleźć i skończyły mi się pomysły... :(

Pozdrawiam :)

1
Bartosz36 napisał(a):

W programie do obsługi portu COM używam makra CreateFile(). Makro to przyjmuje jako argument nazwę portu w formacie LPCWSTR,
Błagam, to nie jest makro. To jest funkcja udostępniana przez WinAPI.

Ja zrobiłem to trochę inaczej. Używam inta jako numeru portu COM. A to dlatego, że za pomocą nazwy COMx dostaniesz się tylko do portów 1-9. Żeby dostać się do wyższych trzeba zrobić tak:
\\.\COM10

Oto mały fragment działającego kodu:

#include <stdio.h>
#include <windows.h>
#pragma hdrstop


#pragma argsused
int main(int argc, char* argv[])
{
  char szCom[100];
  HANDLE hCom;

  sprintf(szCom,"\\\\.\\COM%d",10);
  hCom = CreateFile(szCom,GENERIC_READ|GENERIC_WRITE,0,NULL,OPEN_EXISTING,NULL,NULL);

  return 0;
}
//---------------------------------------------------------------------------

Oczywiście numer portu pobierz sobie od użytkownika albo wczytaj z ustawień i powinno pójść

0

Dzięki za odpowiedź, dam znać jak wypróbuję, ale dzięki za pomysł :)

Co do makra i funkcji, masz rację:

WINBASEAPI
HANDLE
WINAPI
CreateFileW(
    _In_ LPCWSTR lpFileName,
    _In_ DWORD dwDesiredAccess,
    _In_ DWORD dwShareMode,
    _In_opt_ LPSECURITY_ATTRIBUTES lpSecurityAttributes,
    _In_ DWORD dwCreationDisposition,
    _In_ DWORD dwFlagsAndAttributes,
    _In_opt_ HANDLE hTemplateFile
    );

Po prostu popatrzyłem na to:

#ifdef UNICODE
#define CreateFile  CreateFileW
#else

i bezmyślnie z rozpędu napisałem, że to makro :(

Pozdrawiam :)

0

Nie działa :(
Nazwa przekazywana jest w prawidłowym formacie, jednak port nie zostaje otwarty. Póki co jedyna możliwość to nadal makro TEXT(quote).
Myślałem nad tym, by napisać takie makro, które przekazywałoby ciąg do makra TEXT() nie w postaci ciągu w cudzysłowie, ale w postaci tablicy char... ale jak to zrobić?

0

A czy aby nie korzystasz z unicode? Bo makro TEXT zachowuje się różnie w zależności od tego czy chcemy używać unicode, czy nie. Teraz doczytałem, że chcesz konwerterować na LPCWSTR a moja wersja daje zwykłego chara. Nie mam pod ręką komputera z portem COM, ale ta wersja którą podałem działa na pewno. Więc może spróbuj tak:

  wchar_t szCom[100];
  HANDLE hCom;

  wprintf(szCom,L"\\\\.\\COM%d",10);
  hCom = CreateFileW(szCom,GENERIC_READ|GENERIC_WRITE,0,NULL,OPEN_EXISTING,NULL,NULL);
0

Build'a oczywiście przechodzi, jednak port nie zostaje otwarty.
Mam dwa warningi, na które fajnie byłoby zwrócić uwagę:

'function' : 'DWORD' differs in levels of indirection from 'void *'
'CreateFileW' : different types for formal and actual parameter 6

a oba tyczą się tej jednej linijki:

HANDLE PortHandling = CreateFile(PortName, GENERIC_READ|GENERIC_WRITE, FALSE, NULL, OPEN_EXISTING, NULL, NULL);

Nie wiem czym jest 'function', nie mogłem znaleźć o co może mu chodzić, ale wiele z argumentów w CreateFile jest tego formatu DWORD, jednak nie widzę by któreś z użytych przeze mnie było typu void *
Co do drugiego, powinien być typu DWORD, czyli unsigned long. Po zmianie parametru na pożądany typ build przechodzi bez warningów, jednak port pozostaje zamknięty...

Może jest coś jeszcze o czym zapominam?

2

Nie czytałem całego wątku, ale jedno rzuca mi się w oczy! Brak dwukropka!
Nazwa portu RS-232 na windows to:

"com1:"

A co do samego problemu, to albo wczytujesz dane do wchar* mp tak:

wchar_t fillename[0x100];
wscanf(L"%ls", filename);

Albo robisz jak napisał @Mr.YaHooo

1
MarekR22 napisał(a):

Nie czytałem całego wątku, ale jedno rzuca mi się w oczy! Brak dwukropka!
Nazwa portu RS-232 na windows to:

"com1:"

Ale do funkcji CreateFile nie podaje się tego w ten sposób. https://msdn.microsoft.com/en-us/library/windows/desktop/aa363858%28v=vs.85%29.aspx

Communications Resources

The CreateFile function can create a handle to a communications resource, such as the serial port COM1. For communications resources, the dwCreationDisposition parameter must be OPEN_EXISTING, the dwShareMode parameter must be zero (exclusive access), and the hTemplateFile parameter must be NULL. Read, write, or read/write access can be specified, and the handle can be opened for overlapped I/O.

To specify a COM port number greater than 9, use the following syntax: "\.\COM10". This syntax works for all port numbers and hardware that allows COM port numbers to be specified.
Poza tym ten wycinek kodu który zaprezentowałem działa i jest wzięty z realnego produkcyjnego kodu (oczywiście wyciąłem dużą część, a zostawiłem to co najważniejsze) :)

0

@MarekR22 Twój sposób działa poprawnie, dzięki wielkie :)

1

jednak nie widzę by któreś z użytych przeze mnie było typu void *

Jak nie, a NULL? w C jest zdefiniowane jako (void*)0, w przeciwieństwie do C++ gdzie ma wartość 0.

Dawaj 0 zamiast NULL tam gdzie jest parametr DWORD.

1 użytkowników online, w tym zalogowanych: 0, gości: 1