VS2013下(MFC编程) 与 Omron PLC 串口通信,工控机案列


//  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     {
    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端有应答)

你可能感兴趣的:(Vs2013,and,MFC,PLC,串口,通讯)