/************************************************************************************************** NAME : checkPACK_MODBUS INPUT : NO OUTPUT : unsigned char 返回校验结果,正确返回非零值,错误返回零。 FUNCTION : 校验接收数据包的正确性 **************************************************************************************************/ unsigned char checkPACK_MODBUS(unsigned char *rec_buff , int rec_num) { unsigned int rec_CRC; rec_CRC = (rec_buff[rec_num-2] << 8) | rec_buff[rec_num-1]; if( rec_CRC == comp_crc16(rec_buff, rec_num-2) ) { return 1; } else return 0; }
//用于功能码 06 void modbusRTU::ForceReg(unsigned char type,Int16 address,Int16 count,Int16 *value) { send_count = 8; modbus_send_buf[0] = 0x01;//站点 modbus_send_buf[1] = type;//功能码 modbus_send_buf[2] = address>>8; modbus_send_buf[3] = (unsigned char)address;//地址 modbus_send_buf[4] = *value>>8; modbus_send_buf[5] = (unsigned char)(*value); Int16 send_CRC = comp_crc16(modbus_send_buf, send_count-2);//CRC校验 modbus_send_buf[6] = send_CRC>>8; modbus_send_buf[7] = (unsigned char)send_CRC; }
//用于功能码03,04 void modbusRTU::ReadReg(unsigned char type,Int16 address,Int16 count) { send_count = 8; modbus_send_buf[0] = 0x01;//站点 modbus_send_buf[1] = type;//功能码 modbus_send_buf[2] = address>>8; modbus_send_buf[3] = (unsigned char)address; modbus_send_buf[4] = count>>8; modbus_send_buf[5] = (unsigned char)count; Int16 send_CRC = comp_crc16(modbus_send_buf, send_count-2);//CRC校验 modbus_send_buf[6] = send_CRC>>8; modbus_send_buf[7] = (unsigned char)send_CRC; }
/* function:对应modbus功能号06和16,单个和批量写寄存器 input:rec_buf接收到的指令 send_data需要发送的指令 */ void force_reg(unsigned char * rec_buf) { unsigned char fun_code,begin_add,data_num;//功能码,开始地址,数据长度 unsigned int send_num;//发送数据长度 unsigned char *piont; unsigned int send_CRC; int i; // send_data[0] = rec_buf[0]; //获取站号 fun_code = rec_buf[1]; //获取功能码 // send_data[1] = fun_code; // send_data[2] = rec_buf[2];//获取起始地址 // send_data[3] = rec_buf[3]; begin_add = rec_buf[3]*2; piont = (unsigned char *)modbusAdd; //将结构体转换为字符数组,便于后面的循环读取或写入 if(fun_code == 6)//写单个寄存器,返回指令与接收的指令完全一样 { piont[begin_add] = rec_buf[4];//寄存器高位写入 piont[begin_add+1] = rec_buf[5];//寄存器低位写入 send_num = 8;// } else if(fun_code == 16)//写多个寄存器 { data_num = rec_buf[5]*2; send_num = 8; for(i=0; i<data_num; i++) { piont[begin_add+i] = rec_buf[7+i]; } } send_CRC = comp_crc16(rec_buf, send_num-2);//CRC校验 rec_buf[send_num-2] = send_CRC >> 8; rec_buf[send_num -1] = send_CRC; send_count = send_num; PutNChar(rec_buf , send_count); }
//用于功能码 16 void modbusRTU::ForceNReg(unsigned char type,Int16 address,Int16 count,Int16 *value) { send_count = 9+count*2; modbus_send_buf[0] = 0x01;//站点 modbus_send_buf[1] = type;//功能码 modbus_send_buf[2] = address>>8; modbus_send_buf[3] = (unsigned char)address;//地址 modbus_send_buf[4] = count>>8;//寄存器总数 modbus_send_buf[5] = (unsigned char)count; modbus_send_buf[6] = count*2;//寄存器总字节数 for(int i=0;i<count;i++)//写入需要的值 { modbus_send_buf[7+i*2] = value[i]>>8; modbus_send_buf[7+i*2+1] = (unsigned char)value[i]; } Int16 send_CRC = comp_crc16(modbus_send_buf, send_count-2);//CRC校验 modbus_send_buf[send_count-2] = send_CRC>>8; modbus_send_buf[send_count-1] = (unsigned char)send_CRC; }
/* function:对应modbus功能号03,04 批量读寄存器 input:rec_buf接收到的指令 send_data需要发送的指令 */ void read_reg(unsigned char * rec_buff) { unsigned char begin_add = 0; unsigned char data_num = 0; unsigned char *piont; unsigned int send_CRC; unsigned int send_num; int i; begin_add = rec_buff[3]*2;//地址1字节 data_num = rec_buff[5]*2;//需要读取的字节数 send_num = 5 + data_num; // 5个固定字节+数据个数 addr1 + fun1 + num1 +【data】+ crc2 rec_buff[2] = data_num;//字节数 piont = (unsigned char *)modbusAdd; //将结构体转换为字符数组,便于后面的循环读取或写入 for(i=0; i<data_num; i++) { rec_buff[3+i] = piont[begin_add +i]; } send_CRC = comp_crc16(rec_buff, send_num-2); rec_buff[send_num-2] = send_CRC >> 8; rec_buff[send_num -1] = send_CRC; send_count = send_num; PutNChar(rec_buff , send_count); }