在我的程序中开了两个串口,
程序是一个实时任务调度软件,每十分钟开始一次巡测,将21个终端的运行数据(电压、电流、水位、压力等)采集传回;插入到数据库中,21个终端中有16个无线终端、5个有线终端(无线通过数串电台2400b/s、有线RS232 4800b/s)
系统运行几天后(大概3-4天)会出现串口突然收不到数据(OnPackage事件不会被唤起,从新进入一下程序便可解决问题)的怪问题(好像是在我的软件弹出一个“内存在某个地址发生引用错误”的警告信息后才出现),有线和无线串口都出现过(但没同时出现,并且故障发生是另一个串口完全正常!两个川口前端数据处理共用同一个代码段,只是在发送数据时才根据发送数据中的终端IP地址自动切换串口)
编译和运行环境
Win 2000 + CB6.0 + Access
My E_mail : pineyer@yahoo.com.cn
如果需要我可以把源码发给你!
--------------------next---------------------
void __fastcall TdmeDBandWC::InitializeTheWirelessCommunication()
//
// 远端设备无线低速串口Com1通讯初始化设置
//
{
ybcdWirelessCommunication->~TYbCommDevice();
ybcdWirelessCommunication = new TYbCommDevice(this);
try
{
// 使用串口COM2
ybcdWirelessCommunication->PortNo = 1;
ybcdWirelessCommunication->Baud = TYbCommDevice::br2400; //设置波特率为 2400bps
ybcdWirelessCommunication->OnPackage = ybcdWirelessCommunicationPackage;
ybcdWirelessCommunication->Active = true;
}
catch(Exception &e)
{
ShowMessage("无线低速串口: "+e.Message);
if (!ybcdWirelessCommunication->SettingsDialog(this,true))
{
Application->Terminate();
}
}
ybcdWirelessCommunication->PackageSize = 32; //最大可发送 32 个字节的数据包
ybcdWirelessCommunication->QueueSize = 32;
ybcdWirelessCommunication->PackageType = cptFrameTimeout; //用判断超时的方法接收数据包
ybcdWirelessCommunication->UsePackage = true; //启动数据包 (可以随时启动和停止, 与 Active 属性无关)
}
//----------------------------------------------------------------------------
void __fastcall TdmeDBandWC::InitializeHighSpeedDataTransmitDevice(void)
//
// 近端设备有线高速串口Com2通讯初始化设置
//
{
ybcdHSDTransmit->~TYbCommDevice();
ybcdHSDTransmit = new TYbCommDevice(this);
try
{
// 使用串口COM2
ybcdHSDTransmit->PortNo = 2;
ybcdHSDTransmit->Baud = TYbCommDevice::br9600; //设置波特率为 9600bps
ybcdHSDTransmit->OnPackage = ybcdHSDTransmitPackage;
ybcdHSDTransmit->Active = true;
}
catch(Exception &e)
{
ShowMessage("有线高速串口: "+e.Message);
if (!ybcdHSDTransmit->SettingsDialog(this,true))
{
Application->Terminate();
}
}
ybcdHSDTransmit->PackageSize = 32; //最大可发送 32 个字节的数据包
// QueueSize取默认值16
ybcdHSDTransmit->PackageType = cptFrameTimeout; //用判断超时的方法接收数据包
ybcdHSDTransmit->UsePackage = true; //启动数据包 (可以随时启动和停止, 与 Active 属性无关)
}
//---------------------------------------------------------------------------
--------------------next---------------------
void __fastcall TdmeDBandWC::ybcdWirelessCommunicationPackage(TObject *Sender,
int NotifyType)
//
// 此函数用来处理所接受的数据
//
{
char Buf[32]; // 接收缓存区容量设置为32个字节
ybcdWirelessCommunication->ReadPackage(Buf,32);
AnsiString sRecivedData(Buf);
int n = sRecivedData.Pos(TEND); // 找出结束符的位置即收到的有效数据的字节数
if (n >= MinLength) // 收到数据的字节数应大于7, 最短的数据包是终端发来的应答,共8个字节
{
Byte Check = 0;
for (int i = 1; i < n-3; i++) // 校验和不包括通讯起始符
{
Check ^= Buf[i];
}
if (sRecivedData.SubString(n-2,2) == IntToHex(Check, 2)) //验证接受的数据的正确性
{
AnsiString PumpIP = sRecivedData.SubString(2,2);
AnsiString PumpName = GetWellName(PumpIP);
// 数据接收正确
switch (Buf[3])
{
case TRD1 : SetAck(PumpName); // 对应终端应答标识设为已收到正确应答
ProcessRunTimeParameters(&Buf[1]);
break;
/*
case TKW : SetAck(PumpName);
UpdateKW_Count(&Buf[1]);
break;
*/
case TCALL :
SendAck_Wireless(PumpIP); // 发送应答
/*
new TMyMessageBox(PumpName + " 终端请求进行音频对话!\n\r 请响应!!!",
"音频对话请求...", false);
*/
ErrorInfoBox("音频对话请求...", PumpName + " 终端请求进行音频对话!\n\r 请响应!!!", WinXP);
break;
case TACK :
// 刷新水泵状态
if (OperatePumpArray[WellNameList->IndexOf(PumpName)] == TPOn)
{
new TRefreshPumpStatue(false, PumpIP + RRD1, PumpName);//PreparedForSendData(PumpIP + RRD1); // 获取终端运行参数
}
if (OperatePumpArray[WellNameList->IndexOf(PumpName)] == TPOff)
{
new TRefreshPumpStatue(false, PumpIP + RRD1, PumpName);//PreparedForSendData(PumpIP + RRD1); // 获取终端运行参数
}
SetAck(PumpName); // 对应终端应答标识设为已收到正确应答
break;
case TALET :
SendAck_Wireless(sRecivedData.SubString(2, 2)); // 发送接收到正确报警信息应答
//ProcessErrorInfo(&Buf[1]);break;
default : return;
}
frmWaterSupply->RefreshDebugInfo(sRecivedData.SubString(1,n)); //刷新调试信息
}
else
{
// 数据接收不正确
if (Buf[3] == TALET)
{
SendAck_Wireless(sRecivedData.SubString(2, 2), false); // 发送接收到错误报警信息应答
}
frmWaterSupply->RefreshDebugInfo(sRecivedData.SubString(1,n), false); //刷新调试信息
}
}
}
//---------------------------------------------------------------------------
void __fastcall TdmeDBandWC::ybcdHSDTransmitPackage(TObject *Sender,
int NotifyType)
{
char Buf[32]; // 接收缓存区容量设置为32个字节
ybcdHSDTransmit->ReadPackage(Buf,32);
AnsiString sRecivedData(Buf);
int n = sRecivedData.Pos(TEND); // 找出结束符的位置即收到的有效数据的字节数
if (n >= MinLength) // 收到数据的字节数应大于6, 最短的数据包是终端发来的应答,共7个字节
{
Byte Check = 0;
for (int i = 1; i < n-3; i++) // 校验和不包括通讯起始符
{
Check ^= Buf[i];
}
if (sRecivedData.SubString(n-2,2) == IntToHex(Check, 2)) //验证接受的数据的正确性
{
AnsiString PumpIP = sRecivedData.SubString(2,2);
AnsiString PumpName = GetWellName(PumpIP);
....
--------------------next---------------------
// 每天午夜(0:0:0)左右整理一次数据库;使主参数表只保留用户设定日期以内的数据
if ((dtCurrentTime.FormatString("h") == "0") && (minute < ((ViewInterval * WellNameList->Count) / 60 + 1))) // 发生在0:时的第一次巡测完成时
{ // 从而保证压缩数据库的行为只发生一次
AnsiString ConditionStr = FloatToStr((double)dtCurrentTime - Days_rtpKeep);
// 删除遗留过久的数据
ADOcmdUpdateDatabase->CommandText = "delete from RunTimeParameters where CollectTime < "
+ ConditionStr + ";";
ADOcmdUpdateDatabase->Execute();
ADOcmdUpdateDatabase->CommandText = "delete from ErrorHistory where OccuredTime < "
+ ConditionStr + ";";
ADOcmdUpdateDatabase->Execute();
ADOcnnWellInfoDabase->Connected = false;// 断开数据库
CompactDatabase(ExtractFilePath(Application->ExeName) + "WarterSupplySystem.mdb");// 压缩数据库
ADOcnnWellInfoDabase->Connected = true;// 重连数据库
if (!ADOdstTempData->Active)ADOdstTempData->Active = true;
if (!ADOdstWellName->Active)ADOdstWellName->Active = true;
// 重新初始化串口
InitializeTheWirelessCommunication();//无线低速串口
InitializeHighSpeedDataTransmitDevice();//有线高速串口
}
--------------------next---------------------
我的线程同步方法
h File
//---------------------------------------------------------------------------
#ifndef SendCommandThreadH
#define SendCommandThreadH
//---------------------------------------------------------------------------
#include
//---------------------------------------------------------------------------
class TSendCommandThread : public TThread
{
private:
HANDLE m_hAckEvent;
AnsiString sCommand;
AnsiString DestWellName;
protected:
void __fastcall Execute();
void __fastcall SendCommand();
void __fastcall DisableScoutView();
public:
__fastcall TSendCommandThread(AnsiString WellName, AnsiString Str_Command, HANDLE hAckEvent, bool CreateSuspended = false, bool AutoFree = true);
};
//---------------------------------------------------------------------------
#endif
cpp File
//---------------------------------------------------------------------------
#include
#pragma hdrstop
#include "SendCommandThread.h"
#include "DatabaseAndWirelessCommunication.h"
#include "ReadHintThread.h"
#pragma package(smart_init)
extern bool WarningInfoHaveAudioHintFunction;
//---------------------------------------------------------------------------
__fastcall TSendCommandThread::TSendCommandThread(AnsiString WellName, AnsiString Str_Command, HANDLE hAckEvent, bool CreateSuspended, bool AutoFree)
: DestWellName(WellName),sCommand(Str_Command),TThread(CreateSuspended)
{
Priority = tpLower;
m_hAckEvent = hAckEvent;
FreeOnTerminate = AutoFree;
}
//---------------------------------------------------------------------------
inline void __fastcall TSendCommandThread::SendCommand()
{
/*
YbCommDevice->EscapeCommFunction(CLRDTR); //DTR清零
YbCommDevice->EscapeCommFunction(SETDTR); //DTR置位
YbCommDevice->EscapeCommFunction(CLRRTS); //RTS清零
YbCommDevice->EscapeCommFunction(SETRTS); //RTS置位
*/
dmeDBandWC->ybcdWirelessCommunication->Write(sCommand.c_str(),sCommand.Length()); //发送数据
}
//---------------------------------------------------------------------------
inline void __fastcall TSendCommandThread::DisableScoutView(){dmeDBandWC->DisableScoutView(DestWellName);}
//---------------------------------------------------------------------------
void __fastcall TSendCommandThread::Execute()
{
//---- Place thread code here ----
// 计算校验和
Byte Check = 0;
for (int i = 0; i < sCommand.Length(); i++)
{
Check ^= sCommand[i + 1];
}
sCommand = BEGIN + sCommand
+ IntToHex(Check, 2) + END; // 加上起始符、校验和和结束符
int TryNumbers = ReTryNembers;
do //如果终端无回应,连续发送三次
{
Synchronize(SendCommand);
}
while((WaitForSingleObject(m_hAckEvent, iOverTime) != WAIT_OBJECT_0) && (--TryNumbers));
if (!TryNumbers)
{
if (WarningInfoHaveAudioHintFunction)
{
TStringList *AudioHintList = new TStringList;
AudioHintList->Add(DestWellName);
AudioHintList->Add("终端通讯系统存在故障");
new TReadHintThread(AudioHintList, false);
delete AudioHintList;
}
/*
if (MessageBox(NULL, (" 控制中心与" + DestWellName + "终端\n\n通讯系统存在故障!\n\n 将该终端从自动巡测列表中删除?").c_str(), "通讯失败",
MB_YESNO|MB_ICONERROR) == IDYES) */
{
Synchronize(DisableScoutView);
}
}
}
//---------------------------------------------------------------------------
--------------------next---------------------
阅读(1088) | 评论(0) | 转发(0) |