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

📄 communicate.c

📁 基于单片机的多费率电能表源程序
💻 C
📖 第 1 页 / 共 2 页
字号:
#define	COMM_GLOBALS
#include "includes.h"

const INT8U SuperPassWord[]={0x00,0x27,0x10,0x79};
const struct CommunicateDataStruct CommunicateDataTable[]=
{	/*	
	数据标识;
	数据长度;
	数据特征:
		b7~b6:数据寻址方式:
			00:数据在RAM中;
			01:数据在EEPROM中固定地址;
			10:数据在EEPROM中动态地址;
			11:数据在RAM和EEPROM固定地址中,并且要求两者同步更新;		
		b5:是否允许读操作;
		b4:是否允许写操作;
		b3~b0:特殊处理过程编号;
	EEPROM数据地址;
	RAM数据地址;
	*/
	{0x901f	,	16	,	0x20	,	0							,	(INT16U)&EnergyData.ActiveTotalEnergy[0]},			//(当前)正向有功电能集合            
	{0x9020	,	4	,	0x20	,	0							,	(INT16U)&EnergyData.ActiveReverseEnergy[0]},//反向累计电量   
	{0xb020	,	4	,	0x60	,	LAST_POWER_REVERSE_TIME_ID	,	0},//最后一次反向起始时间   
	{0xb021	,	3	,	0x20	,	0							,	(INT16U)&ReverseTotalTime[0]},//反向累计总时间   
	{0xb210	,	4	,	0x60	,	LAST_PROGRAM_TIME_ID		,	0},//最近一次编程时间   
	{0xb212	,	2	,	0x20	,	0							,	(INT16U)&ProgramTimes[0]},//总的编程次数    
	{0xC010 ,	4	,	0x32	,	0x00						,	(INT16U)&CurrentTime.Weekday},      //	日期及周次                                  
	{0xC011	,	3	,	0x33	,	0x00						,	(INT16U)&CurrentTime.Second},           //	时间                                
	{0xC020	,	1	,	0x20	,	0x00						,	(INT16U)&MeterRunningState},	//	电表运行状态                                        
    {0xC030	,	3	,	0x60	,	P_METER_CONST_ID			,	0},//	电表常数(有功)                                      
 	{0xC032	,	6	,	0x70	,	METER_NUMBER_ID    			,	0},//	表号 
    {0xC033	,	6	,	0xe0	,	USER_NUMBER_ID    			,	(INT16U)&UserNumber},//	用户号(局编号)v
	{0xC115	,	3	,	0xd4	,	DISPLAY_SELECT_ID    		,	(INT16U)&DisplaySelect[0]},//	显示选择                          
    {0xC117	,	2	,	0xf0	,	MONTH_STORE_DATE_ID			,	(INT16U)&MonthStoreDate[0]},//	月转存日期                      
   	{0xC119	,	0	,	0x16	,	0							,	0},//正向总、峰、平、谷、反向总(使用清零密码)              
 	{0xC33f	,	36	,	0x35	,	TIMESLICETABLE_ID    		,	(INT16U)&TimeSliceInfo.TimeSlice[0].RateID},//	时段表设置     
 	{0xd120	,	16	,	0xa1	,	ACTIVE_ENERGY_ID0			,	0},	//上1月正向有功电能集合 
	{0xd121	,	16	,	0xa1	,	ACTIVE_ENERGY_ID0			,	0},	//上2月正向有功电能集合 
	{0xd122	,	16	,	0xa1	,	ACTIVE_ENERGY_ID0			,	0},	//上3月正向有功电能集合 
	{0xd123	,	16	,	0xa1	,	ACTIVE_ENERGY_ID0			,	0},	//上4月正向有功电能集合 
	{0xd124	,	16	,	0xa1	,	ACTIVE_ENERGY_ID0			,	0},	//上5月正向有功电能集合 
	{0xd125	,	16	,	0xa1	,	ACTIVE_ENERGY_ID0			,	0},	//上6月正向有功电能集合 
	{0xd126	,	16	,	0xa1	,	ACTIVE_ENERGY_ID0			,	0},	//上7月正向有功电能集合 
	{0xd127	,	16	,	0xa1	,	ACTIVE_ENERGY_ID0			,	0},	//上8月正向有功电能集合 
	{0xd128	,	16	,	0xa1	,	ACTIVE_ENERGY_ID0			,	0},	//上9月正向有功电能集合 
	{0xd129	,	16	,	0xa1	,	ACTIVE_ENERGY_ID0			,	0},	//上10月正向有功电能集合 
	{0xd12a	,	16	,	0xa1	,	ACTIVE_ENERGY_ID0			,	0},	//上11月正向有功电能集合 
	{0xd12b	,	16	,	0xa1	,	ACTIVE_ENERGY_ID0			,	0},	//上12月正向有功电能集合 
 };     

void CommunicateInit(void)
{
	/*UART口初始化*/
	HB_SCR3=0;	
	HB_SMR=0x20;//asy, 8bit, even,1stop
	HB_BRR=129;//bps is 1200 when 10M crystal when using 38024F
	DelayXms(1);
	HF_SPCR_SPC32=1;
	HF_SCR3_RE=1; 
	HF_SCR3_TE=0;		
	CommunicateReceiveEnable();
}     
/*****************通信处理程序******************/      
void CommunicateReceiveEnable(void)                                                                                                	
{   
	_CommunicateReceiveEnableTask=0;	
	RecState=0;
	HF_SCR3_RE=1; 
	HF_SCR3_TE=0;	
	HF_SCR3_RIE=1;	
	HB_SSR&=0x0c7;
	Com485ReceiveBytes=0;
	En_485Re;
	Open_IRReceiveEdgInt;
	Stop_IrMdlt;
}
void CommunicateSendEnable(void)                                                                                                	
{       
	HF_SCR3_RE=0; 
	HF_SCR3_TE=1;
	HF_SCR3_RIE=0;
	HF_SCR3_TIE=0;
	if(Com485ReceiveBytes>10)
	{
		En_485Tr;
	}
	else
	{
		Start_IrMdlt;	
	}
	DelayXms(1);
	_DataSend_=1;
	PreCharactorCnt=1;	
}
INT8U  DichotomySearch(INT16U DataID)
{
	INT8U Left=1; 
	INT8U Right=MAXCOMMUNICATENUM;
	INT8U Middle;
	while(Left<=Right)
	{ 
		Middle=(Left+Right)/2;
		Middle--; 
		if (DataID==CommunicateDataTable[Middle].CommunicateDataID) 
			return Middle; 
		if (DataID>CommunicateDataTable[Middle].CommunicateDataID) 
			Left=Middle+2; 
		else Right=Middle; 		
	} 
	return 255; 
} 

INT8U CommunicateReadData(void)
{
	INT8U DataPos;
	INT8U *Pnt;
	INT8U i ;
	INT16U DataTemp;
	DataTemp=RecBuf[11];
	DataTemp<<=8;
	DataTemp+=RecBuf[10];
	DataPos=DichotomySearch(DataTemp);
	if(DataPos<MAXCOMMUNICATENUM)
	{
		if(CommunicateDataTable[DataPos].PropertyData1&0x20)
		{
			switch(CommunicateDataTable[DataPos].PropertyData1&0xc0)
			{
				case 0x00://ram区数据
				case 0xc0://数据在RAM和EEPROM固定地址中
					Pnt=(INT8U *)CommunicateDataTable[DataPos].RamDataAddress;
					for(i=0;i<CommunicateDataTable[DataPos].DataLength;i++)
					{
						SendBuf[12+i]=*Pnt;
						Pnt++;	
					}
					break;
				case 0x40://eeprom中固定地址数据
					if(!ReadEepromData(CommunicateDataTable[DataPos].EepromDataId,&SendBuf[12]))
					{
						if(!ReadEepromData(CommunicateDataTable[DataPos].EepromDataId,&SendBuf[12]))
						{
							for(i=0;i<CommunicateDataTable[DataPos].DataLength;i++)
								SendBuf[12+i]=0;
						}
					}
					break;
				case 0x80://eeprom中动态地址数据
					i=RecBuf[10]&0x0f;
					if(EnergyData.EnergyPointer>=(i+1))
					{
						TempBufOfMain[0]=(ACTIVE_ENERGY_ID0-1+EnergyData.EnergyPointer-i);
							
					}
					else
					{
						TempBufOfMain[0]=(ACTIVE_ENERGY_ID0+12+EnergyData.EnergyPointer-i);
							
					}
					if(!ReadEepromData(TempBufOfMain[0],&SendBuf[16]))
					{
						if(!ReadEepromData(TempBufOfMain[0],&SendBuf[16]))
						{
							for(i=0;i<CommunicateDataTable[DataPos].DataLength;i++)
								SendBuf[12+i]=0;
						}
					}					
					break;
				default:
					return 0;
									
			}
			SendBuf[9]=CommunicateDataTable[DataPos].DataLength+2;
			SendBuf[10]=RecBuf[10];
			SendBuf[11]=RecBuf[11];	
			switch(CommunicateDataTable[DataPos].PropertyData1&0x0f)
			{
				case 1:
					BcdAdd(&SendBuf[20],&SendBuf[16],TempBufOfMain,4);
					BcdAdd(&SendBuf[24],TempBufOfMain,&SendBuf[12],4);
					break;
				case 5:
				//时段表处理
					SendBuf[9]=TimeSliceInfo.TimeSliceNum*3+2;	
					break;
				default:
					break;					
			}					
			return 1;	
		}		
	}
	return 0;		
}  
INT8U CommunicateWriteData(void)
{
	INT8U DataPos,Sign;
	INT8U *Pnt;
	INT8U i;
	INT16U DataTemp;
	if(Is_ProGramPermit)
	{
		if((RecBuf[10]==0x19)&&(RecBuf[11]==0xc1))
		{
			Sign=1;
			for(i=0;i<4;i++)
			{
				if(RecBuf[12+i]!=Clear0PassWord[i])
				{
					Sign=0;
					break;	
				}	
			}
			if(Sign)
			{
				InitEnergyData(&RecBuf[20]);
				_ProgramRecord=1;				
				SendBuf[9]=0;							
				return 1;
			}
		}
		else
		{
			Sign=1;		
			for(i=0;i<4;i++)
			{
				if(RecBuf[12+i]!=ProgramPassWord[i])
				{
					Sign=0;
					break;	
				}	
			}
			if(Sign)
			{
				DataTemp=RecBuf[11];
				DataTemp<<=8;
				DataTemp+=RecBuf[10];
				DataPos=DichotomySearch(DataTemp);			
				if(DataPos<MAXCOMMUNICATENUM)
				{
					if(CommunicateDataTable[DataPos].PropertyData1&0x10)//允许写
					{
						switch(CommunicateDataTable[DataPos].PropertyData1&0xc0)
						{
							case 0x00:
								Pnt=(INT8U *)CommunicateDataTable[DataPos].RamDataAddress;
								for(i=0;i<CommunicateDataTable[DataPos].DataLength;i++)
								{
									*Pnt=RecBuf[16+i];
									Pnt++;	
								}
								break;
							case 0x40:
								WriteEepromData(CommunicateDataTable[DataPos].EepromDataId,&RecBuf[16]);
								break;
							case 0xc0:
								Pnt=(INT8U *)CommunicateDataTable[DataPos].RamDataAddress;
								for(i=0;i<CommunicateDataTable[DataPos].DataLength;i++)
								{
									*Pnt=RecBuf[16+i];
									Pnt++;	
								}
								WriteEepromData(CommunicateDataTable[DataPos].EepromDataId,&RecBuf[16]);
								break;						
							default:
								return 0;							
						}
						switch(CommunicateDataTable[DataPos].PropertyData1&0x0f)
						{
							case 2:
								SetSystemDate(&CurrentTime.Weekday);
								MultiRateInit();
								if(IsBroadCalibrateTimePermit())
									_BroadCalibrateTimeAllow_=1;
								else
									_BroadCalibrateTimeAllow_=0;								
								break;
							case 3:
								SetSystemTime(&CurrentTime.Second);	
								MultiRateInit();
								if(IsBroadCalibrateTimePermit())
									_BroadCalibrateTimeAllow_=1;
								else
									_BroadCalibrateTimeAllow_=0;						
								break;
							case 4:
								DisplayCircleInterval=(DisplaySelect[0]&0x0f)+(DisplaySelect[0]>>4)*10;
								if(DisplaySelect[2]&0x80)
									DisplayState=1;
								else
									DisplayState=0;
								PaginationSign=0;
								break;
								
							case 5:
								//时段表处理
								TimeSliceInfo.TimeSliceNum=(RecBuf[9]-6)/3;
								Pnt=&TimeSliceInfo.TimeSlice[TimeSliceInfo.TimeSliceNum].RateID;
								for(i=RecBuf[9]-6;i<36;i++)
								{
									*Pnt=0;
									Pnt++;
								}
								TimeSliceSort();
								if(TimeSliceTableCheck())
								{
									WriteEepromData(CommunicateDataTable[DataPos].EepromDataId,&TimeSliceInfo.TimeSliceNum);
									MultiRateInit();
								}
								else
								{
									if(!ReadEepromData(TIMESLICETABLE_ID,TempBufOfMain))
									{
										if(!ReadEepromData(TIMESLICETABLE_ID,TempBufOfMain))
											InitEepromData(TIMESLICETABLE_ID);
									}
									InitRamData(TIMESLICETABLE_ID);	
									MultiRateInit();
									return 0;							
								}
																
								break;						
							default:
								break;
						}
						_ProgramRecord=1;				
						SendBuf[9]=0;							
						return 1;	
					}
				}
			}		
		}
	}
	return 0;
} 
void BroadcastSetTime(void)
{
	CurrentTime.Year=RecBuf[15];
	CurrentTime.Month=RecBuf[14];
	CurrentTime.Day=RecBuf[13];	
	CurrentTime.Hour=RecBuf[12];
	CurrentTime.Minute=RecBuf[11];
	CurrentTime.Second=RecBuf[10];
	CurrentTime.Weekday=GetWeekDay(CurrentTime.Month,CurrentTime.Day, CurrentTime.Year);	
	SetSystemDateAndTime(&CurrentTime.Second);
	MultiRateInit();
	TempBufOfMain[0]=CurrentTime.Hour;
	TempBufOfMain[1]=CurrentTime.Day;
	TempBufOfMain[2]=CurrentTime.Month;
	TempBufOfMain[3]=CurrentTime.Year;
	WriteEepromData(LAST_BROADCAST_TIME_ID,TempBufOfMain);
	_BroadCalibrateTimeAllow_=0;
	_ProgramRecord=1;
} 

void CommunicateWriteUserID(void)
{
	INT8U i;
	INT8U *Pnt;
	Pnt=&RecBuf[10];
	for(i=0;i<6;i++)
	{
		UserNumber[i]=*Pnt;
		TempBufOfMain[i]=*Pnt;		
		Pnt++;
	}
	WriteEepromData(USER_NUMBER_ID,&RecBuf[10]);
	SendBuf[9]=0;	
	_ProgramRecord=1;	
}  
INT8U CommunicateChangePassword(void)
{
	INT8U i,PasswordType;
	INT8U *Pnt;
	PasswordType=PROGRAM_PASSWORD;
	for(i=0;i<4;i++)
	{
		if(RecBuf[10+i]!=ProgramPassWord[i])
		{
			PasswordType=CLEAR0_PASSWORD;
			break;	
		}	
	}	
	if(PasswordType==CLEAR0_PASSWORD)
	{
		for(i=0;i<4;i++)
		{
			if(RecBuf[10+i]!=Clear0PassWord[i])
			{
				PasswordType=SUPER_PASSWORD;
				break;	
			}	
		}			
	}	
	if(PasswordType==SUPER_PASSWORD)
	{
		for(i=0;i<4;i++)
		{
			if(RecBuf[10+i]!=SuperPassWord[i])
			{
				PasswordType=ERROR_PASSWORD;
				break;	
			}	
		}
			
	}	
	switch(PasswordType)
	{
		case ERROR_PASSWORD:
			return 0;
		case SUPER_PASSWORD:
			if(RecBuf[14]==0)
			{
				SetClear0Password();
			}
			else if(RecBuf[14]==1)
				{
					SetProgramPassword();
				}
				else
					return 0;
			
			break;

⌨️ 快捷键说明

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