📄 modbus.c
字号:
/*=====================================================================================
File name: Modbus.C (28x version)
Originator: R&D Group
NIE
Dsscription: communication base on Modbus
=====================================================================================
History:
-------------------------------------------------------------------------------------
03-17-2005 Release Rev 1.0
08-13-2005 Release Rev 1.02
: 修改了汉字传输的顺序,参数表可以直接输入汉字
-------------------------------------------------------------------------------------*/
#include "DSP281x_Device.h"
#include "DSP281x_Sci.h"
#include "Modbus.h" // Include header for Mudbus library
#include "fault_log.h"
extern FAULTLOG faultlog;
//#define FAULT_LOG_MAX 1
#define WAIT_DATA_HEAD 0 //等待报头
#define READ_DATA 1 //接受数据
#define PROCESSING_DATA 2 //处理数据
#define SEND_DATA 3 //发送响应报文
#define PARA_MAX_NUM 50
#define PARA_MAX_TBL_A 180
extern int Parameter0;
////////////rs485端口///////////////////////
void CommA(MODBUS *v)
{
int TempA,TempB,TempC;
long * TablePoint;
int * DataPoint;
//通讯帧故障清除
if(SciaRegs.SCIRXST.bit.RXERROR)
{
SciaRegs.SCICTL1.bit.SWRESET=0;
SciaRegs.SCICTL1.bit.SWRESET=1;
}
switch(v->CommFlag)
{
//接受报头
case WAIT_DATA_HEAD:
{
while((SciaRegs.SCIFFRX.bit.RXFIFST!=0)&&(v->CommFlag==0))
{
TempA=(SciaRegs.SCIRXBUF.all&0x00ff);
if((TempA==0x00ff)||(TempA==v->Slave_Address))
{
v->CommData[0]=TempA;
{ v->Index=1;
v->CommFlag=READ_DATA; //跳出本循环
v->CommCount=0;
}
}
}
break;
//接受数据
case READ_DATA:
v->CommCount++;
while(SciaRegs.SCIFFRX.bit.RXFIFST!=0)
{
v->CommData[v->Index]=(SciaRegs.SCIRXBUF.all&0x00ff); //
//if((v->CommData[v->Index]&0x0ff00)==0)
{ //数据必须正确
v->Index++;
if(v->Index>=PARANUMMAX)
{
v->Index=0;
v->CommFlag = WAIT_DATA_HEAD;
}
v->CommCount=0;
}
}
if(v->CommCount>=DELAYCOUNT)
{
v->CommFlag = PROCESSING_DATA;
}
}
break;
//处理报文,产生响应报文
case PROCESSING_DATA:
{
if(CRC_cal(v->CommData,v->Index)==0) //if1
{
switch(v->CommData[1])
{ //switch2
//MODBUS功能3
case 3:
{
TempA=(v->CommData[2]<<8)|(v->CommData[3]); //参数起始地址
switch(TempA)
{ //switch3
//菜单页参数读命令
case 919:
{
//固定长度响应报文
v->CommData[2]=32;
DataPoint=&ParaTblA[v->ParaNum][0] ;
//读取PARA_TAB中的数据
TempA=3;
while(TempA<(16*2+3))
{
v->CommData[TempA++]= ((*DataPoint)>>8)&0x00ff;
v->CommData[TempA++]= (*DataPoint)&0x00ff;
DataPoint++;
}
//写入实际数据
TablePoint=MenuInfo;
DataPoint=(int *)TablePoint[v->ParaNum];
v->CommData[29]=(*DataPoint>>8)&0xff; //写入报文地址
v->CommData[30]=(*DataPoint)&0x0ff; //写入报文地址
TempA=CRC_cal(v->CommData,35); //固定长度
v->CommData[35]=(TempA>>8)&0x00ff; //写入CRC校验位
v->CommData[36]=TempA&0x00ff;
v->Index = 36; //共计发送36个数据
v->CommCount = 0;
v->CommFlag = SEND_DATA; //转入发送
}
break;
//故障页读取
case 900:
{
v->CommData[2]=9*2; //固定报文格式
TempA=faultlog.log[v->FaultNum][0];
DataPoint=&FaultTabA[TempA][0];
//读取PARA_TAB中的数据
v->CommData[3]=(faultlog.log[v->FaultNum][1])>>8; //hour hi8
v->CommData[4]=faultlog.log[v->FaultNum][1]; //hour low8
v->CommData[5]=(faultlog.log[v->FaultNum][2])>>8; //minute
v->CommData[6]=faultlog.log[v->FaultNum][2]; //secend
v->CommData[7]=(faultlog.log[v->FaultNum][3])>>8; //ms hi8
v->CommData[8]=(faultlog.log[v->FaultNum][3]); //ms low8
TempA=9;
while(TempA<(9*2+9))
{
v->CommData[TempA++]= ((*DataPoint)>>8)&0x00ff;
v->CommData[TempA++]= (*DataPoint)&0x00ff;
DataPoint++;
}
//写入实际数据
TempA=CRC_cal(v->CommData,27); //固定长度
v->CommData[27]=(TempA>>8)&0x00ff; //写入CRC校验位
v->CommData[28]=TempA&0x00ff;
v->Index = 28; //共计发送29个数据
v->CommCount = 0;
v->CommFlag = SEND_DATA; //转入发送
}
break;
//其他,状态页读取
default:
{
if(TempA<100)// 操作盘数据读取
{
v->CommFlag = WAIT_DATA_HEAD;
}
else if(TempA<899) //参数读取
{
TablePoint=MenuInfo1;
TempA=TempA-100; //相对参数页首的偏移
if(TempA<PARA_MAX_TBL_A)
{
TempB=(v->CommData[4]<<8)|(v->CommData[5])-1; //数据个数
TempC=TempB+TempA; //
v->CommData[2]=TempB*2+2;
v->Index=TempB*2+4+1;
for(;TempB>=0;TempB--,TempC--)
{
DataPoint=(int *)TablePoint[TempC];
TempA = TempB*2+4;
v->CommData[TempA]=(*DataPoint)&0x0ff;
TempA--;
v->CommData[TempA]=(*DataPoint>>8)&0x0ff;
}
TempB=CRC_cal(v->CommData,v->Index); //个数=标号+1;
v->CommData[v->Index]=(TempB>>8)&0xff;
v->Index++;
v->CommData[v->Index]=TempB&0xff;
v->CommCount = 0;
v->CommFlag = SEND_DATA; //转入发送
}
else
{
v->CommFlag = WAIT_DATA_HEAD;
}
}
else if(TempA<2000) //事件读取
{
v->CommFlag = WAIT_DATA_HEAD;
}
else if(TempA<8031) //波形记录读取
{
DataPoint=(int*)(0x10bbcc);
//DataPoint[21]=1;
//DataPoint[22]=0;
TempA-=2001;
TempB=(v->CommData[4]<<8)|(v->CommData[5])-1; //数据个数
TempC=TempB+TempA; //
v->CommData[2]=TempB*2+2;
v->Index=TempB*2+4+1;
for(;TempB>=0;TempB--,TempC--)
{
TempA = TempB*2+4;
v->CommData[TempA]=DataPoint[TempC]&0x0ff;
TempA--;
v->CommData[TempA]=(DataPoint[TempC]>>8)&0x0ff;
}
TempB=CRC_cal(v->CommData,v->Index); //个数=标号+1;
v->CommData[v->Index]=(TempB>>8)&0xff;
v->Index++;
v->CommData[v->Index]=TempB&0xff;
v->CommCount = 0;
v->CommFlag = SEND_DATA; //转入发送
}
else //异常数据处理
{
v->CommFlag = WAIT_DATA_HEAD;
}
}
} //end switch3
} //end switch2 case3
break;
//MODBUS功能16 写数据
case 16:
{
TempA=(v->CommData[2]<<8)|(v->CommData[3]); //参数起始地址
switch(TempA)
{ //switch16
case 932:
{
TablePoint=MenuInfo;
DataPoint=(int *)TablePoint[v->ParaNum]; //数据地址
*DataPoint=(v->CommData[7]<<8)+(v->CommData[8]);
TempB=CRC_cal(v->CommData,6); //个数=标号+1;
v->CommData[6]=(TempB>>8)&0xff;
v->CommData[7]=TempB&0xff;
v->Index = 7;
v->CommCount = 0;
v->CommFlag = SEND_DATA; //转入发送
}
break;
case 918: //参数翻页信息处理
{
TempB=(v->CommData[7]<<8)+(v->CommData[8]);
if(TempB==2)
{
v->ParaNum--;
if(v->ParaNum < 0 )
v->ParaNum = MENU_MAX_NUMBER_TBLA -1;
}
else if(TempB==1)
{
v->ParaNum++;
if(v->ParaNum >= MENU_MAX_NUMBER_TBLA)
v->ParaNum = 0;
}
TempB=CRC_cal(v->CommData,6); //个数=标号+1;
v->CommData[6]=(TempB>>8)&0xff;
v->CommData[7]=TempB&0xff;
v->Index = 7;
v->CommCount = 0;
v->CommFlag = SEND_DATA; //转入发送
}
break;
case 912: //故障翻页信息
{
TempB=(v->CommData[7]<<8)+(v->CommData[8]);
if(TempB==2)
{
v->FaultNum--;
if(v->FaultNum < 0 )
v->FaultNum = FAULT_LOG_MAX -1;
}
else if(TempB==1)
{
v->FaultNum++;
if(v->FaultNum >= FAULT_LOG_MAX)
v->FaultNum = 0;
}
TempB=CRC_cal(v->CommData,6); //个数=标号+1;
v->CommData[6]=(TempB>>8)&0xff;
v->CommData[7]=TempB&0xff;
v->Index = 7;
v->CommCount = 0;
v->CommFlag = SEND_DATA; //转入发送
}
break;
default:
{
if(TempA < 100) //操作盘参数更新
{
v->Index = 0;
}
else if(TempA<900) //参数列表内参数数据更新
{
TablePoint=MenuInfo1;
// TablePoint=MenuInfo91;
TempA=TempA-100; //相对参数页首的偏移
TempB=(v->CommData[4]<<8)|(v->CommData[5])-1; //数据个数
TempC=TempB+TempA; //数据地址
v->Index=TempB*2+4+1;
for(;TempB>=0;TempB--,TempC--)
{
DataPoint=(int *)TablePoint[TempC];
TempA = TempB*2+7;
//增加权限控制
*DataPoint=(v->CommData[TempA]<<8)+v->CommData[TempA+1] ;
}
TempB=CRC_cal(v->CommData,6); //个数=标号+1;
v->CommData[6]=(TempB>>8)&0xff;
v->CommData[7]=TempB&0xff;
v->Index = 7;
v->CommCount = 0;
v->CommFlag = SEND_DATA; //转入发送
}
else if(TempA<=2000)
{
v->Index = 0; //对事件记录部分修改无效
}
else if(TempA<=2021) //
{
TempA=TempA-2001; //相对页首的偏移
TempB=(v->CommData[4]<<8)|(v->CommData[5])-1; //数据个数
DataPoint=(int *)(0x10bbcc+TempA);
TempC=TempB+TempA; //数据地址
DataPoint=(int *)(0x10bbcc+TempC);
v->Index=TempB*2+4+1;
for(;TempB>=0;TempB--)
{
TempA = TempB*2+7;
//增加权限控制
*(DataPoint--)=(v->CommData[TempA]<<8)+v->CommData[TempA+1] ;
}
TempB=CRC_cal(v->CommData,6); //个数=标号+1;
v->CommData[6]=(TempB>>8)&0xff;
v->CommData[7]=TempB&0xff;
v->Index = 7;
v->CommCount = 0;
v->CommFlag = SEND_DATA; //转入发送
}
else
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -