📄 modbus.c
字号:
tmp[2] = start_address>>8; //起始地址 高字节
tmp[3] = start_address & 0xFF; //起始地址 低字节
tmp[4] = lenth>>8; //读取数据量 高字节
tmp[5] = lenth & 0xFF; //读取数据量 低字节
tmp_lenth = 6; //二进制包长度
ConstructRtuFrame(GwSciTxBuffer, tmp, tmp_lenth);
GwSciTxBytes = tmp_lenth+2;
if(lenth % 8==0)
{
GwSciRxBytes=(lenth/8)+3+2; // lenth/8线圈状态的字节数,3为地址码,功能码,字节数,2为两个CRC字节
}
else
{
GwSciRxBytes=(lenth/8+1)+3+2;
}
SciSend(); //发送请求
SciReceive(); //接收设备响应
//获取应答;对应答数据分析;对接收到的应答数据分析
if(GwSciRxBuffer[1] == 0x02) //通信正常,数据处理
{
ProcessMasterRTU(pwInState,GwSciRxBuffer,0,GwSciRxBytes);
}
else //查询异常码,可重新发送请求或作其他处理
{
return(CMD_ERR);
}
}
// 功能 :读取保持寄存器:CMD == 3
// 返回 :成功返回1,否则返回0
// 请求命令:[设备地址] [命令号03] [起始寄存器地址高8位] [低8位] [读取的寄存器个数,高8位] [低8位] [CRC校验的高8位] [CRC校验的低8位]
// 设备响应:[设备地址] [命令号03] [返回的字节个数][数据1][数据2]...[数据n][CRC校验的低高8位] [CRC校验的低8位]
char ReadHldreg(unsigned int *pwHldregState, unsigned char DeviceID, unsigned int start_address, unsigned int lenth)
{
unsigned char tmp[64], tmp_lenth,flag;
tmp[0] = DeviceID; //从设备地址
tmp[1] = 0x03; //命令
tmp[2]=start_address>>8; //起始地址 高字节
tmp[3]=start_address & 0xFF; //起始地址 低字节
tmp[4]=lenth>>8; //读取寄存器个数 高字节
tmp[5]=lenth & 0xFF; //读取寄存器个数 低字节
tmp_lenth = 6;
ConstructRtuFrame(GwSciTxBuffer, tmp, tmp_lenth);
GwSciTxBytes = tmp_lenth+2;
GwSciRxBytes=lenth*2+3+2; //地址码,功能码,字节数共占3字节,CRC占2字节
SciSend(); //发送请求
SciReceive(); //接收设备响应
if(GwSciRxBuffer[1]==0x03)
ProcessMasterRTU(pwHldregState,GwSciRxBuffer,0,GwSciRxBytes);
else //通信异常0x83,查询异常码,可重新发送请求或作其他处理
{
return(CMD_ERR);
}
}
// 功能 :读取模拟量输入:CMD == 4
// 返回 :成功返回1,否则返回0
// 请求命令:[设备地址] [命令号04] [起始寄存器地址高8位] [低8位] [读取的寄存器数高8位] [低8位] [CRC校验的低8位] [CRC校验的高8位]
// 设备响应:[设备地址] [命令号04] [返回的字节个数][数据1][数据2]...[数据n][CRC校验的低8位] [CRC校验的高8位]
char ReadAnlogIn(unsigned int *pwAnologInState, unsigned char DeviceID, unsigned int start_address, unsigned int lenth)
{
unsigned char tmp[64], tmp_lenth;
tmp[0] = DeviceID; //从设备地址
tmp[1] = 0x04; //命令
tmp[2] = start_address>>8; //起始地址 高字节
tmp[3] = start_address & 0xFF; //起始地址 低字节
tmp[4] = lenth>>8; //读取数据量 高字节
tmp[5] = lenth & 0xFF ; //读取数据量 低字节
tmp_lenth = 6;
ConstructRtuFrame(GwSciTxBuffer, tmp, tmp_lenth);
GwSciTxBytes = tmp_lenth+2;
GwSciRxBytes = lenth*2+3+2; //地址码,功能码,字节数占3字节,CRC占2字节
SciSend(); //发送请求
SciReceive(); //接收设备响应
//获取应答;对应答数据分析;对接收到的应答数据分析
if(GwSciRxBuffer[1] == 0x04) //通信正常,数据处理
{
ProcessMasterRTU(pwAnologInState,GwSciRxBuffer,0,GwSciRxBytes);
}
else //通信异常0x83,查询异常码,可重新发送请求或作其他处理
{
return(CMD_ERR);
}
}
// 功能 :设置继电器:CMD == 5
// 返回 :成功返回1,否则返回0
// 请求命令:[设备地址] [命令号05] [需下置的寄存器地址高8位] [低8位] [下置的数据高8位] [低8位] [CRC校验的低8位] [CRC校验的高8位]
// 设备响应:如果成功把计算机发送的命令原样返回,否则不响应
char SetCoil(unsigned char DeviceID, unsigned int start_address, unsigned int value)
{
unsigned char tmp[64], tmp_lenth;
tmp[0] = DeviceID; //从设备地址
tmp[1] = 0x05 ; //命令
tmp[2] = start_address>>8; //起始地址 高字节
tmp[3] = start_address & 0xFF; //起始地址 低字节
tmp[4] = value>>8; //待写数据 高字节
tmp[5] = value & 0xFF; //待写数据 低字节
tmp_lenth = 6;
ConstructRtuFrame(GwSciTxBuffer, tmp, tmp_lenth);
GwSciTxBytes = tmp_lenth+2;
GwSciRxBytes = 6+2;
SciSend(); //发送请求
SciReceive(); //接收设备响应
if(GwSciRxBuffer[1] == 0x05) //通信正常,数据处理
{
if(CheckCRC(GwSciRxBuffer,GwSciRxBytes))
{
if(GwSciRxBuffer[2]!=GwSciTxBuffer[2]) return(0);
if(GwSciRxBuffer[3]!=GwSciTxBuffer[3]) return(0);
if(GwSciRxBuffer[4]!=GwSciTxBuffer[4]) return(0);
if(GwSciRxBuffer[5]!=GwSciTxBuffer[5]) return(0);
return(1);
}
else //CRC校验不一致;可重新发送请求或作其他处理
{
return(CRC_ERR);
}
}
else //通信异常0x83,查询异常码,可重新发送请求或作其他处理
{
return(CMD_ERR);
}
}
// 功能 :设置单保持寄存器 CMD == 6
// 返回 :成功返回1,否则返回0
// 请求命令:[设备地址] [命令号06] [需下置的寄存器地址高8位] [低8位] [下置的数据高8位] [低8位] [CRC校验的低8位] [CRC校验的高8位]
// 设备响应:如果成功把计算机发送的命令原样返回,否则不响应
char SetHldreg(unsigned char DeviceID, unsigned int start_address, unsigned int value)
{
unsigned char tmp[64], tmp_lenth;
tmp[0] = DeviceID; //地址
tmp[1] = 0x06; //命令
tmp[2] = start_address>>8; //写数据的起始地址 高字节
tmp[3] = start_address & 0xFF; //写数据的起始地址 低字节
tmp[4] = value>>8; //待写数据 高字节
tmp[5] = value & 0xFF; //待写数据 低字节
tmp_lenth = 6; //有效数据长度
ConstructRtuFrame(GwSciTxBuffer, tmp, tmp_lenth);
GwSciTxBytes = tmp_lenth+2;
GwSciRxBytes = 6+2;
SciSend(); //发送请求
SciReceive(); //接收设备响应
//获取应答;对应答数据分析;对接收到的应答数据分析
if(GwSciRxBuffer[1] == 0x06) //通信正常,数据处理
{
if(CheckCRC(GwSciRxBuffer,GwSciRxBytes))
{
if(GwSciRxBuffer[2]!=GwSciTxBuffer[2]) return(0);
if(GwSciRxBuffer[3]!=GwSciTxBuffer[3]) return(0);
if(GwSciRxBuffer[4]!=GwSciTxBuffer[4]) return(0);
if(GwSciRxBuffer[5]!=GwSciTxBuffer[5]) return(0);
return(1);
}
else //CRC校验不一致;可重新发送请求或作其他处理
{
return(CRC_ERR);
}
}
else //通信异常0x83,查询异常码,可重新发送请求或作其他处理
{
return(CMD_ERR);
}
}
// 功能 :对多个线圈进行强制:CMD == 15
// 返回 :成功返回1,否则返回0
// 请求格式:从站地址 0x0F 第一个位首地址 所写位数 值占用的字节数 值
// (例如,置从站5的位12至17为1,则:05 0F 000C 0006 01 3F CRC)
char SetCoils(unsigned char DeviceID, unsigned int Startbit_Add, unsigned int Bit2Write, unsigned char ByteValue, unsigned char *Values)
{
unsigned char tmp[64], tmp_lenth,i;
tmp[0] = DeviceID;
tmp[1] = 0x0f ;
tmp[2] = Startbit_Add>>8;
tmp[3] = Startbit_Add & 0xFF;
tmp[4] = Bit2Write>>8;
tmp[5] = Bit2Write & 0xFF;
tmp[6] = ByteValue;
for(i=0;i<ByteValue;i++)
tmp[7+i] = Values[i];
tmp_lenth = 7+ByteValue;
ConstructRtuFrame(GwSciTxBuffer, tmp, tmp_lenth);
GwSciTxBytes = tmp_lenth+2;
GwSciRxBytes = 6+2;
SciSend(); //发送CMD请求
SciReceive(); //接收设备响应
//获取应答;对应答数据分析;对接收到的应答数据分析
if(GwSciRxBuffer[1] == 0x0F) //通信正常,数据处理
{
if(CheckCRC(GwSciRxBuffer,GwSciRxBytes))
{
if(GwSciRxBuffer[2]!=GwSciTxBuffer[2]) return(0);
if(GwSciRxBuffer[3]!=GwSciTxBuffer[3]) return(0);
if(GwSciRxBuffer[4]!=GwSciTxBuffer[4]) return(0);
if(GwSciRxBuffer[5]!=GwSciTxBuffer[5]) return(0);
return(1);
}
else //CRC校验不一致;可重新发送请求或作其他处理
{
return(CRC_ERR);
}
}
else //通信异常0x83,查询异常码,可重新发送请求或作其他处理
{
return(CMD_ERR);
}
}
char SetMultiHldreg(unsigned char DeviceID, unsigned int start_address, unsigned int WNum, unsigned char BNum, unsigned int *values)
{
unsigned char tmp[256], tmp_lenth;
unsigned char i=0;
unsigned int j;
tmp[0] = DeviceID; //地址
tmp[1] = 0x10; //命令
tmp[2] = start_address>>8; //写数据的起始地址 高字节
tmp[3] = start_address & 0xFF; //写数据的起始地址 低字节
tmp[4] = WNum>>8; //待写寄存器数量
tmp[5] = WNum & 0xFF; //待写寄存器数量
tmp[6] = BNum; //待写数据的字节数
for(j=0;j<WNum;j++) //填充数据
{
tmp[i+7] = values[j]>>8; //待写数据 高字节
tmp[i+8] = values[j] & 0xFF;//待写数据 低字节
i=i+2;
}
tmp_lenth = 7+i; //有效数据长度
ConstructRtuFrame(GwSciTxBuffer, tmp, tmp_lenth);
GwSciTxBytes = tmp_lenth+2;
GwSciRxBytes = 6+2;
SciSend(); //发送CMD请求
SciReceive(); //接收设备响应
//获取应答;对应答数据分析;对接收到的应答数据分析
if(GwSciRxBuffer[1] == 0x0F) //通信正常,数据处理
{
if(CheckCRC(GwSciRxBuffer,GwSciRxBytes))
{
if(GwSciRxBuffer[2]!=GwSciTxBuffer[2]) return(0);
if(GwSciRxBuffer[3]!=GwSciTxBuffer[3]) return(0);
if(GwSciRxBuffer[4]!=GwSciTxBuffer[4]) return(0);
if(GwSciRxBuffer[5]!=GwSciTxBuffer[5]) return(0);
return(1);
}
else //CRC校验不一致;可重新发送请求或作其他处理
{
return(CRC_ERR);
}
}
else //通信异常0x83,查询异常码,可重新发送请求或作其他处理
{
return(CMD_ERR);
}
}
void interrupt SCI_INT()
{
switch(PIVR)
{
case 0x0006:
{
//置SCI接收中断标志
GwSciRxFlag = 1;
//todo:把接收数据放在中断服务程序中
//GwSciRxBuffer[GwRxCount] = SCIRXBUF;
//todo:通过读SCIRXBUF就可以清除SCIRXST的RXRDY位,下面的判断是否可去掉
//while((SCIRXST & 0x40)!=0); //查看SCIRXST的RXRDY位,判断SCIRXBUF中的数据是否读完
//GwRxCount++;
break;
}
default:
break;
}
//todo:当一个中断被响应时,系统会自动清除IFR中相应的标志位,下面的清除是否必要
//IFR = 0x0001; //清IFR相应中断标志
Enable(); //开总中断
//return; //返回
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -