射频识别技术课程实验–模拟串口间的通信
前期准备
串口调试小助手:
模拟串口工具:
Visual Studio 2022:
测试代码(c++):
#include<iostream>
#include<Windows.h>
using namespace std;
int main()
{
system("color 3F");
HANDLE hCom = CreateFile("\\\\.\\COM2", GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING,// 指定串口编号
FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, NULL);
if (INVALID_HANDLE_VALUE == hCom)
{
cout << "serial open failed" << endl;
system("pause");
return -1;
};
//设置串口
//1、设置输入输出缓冲区大小
SetupComm(hCom, 1024, 1024);
//2、设置时延
COMMTIMEOUTS TimeOuts;
TimeOuts.ReadIntervalTimeout = 1000;
TimeOuts.ReadTotalTimeoutMultiplier = 500;
TimeOuts.ReadTotalTimeoutConstant = 5000;//设定写超时
TimeOuts.WriteTotalTimeoutMultiplier = 500;
TimeOuts.WriteTotalTimeoutConstant = 2000;
SetCommTimeouts(hCom, &TimeOuts);
//3、DCB结构体
DCB dcb;
GetCommState(hCom, &dcb);
dcb.BaudRate = 9600;
dcb.ByteSize = 32;
dcb.StopBits = 1;
SetCommState(hCom, &dcb);
//4、清空硬件的通信错误,清空输入输出缓冲,为W/R做准备
PurgeComm(hCom, PURGE_RXCLEAR | PURGE_TXCLEAR | PURGE_RXABORT | PURGE_TXABORT);
//5、发送串口信息
char buffer[] = { 0XFE, 0X03, 0X04, 0X00, 0X03, 0X00, 0X00, 0X00, 0X00, 0X00, 0XFA };
DWORD dwBytesToWrite = sizeof(buffer);
DWORD dwBytesRealWrite;
DWORD dwErrorFlags;
COMSTAT comStat;
OVERLAPPED osWrite;
//memset(&osWrite,0,sizeof(OVERLAPPED));
osWrite.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
osWrite.Offset = 0;
osWrite.OffsetHigh = 0;
//清除硬件通信错误;
ClearCommError(hCom, &dwErrorFlags, &comStat);
BOOL bWriteStatus;
bWriteStatus = WriteFile(hCom, buffer, dwBytesToWrite, &dwBytesRealWrite, &osWrite);
int m = GetLastError();
if (!bWriteStatus)
{
if (GetLastError() == ERROR_IO_PENDING)
{
WaitForSingleObject(osWrite.hEvent, 2000);
//清理IO缓冲区;
PurgeComm(hCom, PURGE_RXCLEAR | PURGE_TXCLEAR | PURGE_RXABORT | PURGE_TXABORT);
}
else
{
cout << "failed to send" << endl;
system("pause");
return -1;
}
PurgeComm(hCom, PURGE_RXCLEAR | PURGE_TXCLEAR | PURGE_RXABORT | PURGE_TXABORT);
}
PurgeComm(hCom, PURGE_RXCLEAR | PURGE_TXCLEAR | PURGE_RXABORT | PURGE_TXABORT);
//6、接收串口信息
unsigned char lpInBuffer[1024];
DWORD dwBytesRead;
OVERLAPPED osRead;
memset(&osRead, 0, sizeof(OVERLAPPED));
BOOL bReadStatus;
DWORD dwRealRead;
while (1)
{
dwBytesRead = 1024;
osRead.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
ClearCommError(hCom, &dwErrorFlags, &comStat);
dwBytesRead = min(dwBytesRead, (DWORD)comStat.cbInQue);
if (!dwBytesRead)
{
//cout << "no data to be read" << endl;
Sleep(1000);
continue;
}
bReadStatus = ReadFile(hCom, lpInBuffer, dwBytesRead, &dwRealRead, &osRead);
if (!bReadStatus)
//如果ReadFile函数返回FALSE
{
if (GetLastError() == ERROR_IO_PENDING)
//GetLastError()函数返回ERROR_IO_PENDING,表明串口正在进行读操作
{
WaitForSingleObject(osRead.hEvent, 2000);
//使用WaitForSingleObject函数等待,直到读操作完成或延时已达到2秒钟
//当串口读操作进行完毕后,osRead的hEvent事件会变为有信号
PurgeComm(hCom, PURGE_TXABORT | PURGE_RXABORT | PURGE_TXCLEAR | PURGE_RXCLEAR);
short *temp = new short[dwRealRead + 1];
for (int i = 0; i < dwBytesRead; ++i)
{
temp[i] = lpInBuffer[i];
printf("%02X", temp[i]);
}
cout << endl;
/*delete[] temp;*/
}
else
cout << "failed to read" << endl;
}
else
{
short *temp = new short[dwRealRead + 1];
for (int i = 0; i < dwBytesRead; ++i)
{
temp[i] = lpInBuffer[i];
printf("%02X", temp[i]);
}
cout << endl;
delete[] temp;
}
Sleep(1000);
PurgeComm(hCom, PURGE_RXCLEAR | PURGE_TXCLEAR | PURGE_RXABORT | PURGE_TXABORT);
}
PurgeComm(hCom, PURGE_RXCLEAR | PURGE_TXCLEAR | PURGE_RXABORT | PURGE_TXABORT);
system("pause");
}
实验过程
基础实验
-
模拟两个串口
-
打开两个串口调试小助手,分别打开上一步模拟的两个串口,这里我创建的串口名字为“COM1”和“COM2”。
-
测试串口连通性:
可以看到串口连通性正常,两端都可以互相发送数据。
-
打开Visual Studio 2022,新建空项目
-
将准备好的代码放在源文件中,运行调试:
发现提示serial open failed,这是因为我们一开始打开了两个串口,并且代码中指定串口编号为COM2,但是COM2已经打开了,所以报错串口开启失败。
HANDLE hCom = CreateFile("\\\\.\\COM2", GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING,// 指定串口编号
-
于是我们关闭COM2,保留COM1
这时再次运行C++程序,使用串口COM1发送数据:
此时我们的C++程序扮演的角色其实就是串口COM2,接收到串口COM1发送的数据,至此,基础实验部分就完成了。