📄 modbus_rtu.c
字号:
//输入参数: UCHAR *ucpRevcBuff 接收缓冲
// UCHAR *ucpSendBuff 发送缓冲
// UCHAR *ucpLen 发送缓冲长度
//输出参数: void
//返 回 值: UCHAR 异常码
//创建日期: 2008.01.02
//创 建 人: 罗德良
//参考文档:
//说 明: Modbus 2号功能码
//修改历史:
//****************************************************************************
UCHAR Read_MultDI(UCHAR *ucpRevcBuff, UCHAR *ucpSendBuff, UCHAR *ucpLen)
{
UINT16 ui16Temp, i, ui16Len;
UCHAR ucTemp, ucByteNo, ucBitNo;
tagMODREAD *tagpModRead;
tagMODREADRESP *tagpModReadResp;
if (ucpRevcBuff == NULL || ucpSendBuff == NULL || ucpLen == NULL)
{
return (CALL_ERR);
}
tagpModRead = (tagMODREAD *)ucpRevcBuff; //接收缓冲区
tagpModReadResp = (tagMODREADRESP *)ucpSendBuff; //应答缓冲区
tagpModReadResp -> ucSta = tagpModRead -> ucSta; //站号
tagpModReadResp -> ucFun = tagpModRead -> ucFun; //功能码
//寄存器起始地址
ui16Temp = tagpModRead -> ucStarAdrHi * 256ul + tagpModRead -> ucStarAdrLo;
if (ui16Temp >= DICOUNT) return (ADR_ERR); //寄存器超出范围
//寄存器数量
ui16Len = tagpModRead -> ucCntHi * 256ul + tagpModRead -> ucCntLo;
if ((ui16Len + ui16Temp) > DICOUNT) return(ADR_ERR); //寄存器超出范围
//返回数据字节数
tagpModReadResp -> ucByteCnt = ui16Len / 8;
if ((ui16Len % 8) != 0)
{
tagpModReadResp -> ucByteCnt += 1;
}
//内容处理
i = 0;
while (i < ui16Len)
{
//取寄存器位值
ucByteNo = ui16Temp / 8;
ucBitNo = ui16Temp % 8;
ucTemp = ((ucDiReg[ucByteNo] >> ucBitNo) & 0x01);
if ((i % 8) == 0)
{
tagpModReadResp -> ucMess[i / 8] = 0x00;
}
//填充到发送缓冲
tagpModReadResp -> ucMess[i / 8] |= (ucTemp << (i % 8));
i++;
ui16Temp++;
}
//计算CRC
ui16Temp = CRC16((UCHAR *)tagpModReadResp, 3 + tagpModReadResp -> ucByteCnt);
tagpModReadResp -> ucMess[tagpModReadResp -> ucByteCnt] = ui16Temp / 256;
tagpModReadResp -> ucMess[tagpModReadResp -> ucByteCnt + 1] = ui16Temp;
//发送缓冲长度
*ucpLen = 3 + tagpModReadResp -> ucByteCnt + 2;
return (NO_ERR);
}
//****************************************************************************
//函数名称: Write_SingleCoil
//函数功能: 写单个线圈
//输入参数: UCHAR *ucpRevcBuff 接收缓冲
// UCHAR *ucpSendBuff 发送缓冲
// UCHAR *ucpLen 发送缓冲长度
//输出参数: void
//返 回 值: UCHAR 异常码
//创建日期: 2008.01.02
//创 建 人: 罗德良
//参考文档:
//说 明: Modbus 5号功能码
//修改历史:
//****************************************************************************
UCHAR Write_SingleCoil(UCHAR *ucpRevcBuff, UCHAR *ucpSendBuff, UCHAR *ucpLen)
{
UINT16 ui16Temp, ui16Val;
UCHAR ucByteNo, ucBitNo;
tagWRSINGAL *tagpWrSingal;
if (ucpRevcBuff == NULL || ucpSendBuff == NULL || ucpLen == NULL)
{
return (CALL_ERR);
}
tagpWrSingal = (tagWRSINGAL *)ucpRevcBuff; //接收缓冲区
//寄存器地址
ui16Temp = tagpWrSingal -> ucAdrHi * 256ul + tagpWrSingal -> ucAdrLo;
if (ui16Temp >= DOCOUNT) return (ADR_ERR); //地址超出范围
//寄存器值
ui16Val = tagpWrSingal -> ucDatHi * 256ul + tagpWrSingal -> ucDatLo;
if (ui16Val != 0x0000 && ui16Val != 0xff00) return (VAL_ERR); //非法值
//置线圈
ucByteNo = ui16Temp / 8;
ucBitNo = ui16Temp % 8;
if (ui16Val == 0x00)
{//OFF
ucDoReg[ucByteNo] &= ~(0x01 << ucBitNo);
}
else
{//ON
ucDoReg[ucByteNo] |= (0x01 << ucBitNo);
}
memcpy((char *)ucpSendBuff, (char *)ucpRevcBuff, 8);
//发送缓冲长度
*ucpLen = 8;
return (NO_ERR);
}
//****************************************************************************
//函数名称: Write_MultCoil
//函数功能: 写多个线圈
//输入参数: UCHAR *ucpRevcBuff 接收缓冲
// UCHAR *ucpSendBuff 发送缓冲
// UCHAR *ucpLen 发送缓冲长度
//输出参数: void
//返 回 值: UCHAR 异常码
//创建日期: 2008.01.02
//创 建 人: 罗德良
//参考文档:
//说 明: Modbus 15号功能码
//修改历史:
//****************************************************************************
UCHAR Write_MultCoil(UCHAR *ucpRevcBuff, UCHAR *ucpSendBuff, UCHAR *ucpLen)
{
UINT16 ui16Temp, ui16Len, i;
UCHAR ucTemp, ucByteNo, ucBitNo;
tagWRMULTE *tagpWrMulte;
tagMODREAD *tagpModRead;
if (ucpRevcBuff == NULL || ucpSendBuff == NULL || ucpLen == NULL)
{
return (CALL_ERR);
}
tagpWrMulte = (tagWRMULTE *)ucpRevcBuff; //接收缓冲区
tagpModRead = (tagMODREAD *)ucpSendBuff; //应答缓冲区
tagpModRead -> ucSta = tagpWrMulte -> ucSta; //站号
tagpModRead -> ucFun = tagpWrMulte -> ucFun; //功能码
tagpModRead -> ucStarAdrHi = tagpWrMulte -> ucStarAdrHi; //起始寄存器
tagpModRead -> ucStarAdrLo = tagpWrMulte -> ucStarAdrLo;
tagpModRead -> ucCntHi = tagpWrMulte -> ucCntHi; //寄存器数量
tagpModRead -> ucCntLo = tagpWrMulte -> ucCntLo;
//起始寄存器
ui16Temp = tagpWrMulte -> ucStarAdrHi * 256ul + tagpWrMulte -> ucStarAdrLo;
if (ui16Temp >= DOCOUNT) return (ADR_ERR); //寄存器超出范围
//寄存器数量
ui16Len = tagpWrMulte -> ucCntHi * 256ul + tagpWrMulte -> ucCntLo;
if ((ui16Temp + ui16Len) > DOCOUNT) return (ADR_ERR); //寄存器超出范围
//置DO
i = 0;
while (i < ui16Len)
{
//取寄存器位值
ucTemp = ((tagpWrMulte -> ucMess[i / 8]) >> (i % 8)) & 0x01;
ucByteNo = ui16Temp / 8;
ucBitNo = ui16Temp % 8;
//置DO
if (ucTemp == 0x00)
{//OFF
ucDoReg[ucByteNo] &= ~(0x01 << ucBitNo);
}
else
{//ON
ucDoReg[ucByteNo] |= (0x01 << ucBitNo);
}
i++;
ui16Temp++;
}
//计算CRC
ui16Temp = CRC16((UCHAR *)tagpModRead, 6);
tagpModRead -> ucCrcHi = ui16Temp / 256;
tagpModRead -> ucCrcLo = ui16Temp;
//发送缓冲长度
*ucpLen = 8;
return (NO_ERR);
}
//****************************************************************************
//函数名称: Write_SingleAO
//函数功能: 写单个保寄存器
//输入参数: UCHAR *ucpRevcBuff 接收缓冲
// UCHAR *ucpSendBuff 发送缓冲
// UCHAR *ucpLen 发送缓冲长度
//输出参数: void
//返 回 值: UCHAR 异常码
//创建日期: 2008.01.02
//创 建 人: 罗德良
//参考文档:
//说 明: Modbus 6号功能码
//修改历史:
//****************************************************************************
UCHAR Write_SingleAO(UCHAR *ucpRevcBuff, UCHAR *ucpSendBuff, UCHAR *ucpLen)
{
UINT16 ui16Temp, ui16Val;
tagWRSINGAL *tagpWrSingal;
if (ucpRevcBuff == NULL || ucpSendBuff == NULL || ucpLen == NULL)
{
return (CALL_ERR);
}
tagpWrSingal = (tagWRSINGAL *)ucpRevcBuff; //接收缓冲区
//寄存器地址
ui16Temp = tagpWrSingal -> ucAdrHi * 256ul + tagpWrSingal -> ucAdrLo;
if (ui16Temp >= AOCOUNT) return (ADR_ERR); //地址超出范围
//寄存器值
ui16Val = tagpWrSingal -> ucDatHi * 256ul + tagpWrSingal -> ucDatLo;
//if (ui16Val > 4095) return (VAL_ERR); //非法值
//写寄存器
ui16AoReg[ui16Temp] = ui16Val;
memcpy((char *)ucpSendBuff, (char *)ucpRevcBuff, 8);
//发送缓冲长度
*ucpLen = 8;
return (NO_ERR);
}
//****************************************************************************
//函数名称: Write_MultAO
//函数功能: 写多保持寄存器
//输入参数: UCHAR *ucpRevcBuff 接收缓冲
// UCHAR *ucpSendBuff 发送缓冲
// UCHAR *ucpLen 发送缓冲长度
//输出参数: void
//返 回 值: UCHAR 异常码
//创建日期: 2007.05.13
//创 建 人: 罗德良
//参考文档:
//说 明: Modbus 16号功能码
//修改历史:
//****************************************************************************
UCHAR Write_MultAO(UCHAR *ucpRevcBuff, UCHAR *ucpSendBuff, UCHAR *ucpLen)
{
UINT16 ui16Temp, ui16Len, i, ui16Val;
tagWRMULTE *tagpWrMulte;
tagMODREAD *tagpModRead;
if (ucpRevcBuff == NULL || ucpSendBuff == NULL || ucpLen == NULL)
{
return (CALL_ERR);
}
tagpWrMulte = (tagWRMULTE *)ucpRevcBuff; //接收缓冲区
tagpModRead = (tagMODREAD *)ucpSendBuff; //应答缓冲区
tagpModRead -> ucSta = tagpWrMulte -> ucSta; //站号
tagpModRead -> ucFun = tagpWrMulte -> ucFun; //功能码
tagpModRead -> ucStarAdrHi = tagpWrMulte -> ucStarAdrHi; //起始寄存器
tagpModRead -> ucStarAdrLo = tagpWrMulte -> ucStarAdrLo;
tagpModRead -> ucCntHi = tagpWrMulte -> ucCntHi; //寄存器数量
tagpModRead -> ucCntLo = tagpWrMulte -> ucCntLo;
//起始寄存器
ui16Temp = tagpWrMulte -> ucStarAdrHi * 256ul + tagpWrMulte -> ucStarAdrLo;
if (ui16Temp >= AOCOUNT) return (ADR_ERR); //寄存器超出范围
//寄存器数量
ui16Len = tagpWrMulte -> ucCntHi * 256ul + tagpWrMulte -> ucCntLo;
if ((ui16Temp + ui16Len) > AOCOUNT) return (ADR_ERR); //寄存器超出范围
//置DO
i = 0;
while (i < ui16Len)
{
//取寄存器值
ui16Val = tagpWrMulte -> ucMess[i * 2] * 256ul +
tagpWrMulte -> ucMess[i *2 + 1];
//if (ui16Val > 4095) return (VAL_ERR); //寄存器值非法
ui16AoReg[ui16Temp] = ui16Val; //置寄存器
if (ui16Temp == AO_OUT_ADR)
{//AO0校正
Write_AO(0, 0);
}
else if (ui16Temp == (AO_OUT_ADR + 1) )
{//AO1校正
Write_AO(1, 0);
}
i++;
ui16Temp++;
}
//计算CRC
ui16Temp = CRC16((UCHAR *)tagpModRead, 6);
tagpModRead -> ucCrcHi = ui16Temp / 256;
tagpModRead -> ucCrcLo = ui16Temp;
//发送缓冲长度
*ucpLen = 8;
return (NO_ERR);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -