⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mpgb.cpp

📁 vc 485串口通讯测试程序 vc-commtest
💻 CPP
字号:
//#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include "StdAfx.h"
#include "MPGB.h"
int CMPGB::FormReadDataFrame(BYTE *buff, int item , BYTE * addr){
	int m_Item = CheckItem( item );//判断抄表项是否有效?无效返回0
	if(m_Item == 0)//
	    return 0;
	
	BYTE DI0 = m_Item & 0xFF;
	BYTE DI1 = (m_Item >> 8) & 0xFF ;
	buff[0] = 0xfe;
	buff[1] = 0x68;
	for(int i = 0;i < 6;i++)
	     buff[2 + i] = addr[ i ];
	buff[8] = 0x68;
	buff[9] = 0x01;//控制码
	buff[10] = 0x02;	//数据长度
	buff[11] = DI0 + 0x33;
	buff[12] = DI1 + 0x33;
	buff[13] = GetCheckSum(buff+1, 12);
	buff[14] = 0x16;
	buff[15] = 0x00;
	return 16;//数据帧长度
}

int CMPGB::FormCheckClock(BYTE *buff,time_t *m_time,BYTE *addr)//设置电表时钟
{
	tm *pTime;
	
	if(m_time == NULL)
	{
		time_t t;
		time( &t );
		pTime = localtime(&t);
	}
	else
	{		
		pTime = localtime(m_time);
	}
	buff[0] = 0xfe;
	buff[1] = 0x68;
	for(int i = 2;i < 8; i++)
	    buff[ i ] = 0x99;//广播命令地址
	buff[8] = 0x68;
	buff[9] = 0x08;//控制码	
	buff[10] = 0x06;	//数据长度
	
	buff[11] = TranHexToBcd( pTime ->tm_sec ) + 0x33;//0~59
	buff[12] = TranHexToBcd( pTime ->tm_min ) + 0x33;//0~59
	buff[13] = TranHexToBcd( pTime ->tm_hour) + 0x33;//0~23
	buff[14] = TranHexToBcd( pTime ->tm_mday) + 0x33;//1~31
	buff[15] = TranHexToBcd( pTime ->tm_mon + 1) + 0x33;//0~11 + 1
	buff[16] = TranHexToBcd( pTime ->tm_year - 100) + 0x33;//since 1900 year - 100 = since 2003
	buff[17] = GetCheckSum(&buff[ 1 ], 16);
	buff[18] = 0x16;
	buff[19] = 0x00;
	return 20;//// LEN数据帧长度
}

int CMPGB::FormSetAddress(BYTE *buff, BYTE *addr)//设置电表地址
{
	buff[0] = 0xfe;
	buff[1] = 0x68;
	for(int i = 2;i < 8; i++)
	    buff[ i ] = 0x99;//广播命令地址
	buff[8] = 0x68;
	buff[9] = 0x0A;//控制码	
	buff[10] = 0x06;	//数据长度
	
	buff[11] = addr[ 0 ] + 0x33;//0~59
	buff[12] = addr[ 1 ] + 0x33;//0~59
	buff[13] = addr[ 2 ] + 0x33;//0~23
	buff[14] = addr[ 3 ] + 0x33;//1~31
	buff[15] = addr[ 4 ] + 0x33;//0~11 + 1
	buff[16] = addr[ 5 ] + 0x33;//since 1900 year - 100 = since 2003
	buff[17] = GetCheckSum(buff + 1, 16);
	buff[18] = 0x16;
	buff[19] = 0x00;
	return 20;
}
int CMPGB::ProcReturnedFrame(BYTE *inbuff, int inLen,int item, BYTE *outbuff,int &outlen,BYTE *addr){
	int i =0;
	while( i < (inLen - 12))////2*0x68 + 6 * adr + 1 * 0x16 + 1 * crc + 1*Len + 1* control
	{
		if(inbuff[i] == 0x68 && inbuff[i + 7] == 0x68)//找到数据帧头部
		{
		    break;
		}
		i++;
	}
	if(i >= (inLen - 14))//在有效数据长度内没有找到同步字
	{
		return 0x0100;//数据长度不正确
	}
	
	BYTE *pData = &inbuff[i];//数据起始
	BYTE Len  = pData[9] + 10 + 2;//2*0x68 + 6 * adr + 1 * 0x16 + 1 * crc + 1*Len + 1* control
	if(Len > inLen - i)
	{
		return 0x0100;
	}
	if(pData[Len - 1] != 0x16)
	{
		return 0x0200;//没有结束标志
	}
	BYTE m_check = GetCheckSum(pData,Len - 2);
	if(m_check != pData[Len - 2])
	{
		return 0x0300; //校验和不对
	}
	return ProcFullFrame(pData, item,outbuff, outlen, addr);//处理完整的数据返回
}


int  CMPGB::CheckItem(int Item_data)
{
	int data = Item_data & 0xFFFF;
	char LoBYTE = Item_data & 0xFF;
	char HiBYTE = ( Item_data & 0xFF00 ) >> 8;
	char LoBCD  = LoBYTE & 0x0F;
	char HiBCD  = (LoBYTE & 0xF0) >> 4;
	switch(HiBYTE & 0xFF)
	{
		case 0x90://当前正向有功、反向有功总
		case 0x94://上月正向有功、反向有功总
		case 0x98://上上月正向有功、反向有功总
		case 0xA0://当前正向有功、反向有功总最大需量
		case 0xA4://上月正向有功、反向有功总最大需量
		case 0xA8://上上月正向有功、反向有功总最大需量
		case 0xB0://当前正向有功、反向有功总最大需量发生的时间
		case 0xB4://上月正向有功、反向有功总最大需量发生的时间
		case 0xB8://上上月正向有功、反向有功总最大需量发生的时间
		     if( LoBYTE >= 0x10 &&  LoBYTE <= 0x2F )
		         return data;
		     break;
		case 0x91://当前正向无功、反向无功,及 一、二、三、四象限无功总
		case 0x95://上月正向无功、反向无功,及 一、二、三、四象限无功总
		case 0x99://上上月正向无功、反向无功,及 一、二、三、四象限无功总
		case 0xA1://当前正向无功、反向无功,及 一、二、三、四象限无功总最大需量
		case 0xA5://上月正向无功、反向无功,及 一、二、三、四象限无功总最大需量
		case 0xA9://上上月正向无功、反向无功,及 一、二、三、四象限无功总最大需量
		case 0xB1://当前正向无功、反向无功,及 一、二、三、四象限无功总最大需量发生的时间
		case 0xB5://上月正向无功、反向无功,及 一、二、三、四象限无功总最大需量发生的时间
		case 0xB9://上上月正向无功、反向无功,及 一、二、三、四象限无功总最大需量发生的时间
		     if( LoBYTE >= 0x10 &&  LoBYTE <= 0x6F)
		         return data;
		     break;
		case 0xB2://最近一次编程时间,最近一次最大需量清零时间,编程次数,最大需量清零次数,电池工作时间
		     if(( LoBYTE >= 0x10 &&  LoBYTE <= 0x14) || LoBYTE == 0x1F)
		         return data;
		     break;
	        case 0xB3://A、B、C 断相记录
	             if( ( HiBCD >= 0x01 && HiBCD <= 0x04 ) && ( (LoBCD >= 0x00 && LoBCD <= 0x03) ||(LoBCD == 0x0F)))
	                 return data;//
	             break;
	        case 0xB6://瞬时量
	             if( (HiBCD == 1 || HiBCD == 2 ) && ((LoBCD >= 1 && LoBCD <= 3) || LoBCD == 0x0F ))//电压、电流
	                 return data;
	             if( (HiBCD == 3 ) && ((LoBCD >= 0 && LoBCD <= 5) || LoBCD == 0x0F ) )//有功功率
                         return data;
	             if( (HiBCD == 4 || HiBCD == 5 ) && ((LoBCD >= 0 && LoBCD <= 3) || LoBCD == 0x0F ))//无功功率、功率因数
	                 return data;
	             break;
	        case 0xC0:
	             if( (HiBCD == 1 ) && ( (LoBCD >= 0 && LoBCD <= 1) || LoBCD == 0x0F ) )//日期、周次,时间	             
	                 return data;
	             if( (HiBCD == 2 ) && ( (LoBCD >= 0 && LoBCD <= 2) || LoBCD == 0x0F ) )//状态字
	                 return data;
	             if( (HiBCD == 3 ) && ( (LoBCD >= 0 && LoBCD <= 4) || LoBCD == 0x0F ) )//电表常数
	                 return data;
	             break;
	        case 0xC1:
	             if(LoBYTE >= 0x11 && LoBYTE <=0x1A)
	                 return data;
	             break;
	        case 0xC2:
	             if((LoBYTE == 0x11 || LoBYTE == 0x12))
	                 return data;
	             break;
	        case 0xC3:
	             if( (HiBCD == 1) && (LoBCD >=0 && LoBCD <= 4) )
	                 return data;
	             if(HiBCD == 0x02)
	                 return data;
	             if(HiBCD == 0x03)
	                 return data;
	             if(HiBCD == 0x04)
	                 return data;
	             if(HiBCD == 0x0A)
	                 return data;
	             break;
	        case 0xC4:
	             if(LoBYTE >= 0x10 && LoBYTE <= 0x1E)
	                 return data;
	             break;
	        case 0xC5:
	             if(LoBYTE == 0x10 || LoBYTE ==0x11)
	                 return data;
	             break;
	        default:
	             return 0;
	}
	return 0;
}

int CMPGB::ProcFullFrame(BYTE *data, int item,BYTE *outbuff,int &outlen, BYTE *addr)//处理完整的数据返回
{
	int  j;
	if( strncmp((char*) addr, (char*)&data[1],6) != 0)//地址不一侄
	{
		outlen = 6;
		for(int m = 0; m < 6; m++)
		     outbuff[m] = data[ m + 1 ];				
		return 0x0400;//地址不一样
	}
	switch(data[ 8 ])
	{
		case 0x81://读数据返回,无后续数据
		case 0xA1://读数据返回,有后续数据
		case 0x82://请求后续数据返回,无后续数据
		case 0xA2://请求后续数据返回,有后续数据
		case 0x83://重读数据,无后续
		case 0xA4://重读数据,有后续
		    if(item != (( data[ 11 ] - 0x33) * 256 + data[ 10 ] - 0x33 ))
		    {		    
		        return 0x0500;//抄表项目不一样
		    }
		    for(j = 0; j < data[9]; j ++)
		    {
		    	data[12 + j] -= 0x33;//数据域-0x33
		    }
		    for(j = 0; j < data[9];j++)
		    {
		    	if(data[12 + j] == 0xBB)
		    	{		    		
		    		return 0x0600;
		    	}
		    	 
		    }		
		    outlen = (int) data[9] - 2;
		    memcpy( (void *)outbuff, (void *)&data[12], data[9] );    
		    break;
		case 0xC1://读数据返回异常
		case 0xC2://读后续数据返回异常
		case 0xC3://重读数据返回异常
		case 0xC4://写数据,异常应答		  
		    return data[ 10 ] - 0x33; //电表返回错误码
		    break;
		case 0x84://写数据,从站正常应答
		    break;
//		    errCode = data[ 10 ] - 0x33;//电表返回错误码
//		    return false;		    
//		    break;
		case 0x8A://写设备地址,正常应答
		    break;//
		case 0x8C:
		    break;//更改通讯速率,正常应答
		default:
//		    errCode = 0x0600;
		    return 0x0700;//无效的控制字符
	}
	return 0;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -