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

📄 main.c

📁 电力载波抄表系统里的电力载波采集器,采集数据再通过RS485向主站发送.
💻 C
字号:
//	采集器程序更新
//	重新规划存储器管理
//	1、最大管理32只表,未初始化全F
//	2、数量管理,没有记录数的概念,只有表数量
//	3、冻结电量管理。
//	4、抄表间隔:必须是10的倍数,最大60分钟。或者是零(间隔10秒)
//	5、抄读项默认901F。

#include	<pic.h>
#include	"cjq.h"
#include	"function.h"


#include	"work.c"
#include	"protocol.c"
#include	"InOut.c"
#include 	"public.c"

#ifdef	DEBUG
	__CONFIG(HS& WDTDIS& PWRTDIS& BORDIS& UNPROTECT& LVPDIS);
#else
	__CONFIG(HS& WDTEN& PWRTEN& BOREN& PROTECT);
#endif

//***************************************
// 编译选项,使用PICC 8.05版本
//	1、优化等级关闭
//	2、使能"enable assembler optimization"
//****************************************

//********** 主循环开始 *************
void main(void)
{
	di();						//关闭所有中断
	sysinit();					//系统初始化,设置相应端口

	_Show485	= 1;			//指示启动
	Delay1msx(200);
	_Show485	= 0;			//指示启动
	Delay1msx(200);
	_Show485	= 1;			//指示启动
	Delay1msx(200);
	_Show485	= 0;			//指示启动
	
	FMCheck();					//检测EEPROM,初始化相关参数
	TimerInit();				//设置时钟芯片
	variableInit();				//用户变量初始化
	_Show485	= 0;			//启动完成	
	Delay1msx(1500);
	TestTask.DI0	= 0;
	ei();						//打开中断
	
	while(1)					//主循环开始
	{
		ClrWdt();				//清看门狗
		
		Nop();
		RunTimeSet();			//设置各定时标志500ms, 1S, 1min, 60mins

		Nop();
		upCommCheck();			//上行指令检测,包括载波和红外。指令处理,仅仅组织帧
	
		Nop();
		Buff485Rec();			//485数据接收

		Nop();
		BuffPLCSend();			//载波发送

		Nop();
		Buff485Send();			//485发送

		Nop();
		AmrTaskDispose();		//处理485缓冲区的数据,上传,保存,。。。

		Nop();
		minTaskDispose();		//分钟任务处理, 必须放到抄表任务后!!
		
		Nop();
		AmrTaskSet();			//抄表任务定制,仅仅设置485抄读指令

		Nop();
		OnOffCheck();			//开盖检测

		Nop();
		sysCheck();				//每分钟一次
	}
}

//系统运行时间参数
void RunTimeSet(void)
{
	if(v_msCont >= 100u)
	{
		//1s!
		v_msCont	-= 100u;
		v_ssCont++;
		v_DirRetCont++;

		if(v_ssCont >= 60u)
		{
			//1分钟
			_SysCheck	= 1;				//每分钟一次系统检测
			v_ssCont	-= 60u;
            minTaskSet();					//分钟任务设置            
		}
	}

	if(v_DirRetCont >= 20u)
	{
		//20秒,内存实时上传数据无效
		lastCommBack[0]	= 0;
	
	}

	if(BuffPLCMark.Sta == c_RecNow)
	{
		if(BuffPLCMark.otc >= c_ByteOutT)	//c_ByteOutT*10ms 没有通信清载波缓冲区
		{
			BuffPLCMark.Sta	= c_Free;
			BuffPLCMark.ptr	= BuffPLC;
			BuffPLCMark.otc	= 0;
			BuffPLCMark.len	= 0;
		}
	}

	if(Buff485Mark.Sta	== c_WaitRec)		//等待响应
	{
		if(Buff485Mark.otc >= c_FrameOutT)	//帧超时
		{
			Buff485Mark.ptr	= Buff485;
			Buff485Mark.Sta	= c_RecOutT;	//超时
			Buff485Mark.otc	= 0;
			Buff485Mark.len = 0;
		}
	}
	else if(Buff485Mark.Sta	== c_RecNow)	//接收中
	{
		if(Buff485Mark.otc >= c_ByteOutT)	//字节超时
		{
			Buff485Mark.ptr	= Buff485;
			Buff485Mark.Sta	= c_RecOutT;	//超时
			Buff485Mark.otc	= 0;
			Buff485Mark.len	= 0;
		}
	}
	else
	{
		if(Buff485Mark.otc >= c_BuffClrT)	//2.5秒钟内没有动作
		{
			Buff485Mark.ptr	= Buff485;
			Buff485Mark.Sta	= c_Free;
			Buff485Mark.otc	= 0;
			Buff485Mark.len	= 0;
			TestTask.Sta	= c_TaskFree;
			AmrTask.Sta		= c_TaskFree;
			RtTask.Sta		= c_TaskFree;
		}
	}
	
	if((Buff485Mark.Sta == c_RecNow) || (Buff485Mark.Sta == c_Send))
	{
		_Show485		= 1;				//指示485通信
	}
	else
	{
		_Show485		= 0;
	}
}

//**********判断铁电是否初始化
void FMCheck(void)
{
	getStrFM(tempBuff1, a_FMMark, l_FMMark);			//获取铁电中,特征字
	highmemcpypgm2ram(MeterID, RomFMMark, l_FMMark);	//固定特征字
	
	if(0x0 == highmemcmp(tempBuff1, MeterID, l_FMMark))	//比较是否一致
	{
		return;											//相等,已初始化
	}
	
	//未初始化,初始化铁电
	v_ExtRunFlag	= c_FMInit;
	FMInit();

	//32个表地址写入0xff,32*6=192,一次最大写入4*6=24字节
	v_ExtRunFlag	= c_FMSet;

	if(_TRUE != FMSet(a_MeterID, 0xff, 192))
	{
		Reset();
	}
}
//********** 初始化外部存储器
void FMInit(void)
{
	v_IntRunFlag	= c_FMInit;
	safeCheck();
	
	//2.抄表间隔
	tempBuff[0]		= 0xff;	
	v_ExtRunFlag	= c_putStrFM;
	putStrFM(a_AmrSpace, tempBuff, 0x01u);
	
	//3. 设置冻结日时
	tempBuff[0]	    = 0x00u;	
	tempBuff[1]		= c_FreezeData;
	v_ExtRunFlag	= c_putStrFM;
	putStrFM(a_FreezeTime, tempBuff, 0x02u);
	
	//4. EEPROM初始化标志
	highmemcpypgm2ram(tempBuff, RomFMMark, l_FMMark);
	v_ExtRunFlag	= c_putStrFM;
	putStrFM(a_FMMark, tempBuff, l_FMMark);
}

//**********设置时钟芯片参数
void TimerInit(void)
{
	//关闭所有中断输出,时间格式(12 24),设置复位电平
	tempBuff[0]	= c_RTCINTAOFF;
	tempBuff[1]	= c_RTCINTB;
	
	v_ExtRunFlag	= c_putStrRTC;
	if(_FALSE == putStrRTC(0x0e, tempBuff, 0x02))	//0x0e是设置寄存器地址
	{
		Reset();
	}
}

//********* 初始化用户变量
void variableInit(void)
{
	unsigned char temp;
	
	BuffPLCMark.len		= 0;
	Buff485Mark.len		= 0;
	
	BuffPLCMark.ptr		= BuffPLC;
	Buff485Mark.ptr		= Buff485;
	
	BuffPLCMark.Sta		= c_Free;
	Buff485Mark.Sta		= c_Free;
	Buff485Mark.goal	= c_Free;
	
	BuffPLCMark.RetCont	= 0;			//透传抄读指令直接上传次数

	RtTask.Sta		= c_TaskFree;		//默认没有实时任务

	AmrTask.start	= c_TaskAllStart;	//上电马上开始自动抄表
	AmrTask.serial	= 0;				//抄表序号 = 0
	AmrTask.Sta 	= c_TaskFree;		//目前抄读状态空闲,可以设置电表进行抄读

	v_hhTask		= 0xff;				//小时任务不处理
	v_FreezeTask	= 0;				//冻结任务不处理

	lowmemset(lastCommBack, 0, 5);
	lowmemset(BuffPLC, 0, c_BuffMax);
	highmemset(Buff485, 0, c_BuffMax-6);//485缓冲区比载波少6字节!!

	//采集器号
	getStrFM(CollectorID, a_CollecterID, 6u);
	
	//获取当前时间
	getStrRTC(timerBuff, 0, 7);			//ss,mm,hh,WW,DD,MM,YY
	highmemcpy(timerBuff+3, timerBuff+4, 3);
	v_msCont	= 0;
	temp		= timerBuff[0];
	v_ssCont	= bytebcdtohex(temp);
	temp		= timerBuff[1];
	v_mmCont	= bytebcdtohex(temp);
	temp		= timerBuff[2];
	v_hhTask	= bytebcdtohex(temp);
	v_FreezeTask= timerBuff[3];
}

//系统初始化相关
void sysinit(void)
{
	//bank0
	ADCON0	= c_ADcon0;
	
	//bank1
	ADCON1	= c_ADcon1;
	
	TRISA	= c_TrisA;
	TRISB	= c_TrisB;
	TRISC	= c_TrisC;
	
	OPTION	= c_Option;
	INTCON	= c_INTcon;
	PIE1	= c_Pie1;
	PIE2	= c_Pie2;
	
	PR2		= c_SimBaud;
	TXSTA	= c_TXsta;
//	SPBRG	= v_baud485;

	//bank0
	PIR1	= 0;
	PIR2	= 0;
	PORTA	= 0;
	PORTB	= 0xff;
	PORTC	= 0xff;
	
	T1CON	= c_T1con;
	T2CON	= c_T2con9600;
	
	SSPCON	= c_SSPcon;
	CCP2CON	= c_CCP2con;
	CCP1CON	= c_CCP1con & 0xf0;
	CCPR1L	= c_CCPR1L;
	CCPR1H	= 0;
	
	RCSTA	= c_RCsta;
	
	if(OERR)
	{
		CREN	= 0;
		CREN	= 1;
		asm("movf _RCREG, w");
		asm("movf _RCREG, w");
	}
}


//系统检测
void sysCheck(void)
{
	if(c_INTcon	!= (INTCON & c_INTcon))
	{
		INTCON	= c_INTcon;
	}

	if(PIE1	!= c_Pie1)
	{
		PIE1	= c_Pie1;
	}
	
	if(_SysCheck == 0) return;

	_SysCheck	= 0;
	
	//bank0
	ADCON0	= c_ADcon0;
	
	//bank1
	ADCON1	= c_ADcon1;

	TRISA	= c_TrisA;
	TRISB	= c_TrisB;
	TRISC	= c_TrisC;

	OPTION	= c_Option;
	if(PIE2	!= c_Pie2)
	{
		PIE2	= c_Pie2;
	}
	
	PR2		= c_SimBaud;
	
	//bank0
	T1CON	= c_T1con;
	T2CON	= c_T2con9600;
	
	SSPCON	= c_SSPcon;
	CCP2CON	= c_CCP2con;
	CCP1CON	= c_CCP1con & 0xf0;
	CCPR1L	= c_CCPR1L;
	CCPR1H	= 0;
	
}



⌨️ 快捷键说明

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