📄 battery.cpp
字号:
/*****************************************************************************
* battery.cpp ------ 检测电池状态并以文本和曲线的方式显示出来
* 主要功能1:利用spcomm元件获取串口RS232的数据
* (包括;电量、电流、电压、电量剩余百分比)
* 实现函数:Comm1ReceiveData
*
* 功能2:对数据进行筛选和转换并以文本形式显示出来
* 实现函数: ReceiveFlagData(buffer); //获取充电状态
* ReceiveCapaData(buffer); //获取电量数据
* ReceiveChargeData(buffer); //获取电流数据
* ReceiveVoltData(buffer); //获取电压数据
* ReceivePercentData(buffer); //获取剩余电量百分比
*
* 功能3:利用TeeChart元件根据所得最终数据绘制曲线
******************************************************************************/
//---------------------------------------------------------------------------
#include <vcl.h>
#pragma hdrstop
#include "battery.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma link "SPComm"
#pragma link "TeeTools"
#pragma link "TeeEdit"
#pragma link "TeeChartGrid"
#pragma link "TeeNavigator"
#pragma link "TeeURL"
#pragma link "TeeBannerTool"
#pragma link "EVENTLISTLib_OCX"
#pragma resource "*.dfm"
TMainForm *MainForm;
//--------------------构造函数,初始化变量------------------------------------
__fastcall TMainForm::TMainForm(TComponent* Owner)
: TForm(Owner)
{
bFlashflag = false; //判断是否闪烁窗体
bLinkflag = false; //判断是否连接
BatFullFlag = false; //判断电池是否已满
RemCapacity= 0; //剩余电量值
Current=0; //电流
Voltage=0; //电压
Power=0; //功耗
iInterval=0; //数据显示超时时间 (s)
tStartTime=0; //连接后计时时间
}
//-----------------------创建表单,初始化控件-----------------------------------
void __fastcall TMainForm::FormCreate(TObject *Sender)
{
//清空曲线点
RamCapicitySeries->Clear();
VoltageSeries->Clear();
ChargeCurrentSeries->Clear();
}
//-----------------------关闭表单,释放资源------------------------------------
void __fastcall TMainForm::FormClose(TObject *Sender, TCloseAction &Action)
{
Comm1->StopComm();
//AnimateWindow(this->Handle,1500,AW_CENTER | AW_HIDE);
}
/*************************************************************************************\
************************[ 主要功能实现函数 ]**********************************
\*************************************************************************************/
//------------------------连接或断开串口------------------------------
void __fastcall TMainForm::BtnLinkClick(TObject *Sender)
{
if(!bLinkflag) //-----连接-----
{
BtnLink->Caption="断开";
tStartTime=Time();
iInterval=0;
//获取波特率和COM口
Comm1->BaudRate=RateComboBox->Text.ToInt();
Comm1->CommName=ComComboBox->Text;
Comm1->StartComm(); //打开串口
Memo1->Lines->Add("已经连接:Com="+ ComComboBox->Text +" Rate="+RateComboBox->Text);
}
else //-----断开-------
{
BtnLink->Caption="连接";
Edit1->Clear();
TextTool->Text="0:00:00";
ScrollTool->Text="";
Comm1->StopComm(); //关闭串口
Memo1->Lines->Add("已经断开");
}
//控件可用/不可用的转换
bLinkflag = !bLinkflag;
Timer1->Enabled = !(Timer1->Enabled);
BtnWrite->Enabled = !(BtnWrite->Enabled);
Edit1->Enabled = !(Edit1->Enabled);
ComComboBox->Enabled = !(ComComboBox->Enabled);
RateComboBox->Enabled = !(RateComboBox->Enabled);
MaskEdit1->Enabled = !(MaskEdit1->Enabled);
}
//-----------------------写入数据到串口--------------------------------
void __fastcall TMainForm::BtnWriteClick(TObject *Sender)
{
AnsiString str;
str = Edit1->Text;
if(str.IsEmpty())
return;
Memo1->Lines->Add("Write: "+str);
Comm1->WriteCommData( str.c_str(),str.Length());
}
//------------ spcomm 接收到数据后执行以下事件 ----------------------
void __fastcall TMainForm::Comm1ReceiveData(TObject *Sender, Pointer Buffer,
WORD BufferLength)
{
AnsiString buffer, bufferCap, bufferCurrent, bufferVolt, bufferPercent;
//-----保存数据
buffer = (char*)Buffer;
if(buffer.Pos("IICisReady"))
{
//-----------------------------------------------------------
// Power = Current * Voltage ; //功耗
//分别显示出: 当前时间--电量值---电流值---电压值---剩余电量百分比
// if(iInterval >= MaskEdit1->Text.ToInt())
// {
//将数据传递给各个函数,分别进行筛选和转换,并返回所需数据
ReceiveFlagData(buffer); //获取充电状态
bufferCap = ReceiveCapaData(buffer); //获取电量数据
bufferCurrent = ReceiveChargeData(buffer); //获取电流数据
bufferVolt = ReceiveVoltData(buffer); //获取电压数据
bufferPercent = ReceivePercentData(buffer); //获取剩余电量百分比
if(bufferCap=="error" || bufferCurrent=="error" || bufferVolt=="error" ||
bufferPercent=="error" ) //为空表示有错误
return;
Memo1->Lines->Add(TimeToStr(Time())+ bufferCap + bufferCurrent + bufferVolt +bufferPercent);
//绘制曲线点
RamCapicitySeries->Add(RemCapacity,TimeToStr(Time()) ,clRed);
VoltageSeries->Add(Voltage,TimeToStr(Time()) ,clRed);
ChargeCurrentSeries->Add(Current,TimeToStr(Time()) ,clRed);
iInterval=0;
// }
}
else
{
Memo1->Lines->Add(buffer);
}
}
//-----------------------获取充电状态并输出--------------------
//-------------------------------------------------------------
//字符串处理流程:查找->截取->排序->转换->错误判断(防止乱码)
//-------------------------------------------------------------
void _fastcall TMainForm::ReceiveFlagData(AnsiString buffer)
{
AnsiString myBuf(buffer),tempBuf,tempHexBuf;
int iPos=0;
int iTemp=0;
if( (iPos = myBuf.Pos("BQ272_FLAGS")) !=0 )
{
ScrollTool->Text="正在充电";
myBuf = myBuf.SubString(iPos,15);
//----------防止乱码---------------
if(myBuf.Length()<15)
return;
//重新给16进制字符串排序
tempBuf.sprintf("%c%c",myBuf[13],myBuf[14]);
//将16进制字符串转换为10进制整数
iTemp=(int)strtol(tempBuf.c_str(),NULL,16);
if(iTemp>=160 && iTemp<192)
{
Memo1->Lines->Add(TimeToStr(Time())+" 电池已满 "+tempBuf);
//BatFullFlag = true;
}
}
else if((myBuf.Pos("BQ27200_Discharge_Flags"))!=0)
{
ScrollTool->Text="正在放电";
}
else
return ;
}
//-----------------------获取电量---------------------------
AnsiString _fastcall TMainForm::ReceiveCapaData(AnsiString buffer)
{
AnsiString myBuf(buffer),tempBuf,tempHexBuf;
int iPos=0, iTemp=0;
if((iPos = myBuf.Pos("RemCapacity"))!=0)
myBuf = myBuf.SubString(iPos,18);
else
return "error";
//%%%%%%%%%%%%%%%%%%%%%防止乱码%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
if(myBuf.Length()<18)
return "error";
for(int i=13; i<=17; i++)
{
if(i==15)
continue;
if(!(( myBuf[i]>='0' && myBuf[i]<='9' ) || ( myBuf[i]>='A' && myBuf[i]<='F' )) )
return "error";
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
//重新给16进制字符串排序
tempBuf.sprintf("%c%c%c%c",myBuf[16],myBuf[17],myBuf[13],myBuf[14]);
tempHexBuf=tempBuf;
//将16进制字符串转换为10进制字符串
iTemp=(int)strtol(tempBuf.c_str(),NULL,16);
//RemCapacity = (double)iTemp*3.57/20;
RemCapacity=iTemp;
tempBuf.sprintf("%15d",iTemp);
//test for error
if(RemCapacity > 8500)
return "error";
// tempBuf+=tempHexBuf;
return tempBuf;
}
//-----------------------获取电流---------------------------
AnsiString _fastcall TMainForm::ReceiveChargeData(AnsiString buffer)
{
AnsiString myBuf(buffer),tempBuf,tempHexBuf;
int iPos=0;
int iTemp=0;
/*********************检测充电电流***********************/
if( (iPos=myBuf.Pos("ChargeCurrent")) !=0 )
{
myBuf = myBuf.SubString(iPos,19 );
//-%%%%%%%%%%%%%%%%%%%%%%%%防止乱码-%%%%%%%%%%%%%%%%%%%%%%%%%---
if(myBuf.Length()<19)
return "error";
for(int i=15; i<=19; i++)
{
if(i==17)
continue;
if(!(( myBuf[i]>='0' && myBuf[i]<='9' ) || ( myBuf[i]>='A' && myBuf[i]<='F' )))
return "error";
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
//重新给16进制字符串排序
tempBuf.sprintf("%c%c%c%c",myBuf[18],myBuf[19],myBuf[15],myBuf[16]);
tempHexBuf=tempBuf;
//将16进制字符串转换为10进制字符串
iTemp=(int)strtol(tempBuf.c_str(),NULL,16);
// tempBuf.sprintf("%15.2f",iTemp*3.57/20) ;
tempBuf.sprintf("%15d",iTemp);
Current = (double)iTemp;
//Current = (double)iTemp*3.57/20;
}
/***********检测放电电流*******************/
else if( (iPos = myBuf.Pos("DischargeCurrent")) !=0)
{
myBuf = myBuf.SubString(iPos,23);//ym
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%防止乱码%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
if(myBuf.Length()<23)
return "error";
for(int i=18; i<=22; i++)
{
if(i==20)
continue;
if(!(( myBuf[i]>='0' && myBuf[i]<='9' ) || ( myBuf[i]>='A' && myBuf[i]<='F' )))
return "error";
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
//重新给16进制字符串排序
tempBuf.sprintf("%c%c%c%c",myBuf[21],myBuf[22],myBuf[18],myBuf[19]);
tempHexBuf=tempBuf;
//将16进制字符串转换为10进制字符串
iTemp=(int)strtol(tempBuf.c_str(),NULL,16);
// tempBuf.sprintf("%15.2f",iTemp*3.57/20) ;
// Current = (double)iTemp*3.57/20;
tempBuf.sprintf("%15d",iTemp) ;
Current = (double)iTemp;
if(Current > 8500)
return "error";
}
return tempBuf;
}
//-----------------------获取电压-------------------------------------
AnsiString _fastcall TMainForm::ReceiveVoltData(AnsiString buffer)
{
AnsiString myBuf(buffer),tempBuf,tempHexBuf;
int iPos=0;
int iTemp=0;
if((iPos = myBuf.Pos("PreVOLT")) !=0)
myBuf = myBuf.SubString(iPos,14);
else
return "error";
//%%%%%%%%%%%%%%%%%%%%%%%%%防止乱码---%%%%%%%%%%%%%%%%%%%%%%%%%%%------
if(myBuf.Length()<14)
return "error";
for(int i=9; i<=13; i++)
{
if(i==11)
continue;
if(!(( myBuf[i]>='0' && myBuf[i]<='9' ) || ( myBuf[i]>='A' && myBuf[i]<='F' )))
return "error";
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
//重新给16进制字符串排序
tempBuf.sprintf("%c%c%c%c",myBuf[12],myBuf[13],myBuf[9],myBuf[10]);
tempHexBuf=tempBuf;
//将16进制字符串转换为10进制字符串
iTemp=(int)strtol(tempBuf.c_str(),NULL,16);
Voltage = iTemp;
tempBuf.sprintf("%15d",iTemp);
//test for error
// if(Voltage > 6000)
if(Voltage > 8500)
return "error";
//tempBuf+=tempHexBuf;
return tempBuf;
}
//-----------------------获取电量百分比---------------------------
AnsiString _fastcall TMainForm::ReceivePercentData(AnsiString buffer)
{
AnsiString myBuf(buffer),tempBuf,tempHexBuf;
int iPos=0;
int iTemp=0;
if((iPos = myBuf.Pos("RSOC")) != 0)
myBuf = myBuf.SubString(iPos,8);
else
return "error";
//---%%%%%%%%%%%%%%%%防止乱码-----%%%%%%%%%%%%%%%%%%----
if(myBuf.Length()<8)
return "error";
for(int i=6; i<=7; i++)
{
if(!(( myBuf[i]>='0' && myBuf[i]<='9' ) || ( myBuf[i]>='A' && myBuf[i]<='F' )))
return "error";
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
//重新给16进制字符串排序
tempBuf.sprintf("%c%c",myBuf[6],myBuf[7] );
tempHexBuf=tempBuf;
iTemp=(int)strtol(tempBuf.c_str(),NULL,16);
tempBuf.sprintf("%15d%%",iTemp);
//----------防止乱码---------
if(iTemp > 100 || iTemp <= 0)
return "error";
//tempBuf+=tempHexBuf;
return tempBuf;
}
/*---------------------------------------------------------------------------
-------------------------> 次要功能实现函数 <------------------------------
----------------------------------------------------------------------------*/
//--------------添加计时显示功能-----------------------
void __fastcall TMainForm::Timer1Timer(TObject *Sender)
{
TextTool->Text=TimeToStr(Time()-tStartTime);
iInterval++;
}
//--------------------曲线全屏显示------------------------------------
void __fastcall TMainForm::BtnFullScrClick(TObject *Sender)
{
FullScreenTool->Active = true;
}
//------------------将曲线打印------------------------------------
void __fastcall TMainForm::BtnPreViewClick(TObject *Sender)
{
ChartPreviewer1->Execute();
}
//----------------将曲线导出--------------------------------------
void __fastcall TMainForm::BtnExportClick(TObject *Sender)
{
ChartEditor1->Title="图表导出";
ChartEditor1->HighLightTabs=true;
ChartEditor1->DefaultTab=cetExport;
ChartEditor1->Execute();
}
void __fastcall TMainForm::BtnFlashClick(TObject *Sender)
{
if(!bFlashflag)
{
BtnFlash->Caption = "不闪* * !" ;
FLASHWINFO fwi;
fwi.cbSize = sizeof(fwi);
fwi.hwnd = Application->Handle;
fwi.dwFlags = FLASHW_TRAY | FLASHW_TIMER ;
// fwi.uCount = 5;
fwi.dwTimeout = 500;
FlashWindowEx(&fwi);
}
else
{
BtnFlash->Caption = "闪烁^ ^" ;
FLASHWINFO fwi;
fwi.cbSize = sizeof(fwi);
fwi.hwnd = Application->Handle;
fwi.dwFlags = FLASHW_STOP ;
//fwi.uCount = 5;
fwi.dwTimeout = 500;
FlashWindowEx(&fwi);
}
bFlashflag = !bFlashflag;
}
//---------------------------------------------------------------------------
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -