介绍
自从打算把援助刚果项目以文章的形式发表出来,但是由于功能模块较多,所以决定分块发表上来。但是由于工作紧张,所以在写了2遍文章之后就没有时间来续写下面的了。这个期间也有很多热心的读者给我很多宝贵的意见。我知道中间的很多文章对一些在VC领域有很多经验的人来说没有什么用,但是,我提倡的是技术共享的原则。可能一个你认为很简单的东西对一个初学者或者专注与这个方面的人来说是很有帮助的。如果每个人都能够将自己发表出来,那么,我们这对于我们大部分程序员来说将是一个很大的技术积累。
正文
前面2遍文章介绍了一个监控框架的实现和一种计量界面的模拟实现,这个文章我们讲一下基于MSCOMM控件的线程串口通讯的实现。串口通讯程序的编写方法一般有3中,第一种是基于MSCOMM控件的实现,第二种是用网络上面别人写的功能类实现Serial类,这个类功能比较强大,能够满足很多的通讯要求的。第三种就是自己写基于WIN32的API函数进行串口的程序。这种方法比较复杂。一般初学者喜欢用基于MSCOMM的控件方法实现串口通讯。
在我进行的这个项目中,串口通讯程序只设计到与一种硬件装置的通讯,那个就是公司自行研发和生产的保护装置,这种装置应用于电力保护控制系统中,能够自动采集各种模拟量、数字量节点信息,并实现自动报警和基本控制。我们利用MSCOMM控件通讯的目的就是将设备上传来的模拟量,数字量信息和各种报警信息解包然后在界面(上位机)程序进行显示给工作人员就可以了,然后我们通过界面的关联处理方法再将工作人员的各种控制信息传递给外围设备就可以了。
在一般的程序设计过程中,我们一般采用数据库作为数据交换的临时介质,尤其在多机多网程序中我们采用这种方法实现,但是这次由于当地条件限制,我们做的是相当于单机运行的程序,考虑到程序执行效率等方面因素,我没有采用SQL SERVER数据库,而是采用了ACCESS作为数据库。在进行数据量信息传递的时候,采用结构体传递参数的形式进行。这样程序运行的执行效率和实时性就跟上来了。
程序具体实现如下:
这次项目的外围设备由于通讯芯片采用的是自动送取报文而不是采用的应答方式,所以我们直接相应MSCOMM控件小心就可以对串口缓冲区进行数据的读工作了。
相关准备工作:
1、加入MSCOMM控件,然后定义对象并进行初始化
//创建通讯控件
m_Com.Create(NULL,WS_CHILD|WS_VISIBLE,CRect(0,0,10,10),this,ID_COMMCTRL);
m_Com.SetCommPort(1);
m_Com.SetInBufferSize(2000);
m_Com.SetOutBufferSize(2000);
if(!m_Com.GetPortOpen())
m_Com.SetPortOpen(TRUE);
m_Com.SetInputMode(1);
m_Com.SetSettings("9600,n,8,1");
m_Com.SetRThreshold(1);
m_Com.SetInputLen(0);
m_Com.SetInBufferCount(0);
2、定义结构体:
struct ItemMsg{
CString szName; //设备名称标示
float fRealVal; //实时记录数据
float fRealBuff[720]; //实时信息记录
float fHisVal[720]; //历史记录数据,用于曲线记录
BOOL bDigit; //是否为数字量节点
};
3、定义变量对象
ItemMsg *m_ItemMsg;
4、初始化结构体信息(这里可以根据需要采用数据库组态的形式实现,将这些信息配置到数据库中,然后在程序初始化的时候读取相关信息然后进行自动配置就可以了)
void CYbkDemoView::InitbufferVal()
{
this->m_ItemMsg = new ItemMsg[308];
for(int i=0;i<308;i++)
{
m_ItemMsg[i].fRealVal = 0;
m_ItemMsg[i].bDigit = FALSE;//初始化为模拟量接点
for(int j=0;j<720;j++)
{
m_ItemMsg[i].fRealBuff[j] = 0.00f;
m_ItemMsg[i].fHisVal[j] = 0.00f;
}
}
m_ItemMsg[0].szName = "G3440";
m_ItemMsg[0].bDigit = TRUE;
m_ItemMsg[1].szName = "G3443";
m_ItemMsg[1].bDigit = TRUE;
m_ItemMsg[2].szName = "G3445";
m_ItemMsg[2].bDigit = TRUE;
m_ItemMsg[3].szName = "G3441";
m_ItemMsg[3].bDigit = TRUE;
m_ItemMsg[4].szName = "D344";
m_ItemMsg[4].bDigit = TRUE;
m_ItemMsg[5].szName = "城关线Ia";
m_ItemMsg[6].szName = "城关线Ib";
m_ItemMsg[7].szName = "城关线Ic";
m_ItemMsg[8].szName = "城关线P";
m_ItemMsg[9].szName = "城关线Q";
m_ItemMsg[10].szName = "城关线COS";
m_ItemMsg[11].szName = "城关线BIa";
m_ItemMsg[12].szName = "城关线BIb";
m_ItemMsg[13].szName = "城关线BIc";
m_ItemMsg[14].szName = "G3430";
m_ItemMsg[14].bDigit = TRUE;
m_ItemMsg[15].szName = "G3433";
m_ItemMsg[15].bDigit = TRUE;
m_ItemMsg[16].szName = "G3435";
m_ItemMsg[16].bDigit = TRUE;
m_ItemMsg[17].szName = "G3431";
m_ItemMsg[17].bDigit = TRUE;
m_ItemMsg[18].szName = "D343";
m_ItemMsg[18].bDigit = TRUE;
m_ItemMsg[19].szName = "备用1线Ia";
m_ItemMsg[20].szName = "备用1线Ib";
m_ItemMsg[21].szName = "备用1线Ic";
m_ItemMsg[22].szName = "备用1线P";
m_ItemMsg[23].szName = "备用1线Q";
m_ItemMsg[24].szName = "备用1线COS";
m_ItemMsg[25].szName = "备用1线BIa";
m_ItemMsg[26].szName = "备用1线BIb";
m_ItemMsg[27].szName = "备用1线BIc";
m_ItemMsg[28].szName = "G3420";
m_ItemMsg[28].bDigit = TRUE;
m_ItemMsg[29].szName = "G3423";
m_ItemMsg[29].bDigit = TRUE;
m_ItemMsg[30].szName = "G3425";
m_ItemMsg[30].bDigit = TRUE;
m_ItemMsg[31].szName = "G3421";
m_ItemMsg[31].bDigit = TRUE;
m_ItemMsg[32].szName = "D342";
m_ItemMsg[32].bDigit = TRUE;
m_ItemMsg[33].szName = "东门线Ia";
m_ItemMsg[34].szName = "东门线Ib";
m_ItemMsg[35].szName = "东门线Ic";
m_ItemMsg[36].szName = "东门线P";
m_ItemMsg[37].szName = "东门线Q";
m_ItemMsg[38].szName = "东门线COS";
m_ItemMsg[39].szName = "东门线BIa";
m_ItemMsg[40].szName = "东门线BIb";
m_ItemMsg[41].szName = "东门线BIc";
m_ItemMsg[42].szName = "G3410";
m_ItemMsg[42].bDigit = TRUE;
m_ItemMsg[43].szName = "G3413";
m_ItemMsg[43].bDigit = TRUE;
m_ItemMsg[44].szName = "G3415";
m_ItemMsg[44].bDigit = TRUE;
m_ItemMsg[45].szName = "G3411";
m_ItemMsg[45].bDigit = TRUE;
m_ItemMsg[46].szName = "D341";
m_ItemMsg[46].bDigit = TRUE;
m_ItemMsg[47].szName = "马峰线Ia";
m_ItemMsg[48].szName = "马峰线Ib";
m_ItemMsg[49].szName = "马峰线Ic";
m_ItemMsg[50].szName = "马峰线P";
m_ItemMsg[51].szName = "马峰线Q";
m_ItemMsg[52].szName = "马峰线COS";
m_ItemMsg[53].szName = "马峰线BIa";
m_ItemMsg[54].szName = "马峰线BIb";
m_ItemMsg[55].szName = "马峰线BIc";
m_ItemMsg[56].szName = "G3400";
m_ItemMsg[56].bDigit = TRUE;
m_ItemMsg[57].szName = "G3403";
m_ItemMsg[57].bDigit = TRUE;
m_ItemMsg[58].szName = "G3405";
m_ItemMsg[58].bDigit = TRUE;
m_ItemMsg[59].szName = "G3401";
m_ItemMsg[59].bDigit = TRUE;
m_ItemMsg[60].szName = "D340";
m_ItemMsg[60].bDigit = TRUE;
m_ItemMsg[61].szName = "黄家线Ia";
m_ItemMsg[62].szName = "黄家线Ib";
m_ItemMsg[63].szName = "黄家线Ic";
m_ItemMsg[64].szName = "黄家线P";
m_ItemMsg[65].szName = "黄家线Q";
m_ItemMsg[66].szName = "黄家线COS";
m_ItemMsg[67].szName = "黄家线BIa";
m_ItemMsg[68].szName = "黄家线BIb";
m_ItemMsg[69].szName = "黄家线BIc";
//35KVPT1
m_ItemMsg[70].szName = "G3451";
m_ItemMsg[70].bDigit = TRUE;
//1#主变
m_ItemMsg[71].szName = "G3471";
m_ItemMsg[71].bDigit = TRUE;
m_ItemMsg[72].szName = "D347";
m_ItemMsg[72].bDigit = TRUE;
m_ItemMsg[73].szName = "D940";
m_ItemMsg[73].bDigit = TRUE;
m_ItemMsg[74].szName = "1#主变HIa";
m_ItemMsg[75].szName = "1#主变HIb";
m_ItemMsg[76].szName = "1#主变HIc";
m_ItemMsg[77].szName = "1#主变LIa";
m_ItemMsg[78].szName = "1#主变LIb";
m_ItemMsg[79].szName = "1#主变LIc";
//35KV母联
m_ItemMsg[80].szName = "G3491";
m_ItemMsg[80].bDigit = TRUE;
m_ItemMsg[82].szName = "D349";
m_ItemMsg[82].bDigit = TRUE;
m_ItemMsg[83].szName = "G3493";
m_ItemMsg[83].bDigit = TRUE;
//2#主变
m_ItemMsg[84].szName = "G3481";
m_ItemMsg[84].bDigit = TRUE;
m_ItemMsg[85].szName = "D348";
m_ItemMsg[85].bDigit = TRUE;
m_ItemMsg[86].szName = "D941";
m_ItemMsg[86].bDigit = TRUE;
m_ItemMsg[87].szName = "2#主变HIa";
m_ItemMsg[88].szName = "2#主变HIb";
m_ItemMsg[89].szName = "2#主变HIc";
m_ItemMsg[90].szName = "2#主变LIa";
m_ItemMsg[91].szName = "2#主变LIb";
m_ItemMsg[92].szName = "2#主变LIc";
m_ItemMsg[93].szName = "频率";
//35KVPT2
m_ItemMsg[94].szName = "G3461";
m_ItemMsg[94].bDigit = TRUE;
m_ItemMsg[95].szName = "D951";
m_ItemMsg[95].bDigit = TRUE;
m_ItemMsg[96].szName = "备用2线Ia";
m_ItemMsg[97].szName = "备用2线Ib";
m_ItemMsg[98].szName = "备用2线Ic";
m_ItemMsg[99].szName = "备用2线P";
m_ItemMsg[100].szName = "备用2线Q";
m_ItemMsg[101].szName = "备用2线COS";
m_ItemMsg[102].szName = "备用2线BIa";
m_ItemMsg[103].szName = "备用2线BIb";
m_ItemMsg[104].szName = "备用2线BIc";
m_ItemMsg[105].szName = "D950";
m_ItemMsg[105].bDigit = TRUE;
m_ItemMsg[106].szName = "西城开关站线Ia";
m_ItemMsg[107].szName = "西城开关站线Ib";
m_ItemMsg[108].szName = "西城开关站线Ic";
m_ItemMsg[109].szName = "西城开关站线P";
m_ItemMsg[110].szName = "西城开关站线Q";
m_ItemMsg[111].szName = "西城开关站线COS";
m_ItemMsg[112].szName = "西城开关站线BIa";
m_ItemMsg[113].szName = "西城开关站线BIb";
m_ItemMsg[114].szName = "西城开关站线BIc";
m_ItemMsg[115].szName = "D949";
m_ItemMsg[115].bDigit = TRUE;
m_ItemMsg[116].szName = "复烤厂III线Ia";
m_ItemMsg[117].szName = "复烤厂III线Ib";
m_ItemMsg[118].szName = "复烤厂III线Ic";
m_ItemMsg[119].szName = "复烤厂III线P";
m_ItemMsg[120].szName = "复烤厂III线Q";
m_ItemMsg[121].szName = "复烤厂III线COS";
m_ItemMsg[122].szName = "复烤厂III线BIa";
m_ItemMsg[123].szName = "复烤厂III线BIb";
m_ItemMsg[124].szName = "复烤厂III线BIc";
m_ItemMsg[125].szName = "D948";
m_ItemMsg[125].bDigit = TRUE;
m_ItemMsg[126].szName = "岩西线Ia";
m_ItemMsg[127].szName = "岩西线Ib";
m_ItemMsg[128].szName = "岩西线Ic";
m_ItemMsg[129].szName = "岩西线P";
m_ItemMsg[130].szName = "岩西线Q";
m_ItemMsg[131].szName = "岩西线COS";
m_ItemMsg[132].szName = "岩西线BIa";
m_ItemMsg[133].szName = "岩西线BIb";
m_ItemMsg[134].szName = "岩西线BIc";
m_ItemMsg[135].szName = "D947";
m_ItemMsg[135].bDigit = TRUE;
m_ItemMsg[136].szName = "白云民用线Ia";
m_ItemMsg[137].szName = "白云民用线Ib";
m_ItemMsg[138].szName = "白云民用线Ic";
m_ItemMsg[139].szName = "白云民用线P";
m_ItemMsg[140].szName = "白云民用线Q";
m_ItemMsg[141].szName = "白云民用线COS";
m_ItemMsg[142].szName = "白云民用线BIa";
m_ItemMsg[143].szName = "白云民用线BIb";
m_ItemMsg[144].szName = "白云民用线BIc";
m_ItemMsg[145].szName = "D943";
m_ItemMsg[145].bDigit = TRUE;
m_ItemMsg[146].szName = "电容补偿柜线Ia";
m_ItemMsg[147].szName = "电容补偿柜线Ib";
m_ItemMsg[148].szName = "电容补偿柜线Ic";
m_ItemMsg[149].szName = "电容补偿柜线P";
m_ItemMsg[150].szName = "电容补偿柜线Q";
m_ItemMsg[151].szName = "电容补偿柜线COS";
m_ItemMsg[152].szName = "电容补偿柜线BIa";
m_ItemMsg[153].szName = "电容补偿柜线BIb";
m_ItemMsg[154].szName = "电容补偿柜线BIc";
m_ItemMsg[155].szName = "D946";
m_ItemMsg[155].bDigit = TRUE;
m_ItemMsg[156].szName = "备用3线Ia";
m_ItemMsg[157].szName = "备用3线Ib";
m_ItemMsg[158].szName = "备用3线Ic";
m_ItemMsg[159].szName = "备用3线P";
m_ItemMsg[160].szName = "备用3线Q";
m_ItemMsg[161].szName = "备用3线COS";
m_ItemMsg[162].szName = "备用3线BIa";
m_ItemMsg[163].szName = "备用3线BIb";
m_ItemMsg[164].szName = "备用3线BIc";
m_ItemMsg[165].szName = "D945";
m_ItemMsg[165].bDigit = TRUE;
m_ItemMsg[166].szName = "备用4线Ia";
m_ItemMsg[167].szName = "备用4线Ib";
m_ItemMsg[168].szName = "备用4线Ic";
m_ItemMsg[169].szName = "备用4线P";
m_ItemMsg[170].szName = "备用4线Q";
m_ItemMsg[171].szName = "备用4线COS";
m_ItemMsg[172].szName = "备用4线BIa";
m_ItemMsg[173].szName = "备用4线BIb";
m_ItemMsg[174].szName = "备用4线BIc";
m_ItemMsg[175].szName = "D944";
m_ItemMsg[175].bDigit = TRUE;
m_ItemMsg[176].szName = "备用5线Ia";
m_ItemMsg[177].szName = "备用5线Ib";
m_ItemMsg[178].szName = "备用5线Ic";
m_ItemMsg[179].szName = "备用5线P";
m_ItemMsg[180].szName = "备用5线Q";
m_ItemMsg[181].szName = "备用5线COS";
m_ItemMsg[182].szName = "备用5线BIa";
m_ItemMsg[183].szName = "备用5线BIb";
m_ItemMsg[184].szName = "备用5线BIc";
m_ItemMsg[185].szName = "35KV母线Ua";
m_ItemMsg[186].szName = "35KV母线Ub";
m_ItemMsg[187].szName = "35KV母线Uc";
m_ItemMsg[188].szName = "35KV母线Uab";
m_ItemMsg[189].szName = "10KV母线Ua";
m_ItemMsg[190].szName = "10KV母线Ub";
m_ItemMsg[191].szName = "10KV母线Uc";
m_ItemMsg[192].szName = "10KV母线Uab";