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

📄 protocol.c

📁 电力载波抄表系统里的电力载波采集器,采集数据再通过RS485向主站发送.
💻 C
📖 第 1 页 / 共 2 页
字号:
//work
//1.设置采集器地址不需长按按键
//2.

//	载波缓冲区,检测
void upCommCheck(void)
{
    unsigned char	temp;
	unsigned char	serial;
	unsigned int	addr;
	
	if(BuffPLCMark.Sta != c_RecEnd)		//载波接收完成?
	{
		return; 
	}

	//载波帧格式判断,并数据域减33
	if(_FALSE == frame645Checklow(BuffPLC))
	{
		goto	BuffPLCCheckErr;		//指令错误
	}
	temp	= BuffPLC[c_OffsetC];
	
	if((temp&0x80) != 0)
	{
		goto	BuffPLCCheckErr;		//防止某些表,红外载波一起往外发数据!!
	}

	//指令参数保存
	v_FrameC	= BuffPLC[c_OffsetC];
	v_FrameL	= BuffPLC[c_OffsetL];
	v_DI0		= BuffPLC[c_OffsetDI0];
	v_DI1		= BuffPLC[c_OffsetDI1];
    
	//判断是否为广播命令
    if(0x0 == lowmemcmppgm2ram(BuffPLC+1, RomBroadID, 6u))
    {
        //******* 广播指令处理 ************
		if(_TRUE == BroadDispose())					//广播指令处理
        {
            goto	BuffPLCCheckEnd;
        }
		else
        {
            goto	BuffPLCCheckErr;
        }        
    }
	
	///////////////指令处理///////////////
	//1.判断指令来源,红外需要判地址
	if(c_Port_Irf == v_RecPort)
	{
		if(0 != memcmph2l(BuffPLC+1, CollectorID, 6))
		{
			goto	BuffPLCCheckErr;		//地址不对
		}
	}
	else
	{
		memcpyl2h(CollectorID, BuffPLC+1, 6);	//防止没有设置红外地址
	}

	//判断指令对象
	if(_FALSE == CommObjCheck())               	//判断指令对象
	{
//*******************************************************
//*	针对电表相关操作
//*******************************************************/

		//保存指令中电表表号
		memcpyl2h(MeterID, (BuffPLC+c_OffsetData+v_FrameL-8), 0x06);

		//获取电表序号
		serial = getMeterSr(MeterID);			//获取电表序号

//*************************** linyou, 2008-11-20		
//确定规约格式,通过控制字确认。0x11,0x14为07版645。其他默认为97版645
		if((v_FrameC == 0x11) || (0x14 == v_FrameC))
		{
			v_frame_mark	= _frame_07;
			goto	RtTaskset;					//07直接透传
		}
		else
		{
			v_frame_mark	= _frame_97;
		}
//***************************

		if(v_FrameC == 0x01u)
		{
			v_DirRetCont	= 0;				//备份数据有效期计数器

			//判断抄表间隔0xff透传
			getStrFM(tempBuff, a_AmrSpace, 1);
			temp	= tempBuff[0];
			if(temp == 0xff)	goto RtTaskset;
			
			//判断表号是否存在
			if(serial > c_MaxMeterAmount)		//序号大于容量即是不存在
			{
				//该电表不存在,保存该表号
				serial = addOneMeter(MeterID);	//只需要表号,返回序号
				
				//设置测试任务
				if(c_TaskFree == TestTask.start)
				{
					//空闲才设定
					TestTask.start	= c_TaskAllStart;
					TestTask.Sta	= c_TaskFree;
					TestTask.serial	= serial;
				}
				
				goto RtTaskset;
			}
			else
			{
				//电表存在
				//判断抄读标识
				if(0x90 == v_DI1)
				{
					//读取失败次数,确认数据有效性
					getStrFM(tempBuff, a_FalseNO + serial*c_OneSize, 1);
					if(0x0 != tempBuff[0])	goto RtTaskset;

					//抄读当前电能块,第一字节是长度
					getStrFMlow(BuffPLC+c_OffsetDI1, a_Consume + serial*c_OneSize, 20+1);
					//数据处理
					if(0x1f == v_DI0)
					{
						v_FrameL = BuffPLC[c_OffsetDI1] + 2 + 6;	//数据长度 + DI0DI1
						memcpyh2l(BuffPLC+c_OffsetData+v_FrameL-8, MeterID, 6);
						v_FrameC = 0x81;
						goto	BuffPLCCheckEnd;
					}	
					else if(0x10 == v_DI0)
					{
						//抄读当前总电能
						v_FrameL = 0x04 + 2 + 6;					//数据长度 + DI0DI1
						memcpyh2l(BuffPLC+c_OffsetData+4, MeterID, 6);
						v_FrameC = 0x81;
						goto	BuffPLCCheckEnd;
					}
				}
				else if((0x9a == v_DI1) || (0x9e == v_DI1))
				{
					//抄读冻结电能块:日期+长度+数据,
					//不能使用上行缓冲区,否则判断和上次指令是否一致时有误
					getStrFM(tempBuff, a_FzConsume + serial*c_OneSize, 20+2);

					//数据有效性判断
					if(tempBuff[0] == 0)
					{
						//读取失败次数,确认当前数据有效性
						getStrFM(tempBuff, a_FalseNO + serial*c_OneSize, 1);
						if(0x0 != tempBuff[0])	goto RtTaskset;
	
						//抄读当前电能块,第一字节是长度
						getStrFM(tempBuff+1, a_Consume + serial*c_OneSize, 20+1);
					}
					
					//转移数据到上行缓冲区
					v_FrameL	= tempBuff[1];				//数据长度
					memcpyh2l(BuffPLC+c_OffsetData, tempBuff+2, v_FrameL);
					
					if(0x1f == v_DI0)
					{
						v_FrameL +=  8;						//数据长度 + DI0DI1 + 表号
                    	memcpyh2l(BuffPLC+c_OffsetData+v_FrameL-8, MeterID, 6);
						v_FrameC = 0x81;
						goto	BuffPLCCheckEnd;
					}
					else if(0x10 == v_DI0)
					{
						//抄读冻结总电能
						v_FrameL = 0x04 + 2 + 6;			//数据长度 + DI0DI1 + 表号
						memcpyh2l(BuffPLC+c_OffsetData+4, MeterID, 6);
						v_FrameC = 0x81;
						goto	BuffPLCCheckEnd;
					}
					goto BuffPLCCheckErr;
				}
				else if((0xE8 == v_DI1) || (0x9d == v_DI1))
				{
					//获取标志
					getStrFM(tempBuff, a_24ConMark, 0x02);

					//当前日期减一
					highmemcpy(tempBuff+2, timerBuff+dd, 3);
					DateDec(tempBuff+2);
					if(tempBuff[0] == tempBuff[2])
					{
						addr	= a_24Consume0;				//返回前一天数据
					}
					else if(tempBuff[1] == tempBuff[2])
					{
						addr	= a_24Consume1;
					}
					else
					{
						v_hhTask	= timerBuff[hh];
						v_hhTask	= bytebcdtohex(v_hhTask);	//开始一次小时抄读
						goto BuffPLCCheckErr;
					}

					v_FrameC	= 0x81;
					if(0xE8 == v_DI1)
					{
						v_FrameL	= 32;						//2+24+6=32
						memcpyh2l(BuffPLC+c_OffsetData+24, MeterID, 6);
					}
					else
					{
						v_FrameL	= 2+16+6;						
						memcpyh2l(BuffPLC+c_OffsetData+16, MeterID, 6);
					}
										
					if(0x60 == v_DI0)
					{
						//0~5点整点电量
						getStrFMlow(BuffPLC+c_OffsetData, (addr+c_OneSize*serial), 24);
						goto BuffPLCCheckEnd;
					}

					else if(0x61 == v_DI0)
					{
						//6~11点整点电量
						getStrFMlow(BuffPLC+c_OffsetData, (addr+c_OneSize*serial+24), 24);
						goto BuffPLCCheckEnd;
					}

					else if(0x62 == v_DI0)
					{
						//12~17点整点电量
						getStrFMlow(BuffPLC+c_OffsetData, (addr+c_OneSize*serial+48), 24);
						goto BuffPLCCheckEnd;
					}

					else if(0x63 == v_DI0)
					{
						//18~23点整点电量
						getStrFMlow(BuffPLC+c_OffsetData, (addr+c_OneSize*serial)+72, 24);
						goto BuffPLCCheckEnd;
					}
					else if(0x30 == v_DI0)
					{
						//0~3点
						getStrFMlow(BuffPLC+c_OffsetData, (addr+c_OneSize*serial), 16);
						goto	BuffPLCCheckEnd;
					}
					else if(0x31 == v_DI0)
					{
						//4~7点
						getStrFMlow(BuffPLC+c_OffsetData, (addr+c_OneSize*serial)+16, 16);
						goto	BuffPLCCheckEnd;
					}
					else if(0x32 == v_DI0)
					{
						//8~11点
						getStrFMlow(BuffPLC+c_OffsetData, (addr+c_OneSize*serial)+32, 16);
						goto	BuffPLCCheckEnd;
					}
					else if(0x33 == v_DI0)
					{
						//12~15点
						getStrFMlow(BuffPLC+c_OffsetData, (addr+c_OneSize*serial)+48, 16);
						goto	BuffPLCCheckEnd;
					}
					else if(0x34 == v_DI0)
					{
						//16~19点
						getStrFMlow(BuffPLC+c_OffsetData, (addr+c_OneSize*serial)+64, 16);
						goto	BuffPLCCheckEnd;
					}
					else if(0x35 == v_DI0)
					{
						//20~23点
						getStrFMlow(BuffPLC+c_OffsetData, (addr+c_OneSize*serial)+80, 16);
						goto	BuffPLCCheckEnd;
					}
					goto	BuffPLCCheckErr;					
				}
			}
			
RtTaskset:
			if(RtTask.Sta != c_Free)	goto BuffPLCCheckErr;	//如果有实时任务在处理直接退出
			
			//抄读类,判断是否和上次实时指令一致
			//和上一次指令比较,抄读类指令暂存数据,下次查询直接上传
			if(0 == lowmemcmp(BuffPLC+c_OffsetDI0, lastCommBack, 10))	//只比较DI0 DI1 ID(6) CS 16 或者DI0, DI1 DI2 DI3 + ID[6]
			{
				//两次指令一致
				//判断数据有效性
				BuffPLCMark.RetCont++;						//直接上传次数+1
				
				//组织回应帧
				if(RtData[0] == c_UpData)
				{
					v_FrameL	= RtData[1];				//数据长度
					memcpyh2l(BuffPLC+c_OffsetDI0, RtData+2, v_FrameL);		//数据
					memcpyh2l(BuffPLC+c_OffsetData+v_FrameL-2, MeterID, 6);	//表号
					v_FrameC	= v_RetCback;
					v_FrameL	+= 6;							//加表号长度
					
					if(BuffPLCMark.RetCont >= c_RetCont)		//判断上传次数
					{
						lowmemset(lastCommBack, 0xff, 4);		//暂存数据失效
						v_DirRetCont		= 0;				//数据有效性计数器
						BuffPLCMark.RetCont	= 0;
					}
					
					Delay1msx(10);
					goto	BuffPLCCheckEnd;
				}
			}
			
			//指令备份
			lowmemcpy(lastCommBack, BuffPLC+c_OffsetDI0, 10);
		}
		else
		{
			lastCommBack[0]	= 0;					//非抄读类指令,内存数据失效
		}

//***** 指令转发,设定实时抄表任务 ****
		
		//准备新的实时抄表指令
		highmemcpy(RtMeterID, MeterID, 6u);

		//设定抄读项,没有DI0DI1时,没有实际意义
		RtTask.DI0	= v_DI0;
		RtTask.DI1	= v_DI1;

		RtTask.Ctr	= v_FrameC;
		RtTask.len	= v_FrameL - 6;			//减6字节表号

		RtData[0]	= c_DownData;			//标示数据方向是下发到485
		memcpyl2h(RtData+1, BuffPLC+c_OffsetDI0, RtTask.len);//只保存数据域,包括DI0,DI1

		RtTask.Port = v_RecPort;
		RtTask.Sta	= c_TaskRun;			//开始实时任务
		RtTask.FeCont	= 2;				//默认2FE
		
		goto	BuffPLCCheckErr;			//没有数据上传
	}
	else
	{
//*******************************************************
//*	针对采集器有关操作
//*******************************************************/
		if(v_FrameC	== 0x01)
		{
            p_BuffPLC   = BuffPLC+c_OffsetData;

			/////////////////抄读类
			if(v_DI1 == 0xc0)
			{
				//co20, c038, c010, c011
				if(v_DI0 == 0x20)
				{
					//C020 返回波特率和电表纪录数、电表数量
					*p_BuffPLC++	= v_OnOffSta;						//开盖状态
                    *p_BuffPLC++    = getMeterAmount();                 //获取电表数量
                    *p_BuffPLC      = *(p_BuffPLC-1);					//和以前指令统一

                    v_FrameC	= 0x81;
					v_FrameL	= 0x03 + 0x02;
					goto	BuffPLCCheckEnd;
				}
				else if(v_DI0 == 0x38)
				{
					//按长度区分是读取表特征字,还是读取采集间隔
					if(v_FrameL == 0x02)
					{
						//C038 返回版本号 + 抄表间隔时间
						*p_BuffPLC++	= c_VER;
						getStrFM(tempBuff, a_AmrSpace, 0x01);  //采集间隔,16进制
						*p_BuffPLC++	= tempBuff[0];
						
						v_FrameC	= 0x81;
						v_FrameL	= 0x02 + 0x02;
						goto	BuffPLCCheckEnd;
					}
					else if(v_FrameL == 0x08)
					{
						//电表特征字
						//保存指令中电表表号
						memcpyl2h(MeterID, (BuffPLC+c_OffsetData+v_FrameL-8), 0x06);

						//获取电表序号
						serial = getMeterSr(MeterID);
						if(serial > c_MaxMeterAmount)
						{
							//没有该表添加0xFF
							*p_BuffPLC ++	= 0xff;
						}
						else
						{
							getStrFMlow(p_BuffPLC, a_MeterMark+c_OneSize*serial, 1);
							p_BuffPLC++;							
						}
						
						memcpyh2l(p_BuffPLC, MeterID, 6);
						
						v_FrameC	= 0x81;
						v_FrameL	= 0x02 + 0x01 + 0x06;
						goto BuffPLCCheckEnd;
					}
				}
				else if(v_DI0 == 0x10)
				{
					//C010 返回日期周次YYMMDDWW
					getStrRTC(tempBuff, 0x03, 0x04);		//8025时钟地址,03是周开始
					memcpyh2l(p_BuffPLC, tempBuff, 4);
					v_FrameC	= 0x81;
					v_FrameL	= 0x04 + 0x02;
					goto	BuffPLCCheckEnd;
				}
				else if(v_DI0 == 0x11)
				{
					//C011 ss mm hh
					getStrRTClow(p_BuffPLC, 0x00, 0x03);	//8025时钟地址,00是秒开始
					v_FrameC	= 0x81;
					v_FrameL	= 0x03 + 0x02;
					goto	BuffPLCCheckEnd;
				}
				else if(v_DI0 == 0x33)
				{
					if(0xff == BuffPLC[c_OffsetData])		//读取全部电表地址
					{
						if(v_RecPort == c_Port_Irf)
						{
							ReturnAllMeterID();				//返回所有表号
						}
						goto	BuffPLCCheckErr;			//已经返回
					}
				}
			}
			else if(v_DI1 == 0xc1)
			{
				if(v_DI0 == 0x17)
				{
					//C117 抄表日时
					getStrFMlow(p_BuffPLC, a_FreezeTime, 0x02);
					v_FrameC	= 0x81;
					v_FrameL	= 0x02 + 0x02;
					goto	BuffPLCCheckEnd;
				}
			}
			v_FrameC	= 0xC1;
		}
		
//*******设置类 数据域格式(pa p0 p1 p2 + data),密码+数据
		else if(v_FrameC == 0x04)
		{
			
//#ifndef	DEBUG
//			if(_Set == 1)		goto	BuffPLCCheckErr;		//判断按键
//#endif		
			if(v_DI1 == 0xC1)
			{
				//C117
				if((v_DI0 == 0x17) && (v_FrameL == 0x08))
				{	
					//C117 设置自动抄表日时
					v_ExtRunFlag	= c_putStrFM;
					putStrFMlow(a_FreezeTime, BuffPLC+c_OffsetData+4, 0x02);	//前4字节为密码
					v_FrameC	= 0x84;
					v_FrameL	= 0x00;
					goto	BuffPLCCheckEnd;
				}
			}
			else if(v_DI1 == 0xC0)
			{
				//C038,C010,C011
				if((v_DI0 == 0x38) && (v_FrameL == 0x07))
				{
					//C038 设置抄表间隔,只能设置为10,15,20, 30,60,0xff
					temp	= BuffPLC[c_OffsetData+4];
					if((temp!=10)&&(temp!=15)&&(temp!=20)&&(temp!=30)&&(temp!=60)&&(temp!=0xff))
					{
						v_FrameC	= 0xC4;
					}
					else
					{
						v_ExtRunFlag	= c_putStrFM;
						tempBuff[0]		= temp;					//16内存分BANK,特殊处理
						putStrFM(a_AmrSpace, tempBuff, 0x01);	//16内存分BANK
						v_FrameC	= 0x84;
					}
					v_FrameL	= 0x00;
					goto	BuffPLCCheckEnd;
				}
				else if((v_DI0 == 0x10) && (v_FrameL == 10))
				{
					//设置日期周次(wwddmmyy)
					v_ExtRunFlag	= c_putStrRTC;

⌨️ 快捷键说明

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