// CDetectDlg 主 类 名,
//打开串口
HANDLE CDetectDlg::KSrialOpen(){
/*
Overlapped.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
Overlapped.Offset = 0;
Overlapped.OffsetHigh = 0;
*/
BOOL state;
DCB SerialDCB;
LPCTSTR comx = "COM1";//电脑的COm1 端口
hCom = CreateFile(comx, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);//FILE_FLAG_OVERLAPPED FILE_ATTRIBUTE_NORMAL
//FILE_ATTRIBUTE_NORMAL|FILE_FLAG_OVERLAPPED
/*
在串口中必须设置为OPEN_EXISTING。表示不能创建新端口只能打开已有的端口。
FILE_ATTRIBUTE_NORMAL|FILE_FLAG_OVERLAPPED, //重叠方式
*/
if (hCom == INVALID_HANDLE_VALUE)
{
TRACE("----CreateFile error :%d---\n", GetLastError());//得到返回的错误值
return INVALID_HANDLE_VALUE;
}
//设置超时时间
COMMTIMEOUTS Timeouts;
Timeouts.ReadIntervalTimeout = MAXDWORD;//读超时
Timeouts.ReadTotalTimeoutMultiplier = 0;
Timeouts.ReadTotalTimeoutConstant = 100;
Timeouts.WriteTotalTimeoutMultiplier = 0;//写超时
Timeouts.WriteTotalTimeoutConstant = 100;
if (!SetCommTimeouts(hCom, &Timeouts))
{
AfxMessageBox(_T("无法设置超时参数!"));
TRACE("---SetCommTimeouts error :%d---\n", GetLastError());
CloseHandle(hCom);
return INVALID_HANDLE_VALUE;
}
state = GetCommState(hCom, &SerialDCB);
SerialDCB.BaudRate = CBR_115200;//9600 115200
SerialDCB.ByteSize = 7;/* number of bits/byte , 4-8 */
SerialDCB.Parity = EVENPARITY;/* 0-4 = None ,odd,even,mark, space 无奇偶检验 */ /* EVENPARITY 偶*/
SerialDCB.StopBits = TWOSTOPBITS;/*0,1,2 = 1,1.5,2 */ //TWOSTOPBITS
state = SetCommState(hCom, &SerialDCB);
if (!state)
{
AfxMessageBox(_T("无法设置串口状态参数!"));
TRACE("---SetCommState error :%d---\n", GetLastError());//得到返回的错误值
CloseHandle(hCom);
return INVALID_HANDLE_VALUE;
}
//设置缓冲区大小
state = SetupComm(hCom, 1024, 1024);//SERIAL_RECV_BUFFER缓冲区大小 SERIAL_SEND_BUFFER = 100
if (!state)
{
AfxMessageBox(_T("无法设置串口缓冲区大小!"));
TRACE("---SetCommState error :%d---\n", GetLastError());//得到返回的错误值
CloseHandle(hCom);
return INVALID_HANDLE_VALUE;
}
PurgeComm(hCom, PURGE_TXABORT | PURGE_RXABORT);//清空缓冲区 PURGE_TXCLEAR | PURGE_RXCLEAR |
/*
PURGE_TXABORT 终止所有正在进行的字符输出操作,完成一个正处于等待状态的重叠i/o操作,他将产生一个事件,指明完成了写操作
PURGE_RXABORT 输入操作,完成一个正在进行中的重叠i/o操作,并带有已设置得适当事件
PURGE_TXCLEAR 这个命令指导设备驱动程序清除输出缓冲区,经常与PURGE_TXABORT 命令标志一起使用
PURGE_RXCLEAR 输入
*/
return hCom;
}
void CDetectDlg::FCS(CString &str) // 这个函数是用来把数据校验的
{
CString o, oo, ff, fcs, ol;
int b, l, i;
char o2;
o = str;
b = 0;
l = o.GetLength();
for (i = 0; i<l; i++)
{
o2 = o.GetAt(i);
b = b^o2;
}
ff.Format("%X", b);
if (ff.GetLength() == 1) ff = '0' + ff;
fcs = ff + "*";
oo = o + fcs;
str = oo + "\r";
}
char* CDetectDlg::pack_data() // 发送一个特定的数据 先测试一下 是否能够发送完成 并且返回数据
{
m_send_str = "@00RD00020002";//@00SC02 @00KSCIO 001000
FCS(m_send_str);
TRACE("---pack_data():%s ---\n", m_send_str);
return m_send_str.GetBuffer(0);
}
//读串口信息
int CDetectDlg::ReadData()
{
char readBuffer[1024];
DWORD wCount = 1024;//读取的字节数
BOOL bReadStat;
bReadStat = ReadFile(hCom, readBuffer, wCount, &wCount, NULL);
if (!bReadStat)
{
TRACE("---ReadFile error :%d ---\n", GetLastError());//得到返回的错误值
AfxMessageBox("读串口失败!");
CloseHandle(hCom);
return -1;
}
if (readBuffer[5] == '0' && readBuffer[6] == '0')
{
OnOutputMessage("成功得到PLC返回数据");
}
PurgeComm(hCom, PURGE_TXCLEAR | PURGE_RXCLEAR | PURGE_TXABORT | PURGE_RXABORT);
return 0;
}
//写串口信息
int CDetectDlg::WriteData(HANDLE handle, char *buffer)//send_data
{
unsigned long dwBytesWrite;
DWORD dwErrorFlags;
BOOL bWriteStat;
if (0 == ClearCommError(handle, &dwErrorFlags, &ComStat) )
{
AfxMessageBox("该函数ClearCommError调用失败!");
}
dwBytesWrite = strlen(buffer);
TRACE("---strlen(buffer) :%ld ---\n", dwBytesWrite);//得到返值
bWriteStat = WriteFile(handle, buffer, dwBytesWrite, &dwBytesWrite, NULL);
if (!bWriteStat)
{
TRACE("---WriteFile error :%d---\n", GetLastError());//得到返回的值
AfxMessageBox("写串口信息失败!");
return -1;
}
return 0;
}
int CDetectDlg::all_call()
{
WriteData(hCom, pack_data());
ReadData();
return 0;
}
为了确保C++ 程序能够与PLC串口通讯上,在模式上是这样的,发一个数据,(是往串口写数据),确保PLC接到数据,还要读一下串口(即串口返回的 数据,确保PLC端有应答)