통신 프로토콜(modbus--RTU) 仪表设置:pst 01------中TF = 1,D39시리즈要选命令방식2
一、老프로토콜 兼容老프로토콜
1.主机读仪表데이터
| 대기 | 바이트0 | 1 | 2 | 3 |
| 四个바이트的时间 | 1~247 | x03 | 启始주소高8 | 低8 |
| 仪表주소 | 功能代码 | 所要读的레지스터开始주소 | ||
| 4 | 5 | 6 | 7 | 대기 |
| N/2个바이트高8 | 低8 | CRC16低8 | CRC16高8 | 三个바이트的时间 |
| 보내기数量 | CRC16체크섬 | |||
데이터以ASII传送
2.仪表返馈
正常回应
| 바이트0 | 1 |
| 1~247 | 0x03 |
| 仪表주소 | 功能代码 |
| 2 | 3 | 3+n | 3+n | ||
| N | 데이터0 | …… | 데이터N(偶数) | CRC16L | CRC16h |
| 데이터길이 | 데이터 | ||||
1)称重데이터읽기指令
| 功能 | 所要读的레지스터开始주소(주소高8位) | 所要读的레지스터开始주소(주소低8位) | |
| 1 | 读毛重 | 0x00 | 0x01 |
| 2 | 读皮重 | 0x00 | 0x02 |
| 3 | 读净重 | 0x00 | 0x03 |
| 4 | 读总内码 | 0x00 | 0x07 |
| 5 | 读第i号센서内码异常时得到-999999 | 0x00 | 0x0A+i(i=1~16) |
보내기
| 0 | 1 | 2 | 3 | 4 |
| 仪表주소 | 0x03 | 주소高8位 | 주소低8位 | 0x00 |
| 5 | 6 | 7 |
| 0x04 | CRC16L | CRC16H |
返回
| 0 | 1 | 2 | 3 | 5 | 6 |
| 仪表주소 | 0x03 | 0x08 | 符号-或데이터6 | 데이터5 | 데이터4 |
| 7 | 8 | 9 | 10 | 11 |
| 데이터3 | 데이터2 | 데이터1 | 데이터0 | 小数点(右至左) |
| 12 | 13 |
| CRC16L | CRC16H |
例子:
1、읽기当前毛重
보내기:01 03 00 01 00 04 15 C9
수신:若当前毛重为0
01 03 08 30 30 30 30 30 30 30 30 F8 2F (最后两个바이트为CRC16체크섬)
若当前毛重为1240
01 03 08 30 30 30 31 32 34 30 30 85 96
2、远程置零
보내기: 01 06 00 01 00 17 98 04
수신: 01 06 00 01 00 17 98 04
常见문제:
1、仪表连续보내기(如TF=0)时,电脑시리얼 포트能收到데이터,但用指令방식仍无响应
原因: 1)仪表매개변수错误,D2008、D12시리즈仪表TF = 1;D39시리즈仪表为命令방식2
2)仪表시리얼 포트故障,可通过test 08 进行自检。
3)电脑시리얼 포트故障,将接시리얼 포트2和3短路,然后通过시리얼 포트도구보내기데이터,看其能否收到自己보내기的相同的데이터。
4)배선문제,仪表9芯的3号脚(RXD)为수신脚,需要与电脑的2号脚(TXD)연결
5)仪表虽支持modbus RTU 프로토콜,但modbus 发指令时有要求,如读毛重,其레지스터주소为40001.此时必须一次性读4个字(40001~40004),否则无应答。
2、데이터如何解释
以下为读毛重
| 주소 | 콘텐츠 | 举例(重量1234567) | 举例(重量-23456.7) |
| 40001 | 符号-或데이터6,데이터5 | 0x31,0x32 | 0x2d,0x32 |
| 40002 | 데이터4,데이터3 | 0x33,0x34 | 0x33,0x34 |
| 40003 | 데이터2,데이터1 | 0x35,0x36 | 0x35,0x36 |
| 40004 | 데이터0,小数点+0x30 | 0x37,0x30 | 0x37,0x31 |
以下为读净重
| 주소 | 콘텐츠 | 举例(重量1234567) | 举例(重量-23456.7) |
| 40003 | 符号-或데이터6,데이터5 | 0x31,0x32 | 0x2d,0x32 |
| 40004 | 데이터4,데이터3 | 0x33,0x34 | 0x33,0x34 |
| 40005 | 데이터2,데이터1 | 0x35,0x36 | 0x35,0x36 |
| 40006 | 데이터0,小数点+0x30 | 0x37,0x30 | 0x37,0x31 |
以下是西门子 200 smart 的예제:
读毛重:

特别要注意:以上40002对应仪表的40001.
接下来再写个子程序:

子程序인터페이스:

代码:(部分)

二、新프로토콜
只有以下버전支持:
仪表:D2008型(DF)、D12-YF--V09버전 D2008-W ---V13버전,KL-MPLC的com2프로토콜1
| 레지스터주소 | |
| 40060 | 状态Bit0:开机零点确认中 0:已确认 1:正在确认中Bit1:超载 0:正常 1:超载Bit2:稳定 0:不稳定 2:稳定 Bit3:去皮 0:没有去皮 1:去皮状态Bit4:零点 0:没在零点 1:零位区Bit5:计量데이터有效 0:无效 1:有效 Bit6: 센서出错 0:通讯正常 1: 异常Bit7: 备用Bit8~15: 센서个数 |
| 40061 | 센서状态 0:正常 1:异常 Bit16:1号 Bit17:2号...Bit31:16号 |
| 40062-40063 | 毛重:float |
| 40064-40065 | 皮重:float |
| 40066-40067 | 净重:float |
| 40068-40069 | 第1个센서内码:float |
| 40070-40071 | 第2个센서内码:float |
| ... | ... |
| 40098-40099 | 第16个센서内码:float |
| 40100 | 센서状态 0:正常 1:异常 Bit16:17号 Bit17:18号...Bit31:32号 |
| 40101-40102 | 第17号센서内码:float |
| 40103-40104 | 第18号센서内码:float |
| ... | ... |
| 40131-40132 | 第32号센서内码:float |
约定:
当秤台计量데이터无效:仪表的净重为-999999,如果小数点为3位,则为-999.999
置零:向주소40001写0x0017;
2、Modbus主机설정:
第一项:选择为RTU
第二项:

如:

第三项:float표시 형식设置:

第三项:전체显예제子:

3、相关解码代码:수신바이트转化为浮点型
定义데이터结构:
typedef union noneTYPE32데이터BYTE
{
struct{
INT32U onebyte0:8;
INT32U onebyte1:8;
INT32U onebyte2:8;
INT32U onebyte3:8;
}onebyte;
INT32U One32데이터;
FP32 FP32데이터;
}TYPE32데이터BYTE;
代码:
原如수신4个바이트 (按수신顺序)--R데이터[0],R데이터[1],R데이터[2]和R데이터[3]
float FP32데이터;
TYPE32데이터BYTE P_temp;
P_temp.onebyte.onebyte1 = R데이터[0];
P_temp.onebyte.onebyte0 = R데이터[1];
P_temp.onebyte.onebyte3 = R데이터[2];
P_temp.onebyte.onebyte2 = R데이터[3];
F_temp = P_temp.FP32데이터;//F_temp就是结果在西门子 200smart中바이트转浮点型操作如下:
例:浮点数 123.456 对应[0]=0x79 0xe9,0xf6,[3]=0x42
PLC梯形图转化:

效果:

常用例子1:读毛重
仪表显示毛重68,皮重为0
发:01 03 00 42 00 02 64 1F
收: 01 03 04 00 00 42 88 CA F5
常用例子2:远程置零
보내기: 01 06 00 01 00 17 98 04
수신: 01 06 00 01 00 17 98 04
CRC16체크섬算法:
/* CRC 高位바이트值表 */
const unsigned char auchCRCHi[] = {
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,
0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,
0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1,
0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41,
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1,
0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,
0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40,
0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1,
0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,
0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40,
0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,
0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,
0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,
0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,
0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40,
0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1,
0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,
0x80, 0x41, 0x00, 0xC1, 0x81, 0x40
} ;
/* CRC低位바이트值表*/
const unsigned char auchCRCLo[] = {
0x00, 0xC0, 0xC1, 0x01, 0xC3, 0x03, 0x02, 0xC2, 0xC6, 0x06,
0x07, 0xC7, 0x05, 0xC5, 0xC4, 0x04, 0xCC, 0x0C, 0x0D, 0xCD,
0x0F, 0xCF, 0xCE, 0x0E, 0x0A, 0xCA, 0xCB, 0x0B, 0xC9, 0x09,
0x08, 0xC8, 0xD8, 0x18, 0x19, 0xD9, 0x1B, 0xDB, 0xDA, 0x1A,
0x1E, 0xDE, 0xDF, 0x1F, 0xDD, 0x1D, 0x1C, 0xDC, 0x14, 0xD4,
0xD5, 0x15, 0xD7, 0x17, 0x16, 0xD6, 0xD2, 0x12, 0x13, 0xD3,
0x11, 0xD1, 0xD0, 0x10, 0xF0, 0x30, 0x31, 0xF1, 0x33, 0xF3,
0xF2, 0x32, 0x36, 0xF6, 0xF7, 0x37, 0xF5, 0x35, 0x34, 0xF4,
0x3C, 0xFC, 0xFD, 0x3D, 0xFF, 0x3F, 0x3E, 0xFE, 0xFA, 0x3A,
0x3B, 0xFB, 0x39, 0xF9, 0xF8, 0x38, 0x28, 0xE8, 0xE9, 0x29,
0xEB, 0x2B, 0x2A, 0xEA, 0xEE, 0x2E, 0x2F, 0xEF, 0x2D, 0xED,
0xEC, 0x2C, 0xE4, 0x24, 0x25, 0xE5, 0x27, 0xE7, 0xE6, 0x26,
0x22, 0xE2, 0xE3, 0x23, 0xE1, 0x21, 0x20, 0xE0, 0xA0, 0x60,
0x61, 0xA1, 0x63, 0xA3, 0xA2, 0x62, 0x66, 0xA6, 0xA7, 0x67,
0xA5, 0x65, 0x64, 0xA4, 0x6C, 0xAC, 0xAD, 0x6D, 0xAF, 0x6F,
0x6E, 0xAE, 0xAA, 0x6A, 0x6B, 0xAB, 0x69, 0xA9, 0xA8, 0x68,
0x78, 0xB8, 0xB9, 0x79, 0xBB, 0x7B, 0x7A, 0xBA, 0xBE, 0x7E,
0x7F, 0xBF, 0x7D, 0xBD, 0xBC, 0x7C, 0xB4, 0x74, 0x75, 0xB5,
0x77, 0xB7, 0xB6, 0x76, 0x72, 0xB2, 0xB3, 0x73, 0xB1, 0x71,
0x70, 0xB0, 0x50, 0x90, 0x91, 0x51, 0x93, 0x53, 0x52, 0x92,
0x96, 0x56, 0x57, 0x97, 0x55, 0x95, 0x94, 0x54, 0x9C, 0x5C,
0x5D, 0x9D, 0x5F, 0x9F, 0x9E, 0x5E, 0x5A, 0x9A, 0x9B, 0x5B,
0x99, 0x59, 0x58, 0x98, 0x88, 0x48, 0x49, 0x89, 0x4B, 0x8B,
0x8A, 0x4A, 0x4E, 0x8E, 0x8F, 0x4F, 0x8D, 0x4D, 0x4C, 0x8C,
0x44, 0x84, 0x85, 0x45, 0x87, 0x47, 0x46, 0x86, 0x82, 0x42,
0x43, 0x83, 0x41, 0x81, 0x80, 0x40
} ;
/******************************************************
函数名: INT16U crc16(unsigned char *puchMsg, INT16U us데이터Len)
功能: 根据문자串puchMsg 及길이产生一个CRC16
입력:unsigned char *puchMsg 문자串 us데이터Len 길이
출력:INT16U CRC16
*******************************************************/
INT16U crc16(unsigned char *puchMsg, INT16U us데이터Len) //根据문자串puchMsg 及길이产生一个CRC16
{
unsigned char uchCRCHi = 0xFF ; /* 高CRC바이트初始化 */
unsigned char uchCRCLo = 0xFF ; /* 低CRC 바이트初始化 */
unsigned long uIndex ; /* CRC循环中的索引 */
while (us데이터Len--) /* 传输消息缓冲区 */
{
uIndex = uchCRCHi ^ *puchMsg++ ; /* 계산CRC */
uchCRCHi = uchCRCLo ^ auchCRCHi[uIndex] ;
uchCRCLo = auchCRCLo[uIndex] ;
}
return (uchCRCHi << 8 | uchCRCLo) ;
}
//=======================================================적용:假设要보내기读毛重指令(16진법)
01 03 00 01 00 04
产生체크섬的방식
//TXD_C_temps[]存了01 03 00 01 00 04 (6个바이트)
INT16U crc데이터 ;
ByteCount = 6;//데이터为6바이트
crc데이터 = crc16(TXD_C_temps,ByteCount );
TXD_C_temps[byteCount] = crc데이터 >> 8;
byteCount++;
TXD_C_temps[byteCount] = crc데이터 & 0xff;
//此时문자串
01 03 00 01 00 04 15 C9
putchars2_8th(TXD_C_temps,byteCount+1);//通过시리얼 포트보내기
답글 작성