📄 modbus.c
字号:
}
}
return(1);
}
else //CRC校验不一致;可重新发送请求或作其他处理
{
Rx_Buffer[2] = 0x09;
FaultProcess();
return(0);
}
}
else //通信异常0x83,查询异常码,可重新发送请求或作其他处理
{
FaultProcess();
return(0);
}
*/
}
else //通信异常
{
Rx_Buffer[2] = 255;//异常码填充(测试用)
FaultProcess();
return(0);
}
}
/********************************************************************************************************
* 作者 :冯子龙
* 日期 :200709
* 名称 :cmd04_ReadAnlogIn()
* 功能 :读取模拟量输入(ASCII模式):CMD == 4
* 返回 :成功返回1,否则返回0
* 备注 :Tested
请求命令:[设备地址] [命令号04] [起始寄存器地址高8位] [低8位] [读取的寄存器数高8位] [低8位] [CRC校验的低8位] [CRC校验的高8位]
设备响应:[设备地址] [命令号04] [返回的字节个数][数据1][数据2]...[数据n][CRC校验的低8位] [CRC校验的高8位]
*********************************************************************************************************/
uchar cmd04_ReadAnlogIn(uchar DeviceID, uint start_address, uint lenth)
{
uchar tmp[256], tmp_lenth;
tmp[0] = DeviceID;//从设备地址
tmp[1] = 0x04; //命令
tmp[2] = wordHByte(start_address);//起始地址 高字节
tmp[3] = wordLByte(start_address);//起始地址 低字节
tmp[4] = wordHByte(lenth);//读取数据量 高字节
tmp[5] = wordLByte(lenth);//读取数据量 低字节
tmp_lenth = 6;
if(Modbus_mode)
{
construct_ascii_frm (Tx_Buffer, tmp, tmp_lenth);//对以上数据构成ASCII码串
TxBytes = 2*tmp_lenth+2; //有效Modbus数据长度,用于中断发送完成判断
}
else
{
construct_rtu_frm(Tx_Buffer, tmp, tmp_lenth);
TxBytes = tmp_lenth+2;
}
comSend();//发送请求
if(comReceive())//获取应答;对应答数据分析;对接收到的应答数据分析
{
if(Rx_Buffer[1] == 0x04) //通信正常,数据处理
{
if(CheckCRC(Rx_Buffer,RxBytes))
{
switch(Rx_Buffer[2])//返回字节数
{
case 0x02:
{
break;
}
case 0x04:
{
break;
}
case 0x06:
{
break;
}
case 0x08:
{
para_val = Rx_Buffer[3]*256 + Rx_Buffer[4];
break;
}
default:
{
break;
}
}
return(1);
}
else //CRC校验不一致;可重新发送请求或作其他处理
{
Rx_Buffer[2] = 0x09;
FaultProcess();
return(0);
}
}
else //通信异常0x83,查询异常码,可重新发送请求或作其他处理
{
FaultProcess();
return(0);
}
}
else //通信异常
{
Rx_Buffer[2] = 255;//异常码填充
FaultProcess();
return(0);
}
}
/********************************************************************************************************
* 作者 :冯子龙
* 日期 :200709
* 名称 :cmd05_SetCoil()
* 功能 :设置继电器(ASCII模式):CMD == 5
* 返回 :成功返回1,否则返回0
* 备注 :Tested
* 请求命令:[设备地址] [命令号05] [需下置的寄存器地址高8位] [低8位] [下置的数据高8位] [低8位] [CRC校验的低8位] [CRC校验的高8位]
* 设备响应:如果成功把计算机发送的命令原样返回,否则不响应
*********************************************************************************************************/
uchar cmd05_SetCoil(uchar DeviceID, uint start_address, uint value)
{
uchar tmp[256], tmp_lenth;
tmp[0] = DeviceID;//从设备地址
tmp[1] = 0x05 ;//命令
tmp[2] = wordHByte(start_address);//起始地址 高字节
tmp[3] = wordLByte(start_address);//起始地址 低字节
tmp[4] = wordHByte(value);//待写数据 高字节
tmp[5] = wordLByte(value);//待写数据 低字节
tmp_lenth = 6;
if(Modbus_mode)
{
construct_ascii_frm (Tx_Buffer, tmp, tmp_lenth);//对以上数据构成ASCII码串
TxBytes = 2*tmp_lenth+2; //有效Modbus数据长度,用于中断发送完成判断
}
else
{
construct_rtu_frm(Tx_Buffer, tmp, tmp_lenth);
TxBytes = tmp_lenth+2;
}
comSend();//发送请求
if(comReceive())//获取应答;对应答数据分析;对接收到的应答数据分析
{
if(Rx_Buffer[1] == 0x05) //通信正常,数据处理
{
if(CheckCRC(Rx_Buffer,RxBytes))
{
if(Rx_Buffer[2]!=Tx_Buffer[2]) return(0);
if(Rx_Buffer[3]!=Tx_Buffer[3]) return(0);
if(Rx_Buffer[4]!=Tx_Buffer[4]) return(0);
if(Rx_Buffer[5]!=Tx_Buffer[5]) return(0);
return(1);
}
else //CRC校验不一致;可重新发送请求或作其他处理
{
Rx_Buffer[2] = 0x09;
FaultProcess();
return(0);
}
}
else //通信异常0x83,查询异常码,可重新发送请求或作其他处理
{
FaultProcess();
return(0);
}
}
else //通信异常
{
Rx_Buffer[2] = 255;//异常码填充
FaultProcess();
return(0);
}
}
/********************************************************************************************************
* 作者 :冯子龙
* 日期 :200709
* 名称 :cmd06_SetHldreg()
* 功能 :设置单保持寄存器(ASCII模式):CMD == 6
* 返回 :成功返回1,否则返回0
* 备注 :Tested
* 请求命令:[设备地址] [命令号06] [需下置的寄存器地址高8位] [低8位] [下置的数据高8位] [低8位] [CRC校验的低8位] [CRC校验的高8位]
* 设备响应:如果成功把计算机发送的命令原样返回,否则不响应
*********************************************************************************************************/
uchar cmd06_SetHldreg(uchar DeviceID, uint start_address, uint value)
{
uchar tmp[256], tmp_lenth;
tmp[0] = DeviceID; //地址
tmp[1] = 0x06;//命令
tmp[2] = wordHByte(start_address);//写数据的起始地址 高字节
tmp[3] = wordLByte(start_address);//写数据的起始地址 低字节
tmp[4] = wordHByte(value);//待写数据 高字节
tmp[5] = wordLByte(value);//待写数据 低字节
tmp_lenth = 6;//有效数据长度
if(Modbus_mode)
{
construct_ascii_frm (Tx_Buffer, tmp, tmp_lenth);//对以上数据构成ASCII码串(添加数据校验和以及结束标志)
TxBytes = 2*tmp_lenth+2; //有效Modbus数据长度,用于中断发送完成判断
}
else
{
construct_rtu_frm(Tx_Buffer, tmp, tmp_lenth);
TxBytes = tmp_lenth+2;
}
comSend();//发送请求
if(comReceive())//获取应答;对应答数据分析;对接收到的应答数据分析
{
if(Rx_Buffer[1] == 0x06) //通信正常,数据处理
{
if(CheckCRC(Rx_Buffer,RxBytes))
{
if(Rx_Buffer[2]!=Tx_Buffer[2]) return(0);
if(Rx_Buffer[3]!=Tx_Buffer[3]) return(0);
if(Rx_Buffer[4]!=Tx_Buffer[4]) return(0);
if(Rx_Buffer[5]!=Tx_Buffer[5]) return(0);
return(1);
}
else //CRC校验不一致;可重新发送请求或作其他处理
{
Rx_Buffer[2] = 0x09;
FaultProcess();
return(0);
}
}
else //通信异常0x83,查询异常码,可重新发送请求或作其他处理
{
FaultProcess();
return(0);
}
}
else //通信异常
{
Rx_Buffer[2] = 255;//异常码填充
FaultProcess();
return(0);
}
}
/********************************************************************************************************
* 作者 :冯子龙
* 日期 :200709
* 名称 :cmd15_setcoils()
* 功能 :对多个线圈进行强制(ASCII模式):CMD == 15
* 返回 :成功返回1,否则返回0
* 备注 :Tested
* 请求格式:从站地址 0x0F 第一个位首地址 所写位数 值占用的字节数 值
(例如,置从站5的位12至17为1,则:05 0F 000C 0006 01 3F CRC)
*********************************************************************************************************/
uchar cmd15_setcoils(uchar DeviceID, uint Startbit_Add, uint Bit2Write, uchar ByteValue, uchar *Values)
{
uchar tmp[256], tmp_lenth,i;
tmp[0] = DeviceID;
tmp[1] = 0x0f ;
tmp[2] = wordHByte(Startbit_Add);
tmp[3] = wordLByte(Startbit_Add);
tmp[4] = wordHByte(Bit2Write);
tmp[5] = wordLByte(Bit2Write);
tmp[6] = ByteValue;
for(i=0;i<ByteValue;i++)
tmp[7+i] = Values[i];
tmp_lenth = 7+ByteValue;
if(Modbus_mode)
{
construct_ascii_frm (Tx_Buffer, tmp, tmp_lenth);//对以上数据构成ASCII码串(添加数据校验和以及结束标志)
TxBytes = 2*tmp_lenth+2; //有效Modbus数据长度,用于中断发送完成判断
}
else
{
construct_rtu_frm(Tx_Buffer, tmp, tmp_lenth);
TxBytes = tmp_lenth+2;
}
comSend();//发送CMD请求
if(comReceive())//获取应答;对应答数据分析
{
//rtu_data_anlys();
}
return 18;
}
/********************************************************************************************************
* 作者 :冯子龙
* 日期 :200709
* 名称 :cmd16_SetMultiHldreg()
* 功能 :设置多个保持寄存器(ASCII模式):CMD == 16
* 返回 :成功返回1,否则返回0
* 备注 :Tested
*********************************************************************************************************/
uchar cmd16_SetMultiHldreg(uchar DeviceID, uint start_address, uint WNum, uchar BNum, uint *values)
{
uchar tmp[256], tmp_lenth;
uchar i=0;
uint j;
tmp[0] = DeviceID; //地址
tmp[1] = 0x10; //命令
tmp[2] = wordHByte(start_address);//写数据的起始地址 高字节
tmp[3] = wordLByte(start_address);//写数据的起始地址 低字节
tmp[4] = wordHByte(WNum); //待写寄存器数量
tmp[5] = wordLByte(WNum); //待写寄存器数量
tmp[6] = BNum; //待写数据的字节数
for(j=0;j<WNum;j++) //填充数据
{
tmp[i+7] = wordHByte(values[j]);//待写数据 高字节
tmp[i+8] = wordLByte(values[j]);//待写数据 低字节
i=i+2;
}
tmp_lenth = 7+i;//有效数据长度
if(Modbus_mode)
{
construct_ascii_frm (Tx_Buffer, tmp, tmp_lenth);//对以上数据构成ASCII码串(添加数据校验和以及结束标志)
TxBytes = 2*tmp_lenth+2; //有效Modbus数据长度,用于中断发送完成判断
}
else
{
construct_rtu_frm(Tx_Buffer, tmp, tmp_lenth);
TxBytes = tmp_lenth+2;
}
comSend();//发送CMD请求
if(comReceive())//获取应答;对应答数据分析
{
//rtu_data_anlys();
}
return 18;
}
/********************************************************************************************************
* 作者 :冯子龙
* 日期 :200709
* 名称 :Master_process_rtu()
* 功能 :RTU模式 接收分析
* 返回 :1,CMD_ERR
* 备注 :
*********************************************************************************************************/
char process_Master_RTU( int *dest, uchar *src,uint start_address, uint fr_lenth)
{
uint crc_result, crc_tmp;
uchar i, j, shift;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -