Files
LaserTracing_Debug/Project/GateWay/source/User/Src/RS485Task.c
T

624 lines
19 KiB
C
Raw Normal View History

2026-04-23 13:56:52 +08:00
#include "main.h"
#include "RS485Task.h"
#include "Public.h"
#include "spiflash.h"
#include "CatOneTask.h"
#include "DebugCmd.h"
#include "update_protocol.h"
#include "bsp.h"
//#define RS485_DBG_LOG(...) { if(RS485DispEn) Debug_Printf(__VA_ARGS__);}
//static uint8_t RS485DispEn = false;
SensorCommPara_t SComm1Para;
SensorCommPara_t SComm2Para;
const uint8_t RS485SensorCmdPayLoadLen[RS485_SENSOR_CMD_END] = {0, 0, 0, 1, 0};
/*****************************************************************************************
* 函数名称: SavSensorData
* 功能描述: 记录传感器数据
* 参 数: SensorIdx, 传感器序号
Para,传感器结构指针
Data, 传感器数据
Len, 传感器数据长度
* 返 回 值: 无
*****************************************************************************************/
static void SavSensorData(uint8_t SensorIdx, CommUnitData CUData, uint8_t *Data, uint8_t Len)
{
if(Data == NULL) {
memset(CUData->Data[SensorIdx], 0x00, SENSOR_DATA_LEN_MAX);
}
else {
memcpy(CUData->Data[SensorIdx], Data, Len);
}
}
/*****************************************************************************************
* 函数名称: RS485Analyze
* 功能描述: 485数据解析
* 参 数: SCPara, 传感器发送参数
Para, 传感器结构指针
rData, 传感器数据入口
rLen, 传感器数据长度
* 返 回 值: 无
*****************************************************************************************/
void RS485Analyze(GateWayPara GateWay, SensorCommPara SCPara, CommUnit Para, uint8_t *rData, uint8_t rLen)
{
uint16_t crc16;
uint8_t *Payload;
crc16 = (rData[rLen - 1] << 8)|rData[rLen - 2];
uint16_t Check = CRC_Modbus(0xA001, rData, rLen - 2);
if(crc16 != Check)
return;
FrameHeader Header = (FrameHeader)rData;
if(Header->Cmd != RS485_SENSOR_CMD_QUERY) {
if(Header->SlvAddr != SCPara->SensorAddr)
return;
}
Payload = &rData[sizeof(FrameHeader)];
if(Header->PayloadLen == 0)
return;
if(Header->SlvAddr == 0 || Header->SlvAddr > SENSOR_NUM_MAX)
return;
SCPara->SensorErrCnt[Header->SlvAddr - 1] = 0;
switch(Header->Cmd) {
case RS485_SENSOR_CMD_SET_ADDR:
if(*Payload == 1) {
MAIN_DBG_LOG("Sensor%d Addr Set succeed!\r\n", Header->SlvAddr);
}
else {
MAIN_DBG_LOG("Sensor%d Addr Set failed!\r\n", Header->SlvAddr);
}
break;
case RS485_SENSOR_CMD_CAIL:
if(*Payload == 1) {
MAIN_DBG_LOG("Sensor%d calibration succeeded!\r\n", Header->SlvAddr);
}
else {
MAIN_DBG_LOG("Sensor%d calibration succeeded!\r\n", Header->SlvAddr);
}
break;
case RS485_SENSOR_CMD_QUERY:
if(Para->Para.SensorN < 16) {
Para->Para.SensorN++;
Para->Para.SensorType[SCPara->SensorAddr - 1] = rData[6] | (rData[7] << 8);
MAIN_DBG_LOG("Found Sensor%d, Type: %d!\r\n", Header->SlvAddr, Para->Para.SensorType[SCPara->SensorAddr - 1]);
}
break;
case RS485_SENSOR_CMD_READ: {
memcpy(SCPara->SensorData.Data[SCPara->SensorAddr - 1], &rData[sizeof(FrameHeader_t)], Header->PayloadLen);
if(SCPara->SendFlag)
SCPara->ReadSensorCnt++;
DebugDisplaySensorData(Header->SlvAddr, 0, &rData[sizeof(FrameHeader_t)]);
}
default:
break;
}
}
static void update_on_start(uint8_t* frame, int len, uint8_t* pload, int size)
{
update_protocol_req_t* pReq = (void*)&frame[sizeof(update_protocol_hd_t)];
//TODO:
boot_para_t cfg = {0};
cfg.AppFlag = 0;
cfg.UpdateFlag = APP_UPDATE_FLAG;
cfg.Crc32Check = pReq->AppCrc32;
cfg.PackageNum = pReq->PackageNum;
cfg.AppSize = pReq->AppSize;
/**
操作FALSH ,写升级参数
**/
dev_boot_write_param(cfg);
update_send_cmd(0x01, 1, pReq->PackageNum);
//重启进入BOOT
NVIC_SystemReset();
}
static int update_cmd_process(uint8_t cmd, void* frame, int len, void* pload, int size)
{
int res = -1;
switch (cmd) {
case 0x81: {
update_on_start(frame, len, pload, size);
res = 0;
}
break;
default:
break;
}
return res;
}
static int update_process(void* frame, int len)
{
uint8_t cmd = 0;
uint8_t slave_addr = 0;
uint8_t user_data[256] = {0};
int user_data_len = 0;
int res = update_unpack(frame, len, &cmd, &slave_addr, user_data, &user_data_len);
if (res != 0)
return -1;
if (slave_addr != 0x01)
return -2;
res = update_cmd_process(cmd, frame, len, user_data, user_data_len);
if (res != 0)
return -3;
return 0;
}
/*****************************************************************************************
* 函数名称: RS485SensorCmdSend
* 功能描述: 下发传感器指令函数
* 参 数: Para,通讯参数入口
* 返 回 值: 无
*****************************************************************************************/
static void RS485SensorCmdSend(GateWayPara GateWay, SensorCommPara SensorComm)
{
uint8_t sData[50];
uint8_t sLen;
if(SensorComm->Cmd >= RS485_SENSOR_CMD_END)
return;
FrameHeader Header = (FrameHeader)sData;
Header->Header = 0x7C;
Header->SlvAddr = SensorComm->SensorAddr;
Header->Cmd = SensorComm->Cmd;
//Header->DevType = SensorComm->SensorType;
Header->PayloadLen = SensorComm->CmdParaLen;
sLen = sizeof(FrameHeader_t);
if(SensorComm->CmdParaLen > 0) {
memcpy(&sData[sLen], SensorComm->CmdPara, SensorComm->CmdParaLen);
sLen += SensorComm->CmdParaLen;
}
uint16_t Check = CRC_Modbus(0xA001, sData, sLen);
sData[sLen++] = Check & 0xff;
sData[sLen++] = (Check >> 0x08) & 0x00ff;
if(SensorComm == &SComm1Para)
GateWay->ConfigPara.Rs485Ch1.RS485Send(sData, sLen);
else
GateWay->ConfigPara.Rs485Ch2.RS485Send(sData, sLen);
}
/*****************************************************************************************
* 函数名称: RS485SensorCmdSend
* 功能描述: 下发传感器指令函数
* 参 数: CommUintAddr 通讯单元地址
Para,通讯参数入口
* 返 回 值: 无
*****************************************************************************************/
void RS485CmdSend(GateWayPara GateWay, uint8_t CommUintAddr, SensorCommPara SensorComm)
{
SensorCommPara SC;
if(CommUintAddr)
SC = &SComm1Para;
else
SC = &SComm2Para;
SC->Cmd = SensorComm->Cmd;
SC->CmdPara = SensorComm->CmdPara;
SC->CmdParaLen = SensorComm->CmdParaLen;
SC->SensorAddr = SensorComm->SensorAddr;
//SC->SensorType = SensorComm->SensorType;
RS485SensorCmdSend(GateWay, SC);
}
/*****************************************************************************************
* 函数名称: RS485LoopHandler
* 功能描述: RS485循环处理函数
* 参 数: GateWay, 网关参数句柄
RS485Ch, RS485通道句柄
SCPara RS485通讯句柄
* 返 回 值: 无
*****************************************************************************************/
static uint8_t CommUintData[512];
int test = 0;
void RS485LoopHandler(GateWayPara GateWay, RS485Para RS485Ch, SensorCommPara SCPara)
{
uint8_t RxBuffTemp[RS485_RX_BUFF_LEN_MAX];
uint8_t RxLenTemp;
uint16_t CommUintLen;
rt_err_t result;
uint8_t MegData[9];
int ret;
if(RS485Ch->Enable == false) {
rt_thread_delay(10);
return;
}
if(RS485Ch->CommUnitEnable == true) { //使用内置通讯单元
if(RS485Ch->QuerySensorFlag == true) { //开机查找传感器
if(SCPara->SensorCnt < SENSOR_NUM_MAX) {
rt_thread_delay(50);
SCPara->Cmd = RS485_SENSOR_CMD_QUERY;
SCPara->SensorAddr = SCPara->SensorCnt + 1;
SCPara->SensorType = 0;
SCPara->CmdParaLen = RS485SensorCmdPayLoadLen[RS485_SENSOR_CMD_QUERY];
SCPara->CmdPara = NULL;
//rt_mutex_take(GateWay->UartRevMutex, RT_WAITING_FOREVER);
SCPara->RS485TimeOutCnt = 0;
SCPara->RS485RxLen = 0;
RS485SensorCmdSend(GateWay, SCPara);
SCPara->SendFlag = true;
SCPara->SensorCnt++;
if(SCPara->SensorCnt >= SENSOR_NUM_MAX) {
SCPara->ReadSensorInterval = 2;
SCPara->SensorCnt = 0;
SCPara->ReadSensorCnt = 0;
RS485Ch->QuerySensorFlag = false;
}
}
}
else if(RS485Ch->CUData.Para.SensorN > 0){
SCPara->SendFlag = false;
if(SCPara->ReadSensorInterval > 0) {
SCPara->ReadSensorInterval--;
}
else {
if(SCPara->ReadSensorCnt >= RS485Ch->CUData.Para.SensorN || SCPara->SensorCnt >= SENSOR_NUM_MAX) {
SCPara->SensorCnt = 0;
SCPara->ReadSensorCnt = 0;
SCPara->ReadSensorInterval = GateWay->ConfigPara.CommUnitReadInterval * 5;
RS485Ch->CUData.Para.BatLevel = GateWay->Battery;
CommUintLen = CommUintOrgData(GateWay, &RS485Ch->CUData.Para, &SCPara->SensorData, CommUintData);
//AddLog(&CommUintData[2], CommUintLen - 2);
CatOneEthSendQueue(CommUintData, CommUintLen);
if(RS485Ch == &GateWay->ConfigPara.Rs485Ch1) {
MAIN_DBG_LOG("InCommUint1 Send Meg...\r\n");
}
else {
MAIN_DBG_LOG("InCommUint2 Send Meg...\r\n");
}
SCPara->SensorCnt = 0;
}
else {
if(RS485Ch->CUData.Para.SensorType[SCPara->SensorCnt] != 0) {
rt_thread_delay(50);
SCPara->Cmd = RS485_SENSOR_CMD_READ;
SCPara->SensorAddr = SCPara->SensorCnt + 1;
SCPara->SensorType = RS485Ch->CUData.Para.SensorType[SCPara->SensorCnt];
SCPara->CmdParaLen = RS485SensorCmdPayLoadLen[RS485_SENSOR_CMD_READ];
SCPara->CmdPara = NULL;
//rt_mutex_take(GateWay->UartRevMutex, RT_WAITING_FOREVER);
RS485SensorCmdSend(GateWay, SCPara);
SCPara->SendFlag = true;
}
SCPara->SensorCnt++;
}
}
}
}
else { //读取外置通讯单元
if(SCPara->RS485CommUnitReadTimeDelay >= (GateWay->ConfigPara.CommUnitReadInterval * 5) && SCPara->SendFlag == false) {
if(SCPara->SendUnitCommIdx < COMMUNIT_NUM_MAX) {
if(GateWay->ConfigPara.CommUnitArray[SCPara->SendUnitCommIdx].RegFlag &&
GateWay->ConfigPara.CommUnitArray[SCPara->SendUnitCommIdx].Mac[0][2] == 0x02) {
Debug_Printf("RS485Ch%d Read CommUnit: %02X:%02X:%02X:%02X:%02X:%02X\r\n",
((SCPara == &SComm1Para) ? 1 : 2),
GateWay->ConfigPara.CommUnitArray[SCPara->SendUnitCommIdx].Mac[0][0],
GateWay->ConfigPara.CommUnitArray[SCPara->SendUnitCommIdx].Mac[0][1],
GateWay->ConfigPara.CommUnitArray[SCPara->SendUnitCommIdx].Mac[0][2],
GateWay->ConfigPara.CommUnitArray[SCPara->SendUnitCommIdx].Mac[0][3],
GateWay->ConfigPara.CommUnitArray[SCPara->SendUnitCommIdx].Mac[0][4],
GateWay->ConfigPara.CommUnitArray[SCPara->SendUnitCommIdx].Mac[0][5]);
CommUnitCmdSend(GateWay, GateWay->ConfigPara.CommUnitArray[SCPara->SendUnitCommIdx].Mac[0], COMM_UNIT_CMD_READ, NULL, 0, RS485Ch->RS485Send);
SCPara->SendFlag = true;
}
else {
SCPara->SendUnitCommIdx++;
return;
}
}
else {
SCPara->SendUnitCommIdx = 0;
SCPara->RS485CommUnitReadTimeDelay = 0;
}
}
}
if(SCPara->RS485CommUnitReadTimeDelay < (GateWay->ConfigPara.CommUnitReadInterval * 5))
SCPara->RS485CommUnitReadTimeDelay++;
result = rt_sem_take(SCPara->RS485Rev_Sem, 200);
if(result == RT_EOK) {
memcpy(RxBuffTemp, SCPara->RS485RxBuff, SCPara->RS485RxLen);
RxLenTemp = SCPara->RS485RxLen;
// memset(SCPara->RS485RxBuff, 0x00, RS485_RX_BUFF_LEN_MAX);
SCPara->RS485RxLen = 0;
if(RxBuffTemp[0] == 0x7A && RS485Ch->UpgradeEnable == true) { //升级
update_process(RxBuffTemp,RxLenTemp);
}
else if(RxBuffTemp[0] == 0x7A && RS485Ch->CommUnitEnable == true) { //内置通讯单元数据解析
if(SCPara->SendFlag == false) {
SCPara->RS485RxLen = 0;
return;
}
RS485Analyze(GateWay, SCPara, &RS485Ch->CUData, RxBuffTemp, RxLenTemp);
//rt_mutex_release(GateWay->UartRevMutex);
}
else if(RxBuffTemp[0] == 0x7B && RS485Ch->CommUnitEnable == false){ //读取外部通讯单元数据解析
if(SCPara == &SComm1Para)
ret = GateWay->CommUnitRevCallBack(GateWay, RxBuffTemp, RxLenTemp, GateWay->ConfigPara.Rs485Ch1.RS485Send);
else
ret = GateWay->CommUnitRevCallBack(GateWay, RxBuffTemp, RxLenTemp, GateWay->ConfigPara.Rs485Ch2.RS485Send);
if(ret == 0xff) { //注册信息
SCPara->RS485RxLen = 0;
return;
}
if(SCPara->SendFlag && GateWay->ConfigPara.CommUnitArray[SCPara->SendUnitCommIdx].RevNewDataFlag) {
SCPara->SendUnitCommIdx++;
}
else {
SCPara->RS485RxLen = 0;
return;
}
}
else { //调试命令解析
DebugAnalyze(GateWay, RxBuffTemp, RxLenTemp);
}
SCPara->RS485RxLen = 0;
SCPara->SendFlag = false;
}
else {
if(RS485Ch->CommUnitEnable == true) {
//rt_mutex_release(GateWay->UartRevMutex);
if(SCPara->SendFlag == true) { //&& RS485Ch->CUData.Para.SensorN > 0 && RS485Ch->QuerySensorFlag == false){
if(RS485Ch == &GateWay->ConfigPara.Rs485Ch1) {
test++;
MAIN_DBG_LOG("InCommUint1, Sensor %d Comm Error, Cmd %d...\r\n", SCPara->SensorAddr, SCPara->Cmd);
}
else {
MAIN_DBG_LOG("InCommUint2, Sensor %d Comm Error, Cmd %d...\r\n", SCPara->SensorAddr, SCPara->Cmd);
}
SCPara->SensorErrCnt[SCPara->SensorAddr - 1]++;
if(SCPara->SensorErrCnt[SCPara->SensorAddr - 1] >= 5)
SavSensorData(SCPara->SensorAddr - 1, &SCPara->SensorData, NULL, 0);
}
}
else if(SCPara->SendFlag){
GateWay->ConfigPara.CommUnitArray[SCPara->SendUnitCommIdx].CommErrCnt++;
if(GateWay->ConfigPara.CommUnitArray[SCPara->SendUnitCommIdx].CommErrCnt == 10) {
GateWay->ConfigPara.CommUnitArray[SCPara->SendUnitCommIdx].CommErrCnt = 0;
if(GateWay->ConfigPara.CommUnitArray[SCPara->SendUnitCommIdx].CommStatus) {
GateWay->ConfigPara.CommUnitArray[SCPara->SendUnitCommIdx].CommStatus = 0;
MegData[0] = 7;
MegData[1] = COMM_UNIT_CMD_READ;
memcpy(&MegData[2], GateWay->ConfigPara.CommUnitArray[SCPara->SendUnitCommIdx].Mac[0], 6);
MegData[8] = GateWay->ConfigPara.CommUnitArray[SCPara->SendUnitCommIdx].CommStatus;
CatOneEthSendQueue(MegData, 9); //发送离线消息
}
}
SCPara->SendUnitCommIdx++;
}
SCPara->SendFlag = false;
}
}
/*****************************************************************************************
* 函数名称: RS485Ch1_Thread_Entry
* 功能描述: RS485通道1任务函数
* 参 数: 任务参数入口
* 返 回 值: 无
*****************************************************************************************/
void RS485Ch1_Thread_Entry(void *parameter)
{
uint8_t InCommUnitMac[6] = {0x01, 0x80, 0x02, 0x00, 0x00, 0x01};
GateWayPara GateWay;
SensorCommPara SCPara;
RS485Para RS485Ch;
SCPara = &SComm1Para;
SCPara->SensorCnt = 0;
SCPara->InitOverFlag = false;
SCPara->ReadSensorInterval = 300;
GateWay = (GateWayPara)parameter;
InCommUnitMac[3] = GateWay->ConfigPara.GwMac[4];
InCommUnitMac[4] = GateWay->ConfigPara.GwMac[5];
RS485Ch = &GateWay->ConfigPara.Rs485Ch1;
memcpy(RS485Ch->CUData.Para.Mac, InCommUnitMac, 6);
if(RS485Ch->CommUnitEnable == true) {
RS485_CH1_POW_ON();
RS485Ch->CUData.Para.SensorN = 0;
memset(RS485Ch->CUData.Para.SensorType, 0x00, sizeof(SENSOR_NUM_MAX * 2));
RS485Ch->QuerySensorFlag = true;
RS485Ch->CUData.Para.CommStatus = true;
}
SCPara->RS485CommUnitReadTimeDelay = 100;
SCPara->RS485Rev_Sem = rt_sem_create("rsch1sem", 0, RT_IPC_FLAG_FIFO);
if(SCPara->RS485Rev_Sem == RT_NULL) {
Debug_Printf("RS485Ch1Rev Sem Create Failed!\r\n");
}
Debug_Printf("RS485Ch1Rev Thread is running\r\n");
rt_thread_delay(3000);
SCPara->InitOverFlag = true;
update_init(RS485Ch1UartSend);
while(1) {
RS485LoopHandler(GateWay, RS485Ch, SCPara);
//rt_thread_delay(10);
}
}
/*****************************************************************************************
* 函数名称: RS485Ch1RxIrqCallback
* 功能描述: RS485通道1中断处理回调函数
* 参 数: rData 接收到的数据
* 返 回 值: 无
*****************************************************************************************/
void RS485Ch1RxIrqCallback(uint8_t rData)
{
if(SComm1Para.RS485TimeOutCnt == 0) {
SComm1Para.RS485RxLen = 0;
}
if(SComm1Para.RS485RxLen < RS485_RX_BUFF_LEN_MAX)
SComm1Para.RS485RxBuff[SComm1Para.RS485RxLen++] = rData;
SComm1Para.RS485TimeOutCnt = 3;
}
/*****************************************************************************************
* 函数名称: RS485Ch2_Thread_Entry
* 功能描述: RS485通道1任务函数
* 参 数: 任务参数入口
* 返 回 值: 无
*****************************************************************************************/
void RS485Ch2_Thread_Entry(void *parameter)
{
uint8_t InCommUnitMac[6] = {0x01, 0x80, 0x02, 0x00, 0x00, 0x02};
GateWayPara GateWay;
SensorCommPara SCPara;
RS485Para RS485Ch;
SCPara = &SComm2Para;
SCPara->SensorCnt = 0;
SCPara->InitOverFlag = false;
SCPara->ReadSensorInterval = 0;
GateWay = (GateWayPara)parameter;
InCommUnitMac[3] = GateWay->ConfigPara.GwMac[4];
InCommUnitMac[4] = GateWay->ConfigPara.GwMac[5];
RS485Ch = &GateWay->ConfigPara.Rs485Ch2;
memcpy(RS485Ch->CUData.Para.Mac, InCommUnitMac, 6);
if(RS485Ch->CommUnitEnable == true) {
RS485_CH2_POW_ON();
RS485Ch->CUData.Para.SensorN = 0;
memset(RS485Ch->CUData.Para.SensorType, 0x00, sizeof(SENSOR_NUM_MAX * 2));
RS485Ch->QuerySensorFlag = true;
RS485Ch->CUData.Para.CommStatus = 1;
}
SCPara->RS485CommUnitReadTimeDelay = 100;
SCPara->RS485Rev_Sem = rt_sem_create("rsch2sem", 0, RT_IPC_FLAG_FIFO);
if(SCPara->RS485Rev_Sem == RT_NULL) {
Debug_Printf("RS485Ch2Rev Sem Create Failed!\r\n");
}
Debug_Printf("RS485Ch2Rev Thread is running\r\n");
rt_thread_delay(3000);
SCPara->InitOverFlag = true;
while(1) {
RS485LoopHandler(GateWay, RS485Ch, SCPara);
//rt_thread_delay(10);
}
}
/*****************************************************************************************
* 函数名称: RS485Ch2RxIrqCallback
* 功能描述: RS485通道1中断处理回调函数
* 参 数: rData 接收到的数据
* 返 回 值: 无
*****************************************************************************************/
void RS485Ch2RxIrqCallback(uint8_t rData)
{
if(SComm2Para.RS485TimeOutCnt == 0) {
SComm2Para.RS485RxLen = 0;
}
if(SComm2Para.RS485RxLen < RS485_RX_BUFF_LEN_MAX)
SComm2Para.RS485RxBuff[SComm2Para.RS485RxLen++] = rData;
SComm2Para.RS485TimeOutCnt = 3;
}
void RS485RxOverhandler(void)
{
if(SComm1Para.RS485TimeOutCnt > 0)
SComm1Para.RS485TimeOutCnt--;
if(SComm1Para.RS485RxLen > 5 && SComm1Para.RS485TimeOutCnt == 0) {
if(SComm1Para.InitOverFlag == true) {
rt_sem_release(SComm1Para.RS485Rev_Sem);
SComm1Para.RS485TimeOutCnt = 20;
}
else {
SComm1Para.RS485RxLen = 0;
SComm1Para.RS485TimeOutCnt = 0;
}
}
if(SComm2Para.RS485TimeOutCnt > 0)
SComm2Para.RS485TimeOutCnt--;
if(SComm2Para.RS485RxLen > 5 && SComm2Para.RS485TimeOutCnt == 0) {
if(SComm2Para.InitOverFlag == true) {
SComm2Para.RS485TimeOutCnt = 20;
rt_sem_release(SComm2Para.RS485Rev_Sem);
}
else {
SComm2Para.RS485RxLen = 0;
SComm2Para.RS485TimeOutCnt = 0;
}
}
}
#if 0
void RS485Ch2RxIrqCallback(uint8_t rData)
{
static bool FrameHeader = false;
static uint8_t rLen = 0;
if(FrameHeader == false) {
if(rData == 0x7a || rData == 0x7b) {
FrameHeader = true;
RS485Chr2RxLen = 0;
}
}
if(RS485Chr2RxLen < RS485_RX_BUFF_LEN_MAX) {
RS485Chr2RxBuff[RS485Chr2RxLen++] = rData;
}
else {
FrameHeader = false;
RS485Chr2RxLen = 0;
}
if(RS485Chr2RxLen == 6) {
rLen = rData + 8;
}
else if(RS485Chr2RxLen > 6) {
if(RS485Chr2RxLen >= rLen) {
rt_sem_release(RS485Ch2Rev_Sem);
FrameHeader = false;
}
}
}
#endif