📄 com_232.c
字号:
/////////////////////////////////////////////////////////////////////////////
//
// 文件名: 版本
//
// com_232.c 0.03
//
// 概述:
// b5300系列装置通信任务处理程序
//
////////////////////////////////////////////////////////////////////////////
#include "typedef.h"
#include "hardef.h"
#include "sci_drv.h"
#include "flash_mng.h"
#include "set.h"
#include "set_drv.h"
#include "report.h"
#include "calcasm.h"
#include "func.h"
#include "mea.h"
#include "samcall.h"
#include "factor.h"
#include "bios.h"
#include "gl_convert.h"
#include "mmi_drv.h"
#include "com_232.h"
#include "main.h"
#include "initfunc.h"
//保护名称(ps64x.c中定义)
extern const char szRelayName[];
//应答命令表
const TCOMMANDTABLE tCmdTable[]=
{
{0x81,ReplyCmd81},
{0x82,ReplyCmd82},
{0x83,ReplyCmd83},
{0x84,ReplyCmd84},
{0x85,ReplyCmd85},
{0x86,ReplyCmd86},
{0x89,ReplyCmd89},
{0x8A,ReplyCmd8A},
{0x8B,ReplyCmd8B},
{0x8C,ReplyCmd8C},
{0x8E,ReplyCmd8E},
{0x8F,ReplyCmd8F},
{0x90,ReplyCmd90},
{0x91,ReplyCmd91},
{0x92,ReplyCmd92},
{0x93,ReplyCmd93},
{0x94,ReplyCmd94},
{0x95,ReplyCmd95},
{0x96,ReplyCmd96},
{0x98,ReplyCmd98},
{0x99,ReplyCmd99},
{0x9A,ReplyCmd9A},
{0x9B,ReplyCmd9B},
{0x9C,ReplyCmd9C},
{0x9E,ReplyCmd9E},
{0x9F,ReplyCmd9F},
{0xA0,ReplyCmdA0},
{0xA1,ReplyCmdA1},
{0xA2,ReplyCmdA2},
{0xA3,ReplyCmdA3},
{0xA4,ReplyCmdA4},
{0xA5,ReplyCmdA5},
{0xA6,ReplyCmdA6},
{0xAA,ReplyCmdAA},
{0xAB,ReplyCmdAB},
{0xAE,ReplyCmdAE},
{0xAF,ReplyCmdAF},
{0xB0,ReplyCmdB0},
{0xB5,ReplyCmdB5},
{0xB6,ReplyCmdB6},
{0xB7,ReplyCmdB7},
};
const int cstCmdNum=sizeof(tCmdTable)/sizeof(tCmdTable[0]);
//报文的目的地址=命令报文的原地址
//事件报文(17,18)目地址始终=DESTADDR
BYTE byDst=0;
//事件报文的目地址
const BYTE DESTADDR=0;
//应答报文缓冲区
BYTE caAckBuf[260];
//临时存放定值或遥控命令缓存(参见 Ack94,Ack95或98,99报文)
BYTE caTmpBuf[260];
//临时存放逻辑定值的接收缓冲
BYTE caTmpLogBuf[0x8000];
static FM_LOGIC_HEADER m_logic_head;
//逻辑定值接收缓冲指针
static BYTE *pTmpLogBuf;
//内存操作参数
TMEMRDWR tMemRdWr;
//95,99,9B命令执行状态
TCOMMAND tCmd=
{
0, //byCmd:命令
0, //byStatus:执行状态
0 //wDelay:定时计数器,>5"清除byCmd
};
static WORD m_232EventPos=0;
static WORD m_232AlarmPos=0;
static WORD m_232DiPos=0;
static WORD m_232SoePos=0;
static WORD m_232EventCopyPos=0;
// Sci通信任务
// 1)插入通信缓冲队列结构检查程序代码;
// 2)插入主动上送报告发送程序代码:上送报告缓冲区-->sci_out_buf队列;
// 关于上送报告用法的几点说明:
// a)各任务中需主动发送的信息,若实时性要求不高,则报送信息先添入
// 各自的信息缓冲区,在主程序调用SCI通信任务函数时由该函数自行调入
// SCI发送缓冲进行发送。本段程序即为此种方式而设置;
// b)若任务中主动发送的信息实时性要求较高,则可采用发送信息直接送入
// 发送缓冲的方式;
// 3)插入发送中断开放检查及启动发送中断程序代码;
// 在主程序中,调用此函数即完成与SCI串行通信有关的任务
static BYTE szRxBuf[272]; //接收缓冲区
void SciCommTask()
{
int len;
CommTask(0,0,0);
SendPolling(); //主动上送事件报告
SendTaskBuffer(); //发送多帧任务缓冲区报文
len=(int)SCI_Receive(szRxBuf);
if(len >= 7) // 报文长度最少5字节,加2字节dTCounter低16位
{
SciAck(szRxBuf,len);
}
return;
}
//========================================================
// 与通信任务有关的操作函数
//========================================================
//通信应答
//s =报文开始地址
//iLength=报文长度
void SciAck(BYTE *sBuf,int iRecLen)
{
BYTE *pt;
WORD wCount0;
//计算接收时的dTCounter的低16位
pt=sBuf+iRecLen-2;
wCount0=((WORD)(*pt++))<<8;
wCount0+=*pt;
pt=sBuf;
//如果报文目的地址=本CPU的地址或者=0xFF(广播报文),则处理此报文
if((*pt==byCpuN) || (*pt==0xff))
{
//byDst:应答报文的目的地址
pt++;
byDst=*pt++;
//解释执行命令应答
CommandReply(*pt,sBuf,wCount0);
}
}
//解释--执行命令表中的命令
void CommandReply(BYTE byCmd,BYTE *sBuf,WORD wFcount)
{
int i;
for(i=0; i < cstCmdNum; i++)
{
if(byCmd == tCmdTable[i].byCmdId)
{
tCmdTable[i].func(sBuf,wFcount);
return;
}
}
//命令表中不存在的命令视为非法命令
Send15();
}
//发送1个字节数组
//s=数组的开始地址,第一个字节=从第二字节开始有效字节数()
void SciPutn(BYTE * s)
{
BYTE byLen;
byLen =*s++;
SCI_Send(s,byLen);
}
//计算字节数组的SUM8(校验和)
//SUM8的反码被添加在数组尾部
//第1个字节给出数组长度(包括被添加的SUM8的反码)。根据规约要求,数组的长度 >= 5
bool MakeCs(BYTE *str)
{
WORD i;
BYTE *pt,c;
pt=str;
i=(WORD)(*pt++);
c=0;
if(i < 5) return FALSE;
for(; i > 1; i--) c +=*pt++;
*pt =(BYTE)~c;
return TRUE;
}
//10报文:装置上电
void Send10()
{
BYTE *s;
BYTE *cpAck;
int i,l;
//名称长度最多16字节(8个汉字)
l =0;
s =(BYTE *)szRelayName;
while(*s++ && l < 16) l++;
i =16-l;
s =(BYTE *)szRelayName;
cpAck =caAckBuf;
*cpAck++ =29;
*cpAck++ =byDst;
*cpAck++ =byCpuN;
*cpAck++ =0x10;
*cpAck++ =24;
//保护类型码
*cpAck++=RELAY_TYPE_LO;
*cpAck++=RELAY_TYPE_HI;
//保护名称长度16字节,不足时补空格(0x20)
while(l > 0)
{
*cpAck++=*s++;
l--;
}
while(i > 0)
{
*cpAck++=' ';
i--;
}
//软件版本号
*cpAck++=RELAY_VER_LO;
*cpAck++=RELAY_VER_HI;
//插入软件校验码
{
extern TSOFTINFO tSoftInfo;
WORD w =tSoftInfo.wProgCrc;
*cpAck++=(BYTE)w;
*cpAck++=(BYTE)(w>>8);
}
//插入配置信息校验码
*cpAck++=0;
*cpAck++=0;
MakeCs(caAckBuf);
SciPutn(caAckBuf);
}
//11报文:上报日历时钟
void Send11()
{
BYTE *cpAck;
TDATE td;
WORD w;
DateAsign(&td);
cpAck=caAckBuf;
*cpAck++=13;
*cpAck++=byDst;
*cpAck++=byCpuN;
*cpAck++=0x11;
*cpAck++=8;
*cpAck++=(BYTE)td.wYear;
*cpAck++=(BYTE)(td.wYear>>8);
*cpAck++=td.byMon;
*cpAck++=td.byDay;
*cpAck++=td.byHour;
*cpAck++=td.byMin;
w=td.wMs;
*cpAck++=(BYTE)w; //low byte
*cpAck++=(BYTE)(w>>8);//high byte
MakeCs(caAckBuf);
SciPutn(caAckBuf);
}
//12报文:准备发送配置信息
void Send12()
{
BYTE *s;
BYTE *cpAck;
int i,l;
//名称长度最多16字节(8个汉字)
l=0;
s=(BYTE *)szRelayName;
while(*s++ && l < 16) l++;
i =16-l;
s =(BYTE *)szRelayName;
cpAck=caAckBuf;
*cpAck++=29;
*cpAck++=byDst;
*cpAck++=byCpuN;
*cpAck++=0x12;
*cpAck++=24;
//保护类型码
*cpAck++=RELAY_TYPE_LO;
*cpAck++=RELAY_TYPE_HI;
//保护名称长度16字节,不足时补空格(0x20)
while(l > 0)
{
*cpAck++=*s++;
l--;
}
while(i > 0)
{
*cpAck++=(BYTE)' ';
i--;
}
//软件版本号
*cpAck++=RELAY_VER_LO;
*cpAck++=RELAY_VER_HI;
//插入软件校验码
{
extern TSOFTINFO tSoftInfo;
WORD w=tSoftInfo.wProgCrc;
*cpAck++=(BYTE)w;
*cpAck++=(BYTE)(w>>8);
}
//插入配置信息校验码
*cpAck++=0;
*cpAck++=0;
MakeCs(caAckBuf);
SciPutn(caAckBuf);
}
//否定回答
void Send15()
{
BYTE *cpAck;
cpAck=caAckBuf;
*cpAck++=5;
*cpAck++=byDst;
*cpAck++=byCpuN;
*cpAck++=0x15;
*cpAck++=0;
MakeCs(caAckBuf);
SciPutn(caAckBuf);
}
//肯定回答
void Send16()
{
BYTE *cpAck;
cpAck=caAckBuf;
*cpAck++=5;
*cpAck++=byDst;
*cpAck++=byCpuN;
*cpAck++=0x16;
*cpAck++=0;
MakeCs(caAckBuf);
SciPutn(caAckBuf);
}
//命令接收正确,但无所要的数据
void Send19()
{
BYTE *cpAck;
cpAck=caAckBuf;
*cpAck++=5;
*cpAck++=byDst;
*cpAck++=byCpuN;
*cpAck++=0x19;
*cpAck++=0;
MakeCs(caAckBuf);
SciPutn(caAckBuf);
}
//发送指定定值区的整定值
//ff=当前定值区
void Send23(WORD bn)
{
extern TSECTIONINFO tSecInfo;
short i;
BYTE *cpAck;
cpAck=caAckBuf;
*cpAck++=SET_NUMBER*3+7;
*cpAck++=byDst;
*cpAck++=byCpuN;
*cpAck++=0x23;
*cpAck++=SET_NUMBER*3+2;
*cpAck++=RELAY_TYPE_LO;
*cpAck++=RELAY_TYPE_HI;
if(bn == 0xff)
{
if( g_tSysErr.bErr[EV_SETERR] )
{
Send25(RES_SET_INVALID);
return;
}
bn=tSecInfo.byCurSec;
}
//从Flash memory中读取定值
if( !FM_Read_Set((BYTE)bn,cpAck) )
{
//定值错误,返回缺省值
TSETVAL *pSet;
pSet=(TSETVAL *)cpAck;
for(i =0; i < SET_NUMBER; i++)
{
*pSet++=tSetTable[i].tDef;
}
}
MakeCs(caAckBuf);
SciPutn(caAckBuf);
}
//操作结果
void Send25(BYTE res)
{
BYTE *cpAck;
cpAck=caAckBuf;
*cpAck++=8;
*cpAck++=byDst,*cpAck++=byCpuN;
*cpAck++=0x25;
*cpAck++=3;
*cpAck++=RELAY_TYPE_LO;
*cpAck++=RELAY_TYPE_HI;
*cpAck=res;
MakeCs(caAckBuf);
SciPutn(caAckBuf);
}
//2E:9E命令读取的内存单元的内容
//tMemRdWr
void Send2E()
{
BYTE u;
BYTE *cpAck,*pt;
if(tMemRdWr.byLen > 0xf0)
{
Send15();
return;
}
switch(tMemRdWr.byType)
{
case 1://RAM
if(tMemRdWr.dAddr < RAM_BEGIN || (tMemRdWr.dAddr+tMemRdWr.byLen) > RAM_END)
{
Send25(RES_MEM_OVRANGE);
return;
}
pt=(BYTE*)tMemRdWr.dAddr;
cpAck=caAckBuf;
*cpAck++=tMemRdWr.byLen+5+5;
*cpAck++=byDst,*cpAck++=byCpuN;
*cpAck++=0x2E;
*cpAck++=tMemRdWr.byLen+5;
*cpAck++=tMemRdWr.byType;
*cpAck++=(BYTE)tMemRdWr.dAddr;
*cpAck++=(BYTE)(tMemRdWr.dAddr >> 8);
*cpAck++=(BYTE)(tMemRdWr.dAddr >> 16);
*cpAck++=tMemRdWr.byLen;
//store M bytes
u=tMemRdWr.byLen;
while( u-- ) *cpAck++=*pt++;
MakeCs(caAckBuf);
SciPutn(caAckBuf);
return;
//case 2: //EEPROM
case 3: //FLASH MEMORY
if(tMemRdWr.dAddr < (DWORD)FM_BEGIN || (tMemRdWr.dAddr+tMemRdWr.byLen) > FM_END)
{
Send25(RES_MEM_OVRANGE);
return;
}
if ( !FM_LOCK_FLASH() )
{
Send15();
return;
}
pt =(BYTE *)tMemRdWr.dAddr;
cpAck=caAckBuf;
*cpAck++=tMemRdWr.byLen+5+5;
*cpAck++=byDst,*cpAck++=byCpuN;
*cpAck++=0x2E;
*cpAck++=tMemRdWr.byLen+5;
*cpAck++=tMemRdWr.byType;
*cpAck++=(BYTE)tMemRdWr.dAddr;
*cpAck++=(BYTE)(tMemRdWr.dAddr >> 8);
*cpAck++=(BYTE)(tMemRdWr.dAddr >> 16);
*cpAck++=tMemRdWr.byLen;
//store u bytes
u =tMemRdWr.byLen;
while( u-- ) *cpAck++ =*pt++;
FM_UNLOCK_FLASH();
MakeCs(caAckBuf);
SciPutn(caAckBuf);
return;
case 4: //EPROM
if((tMemRdWr.dAddr+tMemRdWr.byLen) > ROM_END)
{
Send25(RES_MEM_OVRANGE);
return;
}
pt=(BYTE*)tMemRdWr.dAddr;
cpAck=caAckBuf;
*cpAck++=tMemRdWr.byLen+5+5;
*cpAck++=byDst,*cpAck++=byCpuN;
*cpAck++=0x2E;
*cpAck++=tMemRdWr.byLen+5;
*cpAck++=tMemRdWr.byType;
*cpAck++=(BYTE)tMemRdWr.dAddr;
*cpAck++=(BYTE)(tMemRdWr.dAddr >> 8);
*cpAck++=(BYTE)(tMemRdWr.dAddr >> 16);
*cpAck++=tMemRdWr.byLen;
//store u bytes
u =tMemRdWr.byLen;
while( u-- ) *cpAck++=*pt++;
MakeCs(caAckBuf);
SciPutn(caAckBuf);
return;
default:
Send15();
}
}
//发送30报文
void Send30(BYTE *sBuf)
{
BYTE *pt;
WORD i,k;
DWORD dw;
long arg0,arg,lOff;
//以Ua的相位角作参考量
arg0=ptMea->lAng[SAM_UA];
//校验通道号
//ff=所有通道,否则指定一个通道
pt =sBuf+4;
i =(WORD)(*pt);
if(i == 0xff)
{
k=AI_NUMBER;
i=0;
}
else if(i > AI_NUMBER || i < 1)
{
Send25(RES_CHN_INVALID);
return;
}
else
{
i--;
k=1;
}
//发送有效值和相位角
//i=起始通道号
//k=通道数
pt=caAckBuf;
*pt++=(BYTE)(k*12+5);
*pt++=byDst;
*pt++=byCpuN;
*pt++=0x30;
*pt++=(BYTE)(k*12);
for(; k > 0; i++,k--)
{
if(i<=(AI_NUMBER-1))
{
dw=_MulFac2(ptMea->lrms[i],0x10000L,tMeaRelayTab[i].dKBL);
lOff=_MulFac2(ptMea->l0[i],0x10000L,tMeaRelayTab[i].dKBL);
arg=ptMea->lAng[i]-arg0;
}
else
{
dw=0;
lOff=0;
arg=0;
}
*pt++=(BYTE)dw;
*pt++=(BYTE)(dw>>8);
*pt++=(BYTE)(dw>>16);
*pt++=(BYTE)(dw>>24);
while(arg < -(180*65536L))
{
arg +=(360*65536L);
}
while(arg > (180*65536L))
{
arg -=(360*65536L);
}
*pt++=(BYTE)arg;
*pt++=(BYTE)(arg>>8);
*pt++=(BYTE)(arg>>16);
*pt++=(BYTE)(arg>>24);
*pt++=(BYTE)lOff;
*pt++=(BYTE)(lOff>>8);
*pt++=(BYTE)(lOff>>16);
*pt++=(BYTE)(lOff>>24);
}
MakeCs(caAckBuf);
SciPutn(caAckBuf);
}
//81:设置日历时钟
void ReplyCmd81(BYTE *sBuf,WORD wFrameCounter)
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -