0

我对 Modbus 协议完全陌生。我的设置由三个具有不同地址的设备组成。它们都通过 RS232 连接到 COM1。我使用 Modbus Poll 来检查输入数据,它工作正常。我现在要做的是读取 vc++ (MFC) 应用程序中的保持寄存器。对于串行通信,我使用 MSComm 类。我写了一些代码,但我根本没有输入。

我目前的代码:

BOOL Crs232test4Dlg::OpenConnection ()
{
    char error [513];

    try
    {
        if (! m_MSComm.GetPortOpen ())
        {
            m_MSComm.SetCommPort (1);
            m_MSComm.SetSettings ("9600,N,8,1");
            m_MSComm.SetInputLen (4);
            // Receive Data as Text
            m_MSComm.SetInputMode (0);
            m_MSComm.SetPortOpen (true);
            m_MSComm.SetCommID (1);
           return m_MSComm.GetPortOpen ();
        }
        AfxMessageBox ("Success!!!!", MB_OK);
        return TRUE;
    }

    catch (CException *e)
    {
        e->GetErrorMessage (error, 512);
        AfxMessageBox (error, MB_OK);
        return FALSE;
    }
}


void Crs232test4Dlg::OnVaisalaComm ()
{
    if (m_MSComm.GetCommEvent () == 2)
    {
        COleVariant in_dat;
        in_dat = m_MSComm.GetInput ();
        Sleep (100);
        CString strInput (in_dat.bstrVal);
        m_Input = m_Input + strInput;
        UpdateData (FALSE);
    }
}

我现在想推出 m_Input,但它并没有改变一点。在设置 SetCommID 时,我也会收到警告(属性是只读的),我认为这并不重要。

谁能指导我,因为我现在真的一无所知。

问候

编辑:根据一个通信示例,我试图像处理文件一样处理设备。

m_hCom = CreateFile(m_sComPort, 
        GENERIC_READ | GENERIC_WRITE,
        0, // exclusive access
        NULL, // no security
        OPEN_EXISTING,
        0, // no overlapped I/O
        NULL); // null template
// :(colon) Address=1 Function=3 Starting register= 40001 (To write 400001 or 0?)
Registers to read=4 checksum CR LF
char    strASCII[] = "3A 30 31 30 33 30 30 30 30 30 30 30 34 46 38 0D 0A";

bWriteRC = WriteFile (m_hCom, strASCII, strlen(strASCII), &iBytesWritten, NULL);

memset(sBuffer,0,sizeof(sBuffer));
// Reading output of the M3
bReadRC = ReadFile (m_hCom, &sBuffer, 1, &iBytesRead, NULL);

if (bReadRC && iBytesRead > 0)
    {
        sResult = sBuffer;
    }
    else
    {
        sResult = "Read Failed";
        dwError = GetLastError();

        sprintf(sMsg, "Read length failed: RC=%d Bytes read=%d, "
                "Error=%d ",
                bReadRC, iBytesRead, dwError);
        AfxMessageBox(sMsg);
    } 

我收到读取长度失败错误。strASCII 不正常分离,现在只是为了更好地概述。我已经检查了 Modbus Poll 中的通信。我的输出是正确的,但它似乎没有得到数据。

编辑:我明白了。非常感谢您的帮助。我输入了错误的校验和。

4

3 回答 3

2

MODBUS 远比通过串口读取简单数据要复杂得多。Is 是一种面向复杂数据包的协议,具有复杂的同步特性。它指定了主从操作。通过使用 MSComm 或超级终端,您不会从 MODBUS 设备中得到任何东西。MODBUS 协议已经有很好的文档记录,但实现起来并不容易。也存在许多变化。可能需要几千行代码才能获得基础知识。一个已知且成熟的商业图书馆可能是更好的方法,这还包括技术支持,这对于这类产品至关重要。例如,SuperCom,一个商业软件库,为串行和 TCP 数据通信提供 MODBUS,还支持 MFC。还包括客户端(主)和从属功能。它为知名编译器提供了许多示例。那里肯定存在更多的商业解决方案。

于 2015-11-12T11:41:49.663 回答
1

不是答案,而是解决问题的指南。

  • 你最好的朋友应该是:

    1) 空调制解调器 232female<->232female 电缆与第二台具有 com 端口的计算机(或带 USB-> 串行转换器的笔记本电脑)......通过您自己的线对线焊接电缆可能是最好的解决方案。

    2) Windows 超级终端简单但可靠的应用程序预装在大多数 Windows 上...以 comPort 模式启动,具有与模块相同的比特率/奇偶性/停止位参数。


  • 首先通过在 comps 和“聊天”几句上运行 hterm 来检查连接和电缆是否正常
  • 第二次检查您的程序是否正常,方法是在第一个 comp 上运行它,然后在其他 comp 上运行 hterm
  • Modbus 模块有时在 Master 发送对模块地址的一些查询之前不发送任何内容,因此您的程序可能需要先发送一些内容(对于该调查,您可以记录您的 modbusPool 与连接的其他 comp 而不是 MBUS 模块)

...关于 Windows 信号队列和 MSCOmm 类的所有方面可能没问题,但是为了消除项目启动中通信失败的所有可能原因,也许你应该更喜欢简单的威胁 COM 端口作为文件,并在一些 while 循环中读取它...此示例的一些简短版本...在启动时设置串行参数并读取名为 comX.

上面的链接在下载时具有良好的 cSerialClass 实现,但没有任何错误检查的简单入门在 pastebin

于 2013-02-04T17:45:00.740 回答
1

这里有两个问题:

1/ 您不能将三个设备通过 RS232 连接在一起。RS232 是点对点的,这意味着只能将两个设备连接在一起。

2/ 从站仅在主站查询时发送数据。如果主机不先发送 MODBUS 请求,您将永远不会收到从机的回复。

PS:我感觉 m_MSComm.SetCommID() 应该在端口打开之前调用,而不是之后。

为了创建正确的请求,您可以参考标准:

第一个文档将指导您如何构建请求 (PDU),而第二个文档详细说明了如何将请求封装在适合串行通信的“传输”帧 (ADU) 中。

最常见的请求是“读取保持寄存器”(功能#3)。如果您的从设备具有地址 5,并且您想读取从地址 10 开始的两个寄存器,那么您的请求将类似于:0x05 0x03 0x000A 0x0002 0x???? (其中 '????' 是 CRC16 值,我懒得计算)。

于 2013-02-05T11:34:23.497 回答