8351|10

69

帖子

0

TA的资源

一粒金砂(中级)

楼主
 

关于modbus通信协议中发送数据的问题 [复制链接]

各位大虾:
      最近在写一份上位机程序,和下位机进行通信,采用的是modbus协议,数据一ASCII代码发送。上位机开发环境是VC++6.0,用MFC做的界面,首先是设置串口参数,串口COM1,波特率是9600,无校验,一个停止位,数据位7位。
不知到该怎样设置发送的数据。
void CModbusDlg::OnModbussend()
{
        // TODO: Add your control notification handler code here
        if (!m_Com->PortOpened())
        {
                AfxMessageBox("通讯串口没有打开!");
                return;
        }
        char* ucharReadFrame;
         CString str;
        m_edtSendView.GetWindowText(str);
        int   num=str.GetLength();
        ucharReadFrame =new   char[num];
        memcpy(ucharReadFrame,(LPCTSTR)str,num);
        m_Com->Send(ucharReadFrame, num);                       
}
bool CComControl::Send(char* pBuff, DWORD dwBytesSend)
{
        if(!PortOpened())        return false;
        BOOL wRes;
        DWORD dwBytesW;
        wRes = WriteFile( m_hCom,
                                          pBuff,
                                          dwBytesSend,
                                          &dwBytesW,
                                          &m_ovWrite
                                        );
       
        if(!wRes)        //there are some data not send
        {               
                if(GetLastError() == ERROR_IO_PENDING)
                {
                        WaitForSingleObject(m_ovWrite.hEvent, 20*1000);        //阻塞呼叫线程,如果出现错误或是超时则返回
                        wRes = GetOverlappedResult( m_hCom,                // 串口设备句柄
                                                                                &m_ovWrite,        // 指向重叠结构
                                                                                &dwBytesW,        // 指向实际字节计数
                                                                                false                // 等待标记
                                                                          );
                        if(!wRes || dwBytesW != dwBytesSend)
                        {
                                ClearInOut();
                                return false;
                        }
                }
                else        // an error occured
                {       
                        ClearInOut();
                        return false;
                }
        }
        return true;
}

a: 起始字符 [①:1位/STX(02H)或“@”(40H)]
?
?
?
选择 STX ( 02H ) - - - ETX (03H)
选择 “@” ( 40H ) - - - “:” (3AH)
b: 机器地址 [②,③:2位]
?
?
?
?
c: 附属地址[④:1位]
?
(3) 基本格式第II部分详解
h: 文本结束字符[?:1位/ETX(03H)]或[“:”(3AH)]
? 表示完成指令接收,可立即开始执行。
I : BCC数据(块校验字符)[?, ?:2位]
?
?
?
?
?
a b c d e g h i
? ? ? ? ?
STX 0 1 1 R 0 0 ---- ETX 3 E CR
STX 0 2 1 W 0 0 ,**** ETX 4 F CR
基本格式第1部分 文本部分基本格式第II部分
起始字符
调节器地址
附属地址
指令类型
数据
文本结束字符
BCC 数据
结束字符
(分界符)
应答代码
声明通讯字符串的起始字符。
收到此字符可作为另一条通讯指令开始的判据。
起始字符与文本结束字符是一一对应的关系。
指定传送指令调节器的地址。
地址可在1-255(十进制)范围内指定。
二进制8位数据(1:0000 0001 - 255:1111 1111)分为前4位与后4位转成ASCII码数据。
②:前4位数据转为ASCII码
③:后4位数据转为ASCII码
机器地址=0(30H,30H)用于广播指令。
SRS10系列支持广播指令。
对广播指令,无论正确与否,都不做应答。
要以ASCII代码发送一串数据,应该怎样编码呢?

比如@011W018C0:00

a b c d e f g h i j
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
STX 0 1 1 R 0 1 0 0 0 … ETX D A CR …
STX 0 2 1 W 0 1 8 c 0 … ETX 0 B CR …
1. 通讯发送格式的解释:
a 通讯的起始符: 第 1 位。STX:(02H)或”@”(40H) 。
b 通讯下位机地址:第2、3 位由8 位二进制组成。地址范围1~98,这8 位二进制被分成
高4 位和低4 位,其中高4 位被送入2 中,低4 位放入3 中,并转换成ASCII 码。
c 通讯下位机地址的子地址:第4 位。当只有一个回路时为1;当有两个回路时通道一为1,
通道二为2。
d 通讯命令类型:第5 位。“R”(52H),表明在上位机发送或仪表应答中的读命令。“W”
(57H),表明在上位机发送或仪表应答的写命令。“B”表明在上位机以广播方式发送命令。
e 通讯命令代码:第6、7、8、9 位。是16 位二进制代码(0~65535),这16 位被分成四
组,并转换成相应的ASCII 码。命令代码祥见命令代码表。
f 通讯命令连续读代码:第10 位。表明上位机要连续读取多少个参数。这位取值范围(0~9)
(30H~39H),十个数。实际的连续读参数的个数=表明的数值+1。
g 通讯数据:第11 位。这位的数据量决定于这位的数据,既这位的数据长度不定。数据总
是以“,”(2CH),数据项与数据项之间不需要任何分割符。数据的长度主要取决于第10 位
的方式。每一个数据项由16 位二进制代码组成(1 个字),每4 位被分成一个数据单元,同
时每个数据单元又被转换成ASCII 数据,当第5 位为“R”读命令时,此位不写。
第一数据项 第二数据项 第 N 数据项
高位低位高位低位高位低位,” 第一单元第二单元第三单元第四单元第一单元第二单元
第三 单元第四单元第一单元第二单元第三单元第四单元2CH
h 数据发送结束符:第12 位。ETX(03H)或“:”(3AH)。所有的数据和命令在此位之
前都以发送完成,遇到此字符表名结束。
i BCC 块校验:第13、14 位。三种BCC 块校验和无校验。上位机的BCC 校验应通过软件
处理。仪表的BCC 校验可在仪表1-34 窗口设置。当BCC 校验结果有错误时,将没有应答。
BCC 校验数据被分成高4 位和低4 位,并被转换成ASCII 码。
13 位为高4 位的ASCII 码。14 位为低4 位的ASCII 码。

最新回复

O(∩_∩)O谢谢  详情 回复 发表于 2010-7-1 14:19
点赞 关注

回复
举报

75

帖子

0

TA的资源

一粒金砂(初级)

沙发
 
帮顶下。

MARK.
 
 

回复

76

帖子

0

TA的资源

一粒金砂(初级)

板凳
 
modbus ASC模式是固定以冒号为帧起始,回车换行为帧结尾的,便于在终端打印出数据。
至于中间的用户协议是由你们自己定义。

还有一点,ASC模式一字节数据只用7位的,所以对于通信来说,字节最高位无意义。

PC端只要把所有要发送的数据与0x80按位或。

下位机串口通信模式设为7个数据位的模式。

你上面提的要求还没时间仔细看,回去再看看。
不知道我说的能不能帮到你,很久之前做过modbus的程序,差不多全还给老师了。
 
 
 

回复

73

帖子

0

TA的资源

一粒金砂(初级)

4
 
讲错了,PC端数据应该是与0x7F按位与。
呵呵,记错了。
下位机还是上面说的那样,7个数据位,2个起始位。
 
 
 

回复

62

帖子

0

TA的资源

一粒金砂(初级)

5
 
谢谢,比如我想打开下位机的COM端口,首先我应该写@011W018C1:00结束时以CR结束。用ASCII发送的 时候,怎么发送呢?
 
 
 

回复

81

帖子

0

TA的资源

一粒金砂(初级)

6
 
打开下位机的COM端口是什么意思?
没有打开就无通信了啊,你的命令就没有用了。
 
 
 

回复

76

帖子

0

TA的资源

一粒金砂(初级)

7
 
下位机是一只处于通信状态的,读里面的信息,但是如果要想往下位机写东西,首先要发送一串指令,让其打开COM端口
 
 
 

回复

84

帖子

0

TA的资源

一粒金砂(初级)

8
 
你用个正常的应用程序和PLC通信,拦截下数据流,自己照着写不就成了,它发什么你就发什么呗。
你可以用这个工具调试你的串口程序。

下载地址:
http://download.cnet.com/ComTrace/3000-2218_4-75156892.html?tag=mncol

感觉好别忘了给个review(评论),谢谢!
 
 
 

回复

65

帖子

0

TA的资源

一粒金砂(初级)

9
 
你上面用什么写串口?
我觉得直接用WriteFile写字符串下去就可以了。
我以前是用CSerialPort这个类,不过其实这个类里面也是用的WriteFile。
不用想的太复杂的。
 
 
 

回复

59

帖子

0

TA的资源

一粒金砂(初级)

10
 
下载“ModBusPcMaster.rar”看看
 
 
 

回复

82

帖子

0

TA的资源

一粒金砂(初级)

11
 
O(∩_∩)O谢谢
 
 
 

回复
您需要登录后才可以回帖 登录 | 注册

随便看看
查找数据手册?

EEWorld Datasheet 技术支持

相关文章 更多>>
关闭
站长推荐上一条 1/10 下一条

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

About Us 关于我们 客户服务 联系方式 器件索引 网站地图 最新更新 手机版

站点相关: 国产芯 安防电子 汽车电子 手机便携 工业控制 家用电子 医疗电子 测试测量 网络通信 物联网

北京市海淀区中关村大街18号B座15层1530室 电话:(010)82350740 邮编:100190

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved
快速回复 返回顶部 返回列表