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

📄 work.c

📁 电力载波抄表系统里的电力载波采集器,采集数据再通过RS485向主站发送.
💻 C
📖 第 1 页 / 共 2 页
字号:
				FMSet(a_24Consume1+c_OneSize*serial, 0, c_24ConLen);
			}
		}
		else if(tempBuff1[1] == tempBuff[0])
		{
			tempBuff1[0]	= timerBuff[dd];		//当前日写入另一区域
			addr			= a_24Consume0;			//写另一个缓冲区
			for(serial=0; serial<c_MaxMeterAmount; serial++)
			{
				v_ExtRunFlag	= c_FMSet;
				FMSet(a_24Consume0+c_OneSize*serial, 0, c_24ConLen);
			}
		}
		else
		{
			tempBuff1[0]	= timerBuff[dd];
			tempBuff1[1]	= tempBuff[0];
			addr			= a_24Consume0;
			for(serial=0; serial<c_MaxMeterAmount; serial++)
			{
				v_ExtRunFlag	= c_FMSet;
				FMSet(a_24Consume0+c_OneSize*serial, 0, c_24ConLen*2);
			}
		}
		v_ExtRunFlag	= c_putStrFM;
		putStrFM(a_24ConMark, tempBuff1, 2);
	}
		
	//转存小时电量
	for(serial=0; serial<c_MaxMeterAmount; serial++)
	{
		//判断该序号表号是否有效
		if(_FALSE == getMeterID(tempBuff, serial))	continue;		//无效判断下一只电表
		
		//判断当前电量有效性
		getStrFM(tempBuff, a_FalseNO+c_OneSize*serial, 1);
		temp	= tempBuff[0];
		if(temp != 0)
		{
			//数据无效
			highmemset(tempBuff+2, 0, 4);						//tempBuff+2开始是电量

			v_ExtRunFlag	= c_putStrFM;
			putStrFM(a_FzConsume+c_OneSize*serial, tempBuff+2, 1);//冻结数据无效标志
			continue;
		}
		else
		{
			//数据有效
			getStrFM(tempBuff+1, a_Consume+c_OneSize*serial, 21);//获取当前电量,tempBuff+2,电量
		
			//判断冻结任务
			if(v_FreezeTask != 0)
			{
				//保存冻结电量
				tempBuff[0]		= v_FreezeTask;					//冻结日
				temp			= tempBuff[1] + 2;				//写入数据长度+长度和冻结日
				v_ExtRunFlag	= c_putStrFM;
				putStrFM(a_FzConsume+c_OneSize*serial, tempBuff, temp);
			}
		}

		//写入小时电量
		v_ExtRunFlag	= c_putStrFM;
		putStrFM((addr+c_OneSize*serial)+(4*v_hhTask), tempBuff+2, 4);
	}
	
	v_hhTask		= 0xff;
	v_FreezeTask	= 0;
}

//*********定时任务开始条件判断
//程序入口:分钟每次加1时调用
//自动抄表启动,冻结电量的存储,小时电量,月电量。。。
//*************************************
void minTaskSet(void)
{
	unsigned char temp;
	
	//获取当前时间
	getStrRTC(timerBuff, 0, 7);					//ss,mm,hh,WW,dd,MM,YY
	highmemcpy(timerBuff+3, timerBuff+4, 3);	//调整为s,m,h,w,d,m,y
	
	//修正时间偏差
	temp	= timerBuff[ss];				//因为所有间接寻址都在高bank,需要导入低两bank
	v_ssCont	= bytebcdtohex(temp);
	temp	= timerBuff[min];
	v_mmCont	= bytebcdtohex(temp);

	//获取抄表间隔,抄表间隔取值10,15,20, 30,60
	getStrFM(tempBuff, a_AmrSpace, 1);
	v_AmrSpace	= tempBuff[0];
	temp		= v_AmrSpace;

	if(v_AmrSpace == 0xff)
	{
		temp	= 30;
	}

	if((v_mmCont%temp) != 0)	return;		//没有定时任务
	
	//*** 到达定时抄表时间
	//启动定时抄表任务
	if(c_TaskAllStart != AmrTask.start)		//如果已经启动,不需重新起动
	{
		AmrTask.start	= c_TaskAllStart;	//启动条件
		AmrTask.Sta		= c_TaskFree;
		AmrTask.serial	= 0;				//开始序号
	}
	
	//判断整点
	if(v_mmCont != 0)		return;			//不是整点没有任务

	//整点,开始小时重点用户电量转存
	temp		= timerBuff[hh];			//小时, BCD码
	v_hhTask	= bytebcdtohex(temp);		//开始小时任务

	//判断小时是否和冻结时一致
	getStrFM(tempBuff, a_FreezeTime, 1);
	v_FreezeTask	= tempBuff[0];			//冻结时相等,开始冻结任务
	if(v_FreezeTask != temp)
	{
		v_FreezeTask	= 0;					//取消冻结任务
	}
	else
	{
		v_FreezeTask	= timerBuff[dd];
	}
}

//组织645帧,485缓冲区
//需要传递表号地址
//只能固定使用Buff485!!!!
void FrameSet485(bank2 unsigned char *ID)
{
	unsigned char len, cs;
	
	Buff485[c_Offset68_1]	= 0x68;
	Buff485[c_Offset68_2]	= 0x68;
	Buff485[c_OffsetC]		= v_FrameC485;
	Buff485[c_OffsetL]		= v_FrameL485;
	Buff485[c_OffsetDI0]	= v_DI0485;
	Buff485[c_OffsetDI1]	= v_DI1485;

	Buff485Mark.len			= v_FrameL485 + 12;		//数据域为0时帧长12,包括CS 16

	//填充表号
	highmemcpy(Buff485+1, ID, 6);
	
#ifdef DEBUG
	for(len=6; len>0; len--)
	{
		if((*(ID+len)) == 0xff)
		{
			NOP();
		}
	}
#endif
	
	//数据域+33
	p_Buff485				= Buff485 + c_OffsetDI0;
	len		= v_FrameL485;
	while(len--)
	{
		*p_Buff485	+= 0x33;
		p_Buff485++;
	}

	//计算CS
	len			= v_FrameL485 + 10;		//需要计算CS的个数	
	p_Buff485	= Buff485;
	cs			= 0;
	while(len--)
	{
		cs		+= *p_Buff485;
		p_Buff485++;
	}
	
	*p_Buff485++	= cs;
	*p_Buff485		= 0x16;

	//设置返回参数
	Buff485Mark.ptr		= Buff485;
	Buff485Mark.Sta		= c_Send;
}

//自动抄表,数据有效性判断
//数据都在Buff485中
unsigned char amrFrameCheck(void)
{
	if(_FALSE == frame645Check(Buff485)) return _FALSE;		//帧格式

	if(0x81	!= Buff485[c_OffsetC])	return _FALSE;			//控制字,因为都是抄读类

	if(Buff485[c_OffsetDI0] != AmrTask.DI0)	return _FALSE;

	if(Buff485[c_OffsetDI1] != AmrTask.DI1)	return _FALSE;

	if(Buff485[c_OffsetL] < 0x06)		return _FALSE;		//抄读数据不能少于4字节 + 2

	if(highmemcmp(Buff485+1, AmrMeterID, 6) != 0)	return _FALSE;	//表号不一致
	
	return	_TRUE;

}
//测试表类型,数据有效性判断
//数据都在Buff485中
unsigned char testFrameCheck(void)
{
	if(_FALSE == frame645Check(Buff485)) return _FALSE;		//帧格式

	if(0x81	!= Buff485[c_OffsetC])	return _FALSE;			//控制字,因为都是抄读类

	if(Buff485[c_OffsetDI0] != TestTask.DI0)	return _FALSE;

	if(Buff485[c_OffsetDI1] != TestTask.DI1)	return _FALSE;

	if(Buff485[c_OffsetL] < 0x06)		return _FALSE;		//抄读数据不能少于4字节 + 2

	return	_TRUE;
}

//************** 根据DI0设置抄读项相应位
void bsfMarkbit(unsigned char *p_mark, unsigned char DI0)
{
	switch (DI0) {
	case 0x1f:
		*p_mark	|= bsf_901f;
		break;
	case 0x10:
		*p_mark	|= bsf_9010;
		break;
	case 0x11:
		*p_mark	|= bsf_9011;
		break;
	case 0x12:
		*p_mark	|= bsf_9012;
		break;
	case 0x13:
		*p_mark	|= bsf_9013;
		break;
	case 0x14:
		*p_mark	|= bsf_9014;
	}
}
void bcfMarkbit(unsigned char *p_mark, unsigned char DI0)
{
	switch (DI0) {
	case 0x1f:
		*p_mark	&= bcf_901f;
		break;
	case 0x10:
		*p_mark	&= bcf_9010;
		break;
	case 0x11:
		*p_mark	&= bcf_9011;
		break;
	case 0x12:
		*p_mark	&= bcf_9012;
		break;
	case 0x13:
		*p_mark	&= bcf_9013;
		break;
	case 0x14:
		*p_mark	&= bcf_9014;
		break;
	}
}
/*******************************************/
//	查找空表号位置
/*******************************************/ 
unsigned char getFreeMeter(void)
{
    unsigned char loop1;
    unsigned char loop2		= 0;				//8次读取=32只表
    unsigned char serial    = 0;                //表序号
    bank2 unsigned char *p_data;
	
	while(loop2 < 8)
	{
    	//获取所有电表表号
    	getStrFM(tempBuff, a_MeterID+loop2*24, 24);//一次4只表
    	p_data		= tempBuff;
    	
    	loop1		= 4;
    	while(loop1--)
    	{
    	    if(_FALSE == MeterIDCheck(p_data))	//无效表号就可以作为空表号地址
    	    {
    	        return(serial);					//返回地址序号
    	    }
    	    serial++;
    	    p_data += 6;
    	}
    	
    	loop2++;
    }
    
    return  c_MaxMeterAmount+10;				//随便返回一个大于表数量的数
}
//************** 添加新表号到采集器内
// 添新表到第一个空位
// 返回加入序号,序号大于数量,没有加成功
//*************************************
unsigned char addOneMeter(bank2 unsigned char *ID)
{
	unsigned char	sr;			//保存序号

	sr = getFreeMeter();

	if(sr < c_MaxMeterAmount)
	{
		//有空位可以添加电表
		//保存表号
		v_ExtRunFlag	= c_putStrFM;
		putStrFM(a_MeterID+6*sr, ID, 6u);	//表号连续存放,不同于数据

		//初始化失败次数为1, 0代表成功
		v_ExtRunFlag	= c_FMSet;
		FMSet(a_FalseNO+c_OneSize*sr, 0x01u, 1u);

		//冻结标志初始化
		v_ExtRunFlag	= c_FMSet;
		FMSet(a_FzConsume+c_OneSize*sr, 0x00, 0x01);//首字节为零数据无效

		//初始化电表特征字
		v_ExtRunFlag	= c_FMSet;
		FMSet(a_MeterMark+c_OneSize*sr, 0x00, 0x01);
	}
	return	sr;
}

/***********************************
*	delOneMeter:按序号删除一只电表
***********************************/
void delOneMeter(unsigned char sr)
{
	//删除电表
	v_ExtRunFlag	= c_FMSet;
	FMSet(a_MeterID + 6*sr, 0xff, 6);
}

/**************************************
*	按序号获取电表表号,并判断是否有效
**************************************/
unsigned char getMeterID(bank2 unsigned char *ID, unsigned char sr)
{
	if(sr > c_MaxMeterAmount)	return(_FALSE);

	getStrFM(ID, a_MeterID + 6*sr, 6);			//读取表号

	
	return	(MeterIDCheck(ID));					//判断表号有效性
}
/*******************************************/
//按表号查找表序号,返回电表在存储器中的序号
//从 0 开始
// 返回值大于表最大数量时失败
/*******************************************/ 
unsigned char getMeterSr(bank2 unsigned char *p_ID)
{
    unsigned char loop1;
    unsigned char loop2		= 0;				//8次读取=32只表
    unsigned char serial    = 0;                //表序号
    bank2 unsigned char *p_data;
	
	while(loop2 < 8)
	{
    	//获取所有电表表号
    	getStrFM(tempBuff, a_MeterID+loop2*24, 24);//一次4只表
    	p_data		= tempBuff;
    	
    	loop1		= 4;
    	while(loop1--)
    	{
    	    if(0 == highmemcmp(p_data, p_ID, 6))
    	    {
    	        return(serial);					//返回地址序号
    	    }
    	    serial++;
    	    p_data += 6;
    	}
    	
    	loop2++;
    }
    
    return  c_MaxMeterAmount+10;				//随便返回一个大于表数量的数
}
// 按抄读项设置,抄读标示
// 输入:	抄读项或者特征字屏蔽表数量
void setDataMark485(unsigned char mark)
{
	v_DI1485		= 0x90;
	if(mark & bsf_901f)
	{
		v_DI0485	= 0x1f;
	}
	else if(mark & bsf_9010)
	{
		v_DI0485	= 0x10;
	}
	else if(mark & bsf_9011)
	{
		v_DI0485	= 0x11;
	}
	else if(mark & bsf_9012)
	{
		v_DI0485	= 0x12;
	}
	else if(mark & bsf_9013)
	{
		v_DI0485	= 0x13;
	}
	else if(mark & bsf_9014)
	{
		v_DI0485	= 0x14;
	}
}

/*************************************
* 	电表特征字有效性判断
*	_TRUE	有效
*	_FALSE	无效
**************************************/
unsigned char MeterMarkCheck(unsigned char Mark)
{
	if(Mark & 0x80)
	{
		if(Mark & 0b01111100)	return _FALSE;		//支持901F,分项必须是零
	}
	else
	{
		if((Mark & 0b01000000) == 0x00)	return _FALSE;	//不支持901F,也不支持9010有问题
	}
	
	if((Mark & 0b00000011) == 0x03)	return _FALSE;	//前导符个数最大2
	
	return	_TRUE;
}

/**************************************
*	检测开盖
*	输入:RA4	
**************************************/
void	OnOffCheck(void)
{
	static	unsigned char OnOffCont		= 128;		//计数器
	
	if(_OnOff == 0)						//低电平开箱
	{
		OnOffCont++;
	}
	else
	{
		OnOffCont--;
	}
	
	if(OnOffCont < 8)
	{
		OnOffCont	= 128;
		v_OnOffSta	= c_OffSta;
	}
	else if(OnOffCont > 218)			//开箱
	{
		OnOffCont	= 128;
		if(c_OffSta == v_OnOffSta)
		{
			v_OnOffSta	= c_OnSta;		//开箱状态
			tempBuff[0]	= v_OnOffSta;
			v_ExtRunFlag	= c_putStrFM;
			putStrFM(a_OnOffSta, &tempBuff[0], 1);
			//保存开箱时间
			putStrFM(a_OnOffSta+1, timerBuff, 6);
		}
	}
}

⌨️ 快捷键说明

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