Chinaunix首页 | 论坛 | 博客
  • 博客访问: 2349903
  • 博文数量: 816
  • 博客积分: 10000
  • 博客等级: 上将
  • 技术积分: 5010
  • 用 户 组: 普通用户
  • 注册时间: 2008-12-17 17:57
文章分类

全部博文(816)

文章存档

2011年(1)

2008年(815)

分类:

2008-12-17 18:07:40

在我的程序中开了两个串口,

程序是一个实时任务调度软件,每十分钟开始一次巡测,将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) |
给主人留下些什么吧!~~