我正在按照教程here与串行端口进行通信
打开然后关闭串口的主要代码如下:
HANDLE hComm;
hComm = CreateFileA((LPCSTR)"COM8", //port name
GENERIC_READ | GENERIC_WRITE, //Read/Write
0, // No Sharing
NULL, // No Security
OPEN_EXISTING,// Open existing port only
0, // Non Overlapped I/O // FILE_FLAG_NO_BUFFERING, // copied from the MFC version
NULL); // Null for Comm Devices
if (hComm == INVALID_HANDLE_VALUE){
DWORD err = GetLastError();
printf("Error in opening serial port\n");
printf("err = 0x%x\n", err);
}
else
printf("opening serial port successful\n");
CloseHandle(hComm);//Closing the Serial Port
如果我使用CreateFile()
,代码可以正常编译,但是没有打开串行端口(我收到Error in opening serial port
消息)
在玩了一段时间之后,我发现CreateFileA()
成功打开了串行端口(而我什至发现这的唯一原因是,当我在Google搜索CreateFile()
函数时得到了CreateFileA()
的MSDN定义页作为第一个结果
我在Google周围搜索,但是我找不到两者之间的区别。我找到了this,它说我应该始终CreateFile()
,其余的应该由编译器来完成,但这在我的情况下不起作用,仅在我专门使用CreateFileA()
CreateFile()
和CreateFileA()
有什么区别,我应该在程序中使用哪一个进行基本的串行端口通信?
Windows 10
Visual Studio 2013 Express
答案 0 :(得分:7)
此处需要有关Windows API的一些解释:微软很早就引入了Unicode。当时,他们决定以16位表示Unicode字符。我想当时这是一个有效的决定。因此,Microsoft平台上的wchar_t
是16位宽的(Unicode)文本存储在wchar_t
中-这具有每个字符都具有相同宽度的优点。缺点是处理char
的现有API已不再兼容。
如今,具有32位Unicode代码点,这看起来很愚蠢-Microsoft平台上的Unicode文本是使用UTF-16编码的,因此您有两个缺点:与基于简单char
的简单字符串不兼容多字符序列。在许多其他平台上,wchar_t
是32位宽,Unicode要么存储在这些wchar_t
中,要么在“正常” char
中编码为UTF-8。
但是回到Microsoft API:为了解决此问题,他们将所有处理字符串的API调用重命名为带有A
后缀,并引入了第二组相同的调用,采用了wchar_t
,后缀为W
的Unicode变体。取决于编译时开关UNICODE
,预处理器会将原始名称映射为带后缀的实名。
您可能知道,C中的字符串文字的类型为char *
。要制作类型为wchar_t *
的字符串文字,您需要在其前面加上L
。为了在设置UNICODE
时自动执行此操作,提供了另一个宏:_T()
。因此,您期望在代码中执行的操作是将任何字符串文字都包装在_T()
中,恰好在定义了L
时,它将以UNICODE
为前缀。
因此,此行:
hComm = CreateFileA((LPCSTR)"COM8"
应改为:
hComm = CreateFile(_T("COM8")
在LPCSTR
和LPWCSTR
上的字眼:如今它们等效于char *
和wchar_t *
。因此,铸造是不必要的。这些名称的原因是向后兼容具有分段内存和“远指针”的古代系统。只要您不需要为win16编译代码,就不要理会它们。
最后,我个人认为:Windows知道Unicode的时间已经很长了(IIRC已经与Win95一起使用),并且如今已成为标准。您不太可能想针对不支持unicode的Windows系统。您很可能想编写一些可移植的代码,然后问题是对Unicode的处理不同(Windows上为wchar_t
,在大多数其他系统上为UTF-8的char
,UTF-8也是主要的在互联网上)。
为此,我更喜欢始终定义UNICODE
,对于Windows API所需的任何常量字符串(例如您的wchar_t
调用),请使用CreateFile()
字符串常量。 L
),并使用UTF-8将所有字符串内部存储在char
中,仅在需要将它们传递给Windows API时进行转换。有两个函数可以进行转换:MultiByteToWideChar()
和WideCharToMultiByte()
。这样,您可以轻松地为使用UTF-8的其他操作系统的API编写适配器。