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

📄 dlt645pri.c

📁 详细介绍了arm7-at91r40008,的开发全过程
💻 C
📖 第 1 页 / 共 2 页
字号:
/*------------------------------------------------------------------*/
/*模块名称:DL/T645.c                                            		*/
/*模块功能:DL/T 645-1997 多功能电能表通讯规约											*/
/*编写日期:2006年11月                                         			*/
/*编写者:  zhangxiaodan																						*/
/*------------------------------------------------------------------*/

#include "includes.h"
#include "dlt645pri.h"

extern struct DBConfig		*DBCfgs;
extern struct LinkInfo* ComLink[PORTNUM];
extern struct AppInfo* ComApp[PORTNUM];
extern struct SysPort*	ComDb[PORTNUM];

/*------------------------------------------------------------------*/
/*函数名称:DLT645_1997PriTask()																				*/
/*函数功能:DL/T 645-1997 多功能电能表规约主站方任务								*/
/*------------------------------------------------------------------*/
void DLT645_1997PriTask(struct SysPort *Info, struct PortAppInfo* PortCfg)
{
	BOOL	flag;
	INT8U	i, err;
	INT16U	events;

	i = Info->PortID - 1;
	
	//初始化
	ComLink[i] = (void*) malloc (sizeof (struct LinkInfo));
	ComApp[i] = (void*) malloc (sizeof (struct AppInfo));
	if ((ComLink[i] == NULL) || (ComApp[i] == NULL))
		return ;
	else
	{
		memset (ComLink[i], 0, sizeof (struct LinkInfo));
		memset (ComApp[i], 0, sizeof (struct AppInfo));
	}
	
	ComDb[i] = Info;
	flag = DLT645InitPriLink(i+1, PortCfg);
	if (!flag)
	{
		free (ComLink[i]);
		ComDb[i] = NULL;
		return ;
	}
	flag = DLT645InitPriApp(i+1, PortCfg);
	if (!flag)
	{
		free (ComApp[i]);
		ComDb[i] = NULL;
		return ;
	}
	
	DLT645RecMISIData(Info->PortID,FALSE);
	
	OSFlagPost(ComDb[i]->Event, FTXNEXT, OS_FLAG_SET, &err);
	while (1)
	{
		events = OSFlagPend(Info->Event, TIME100MS+FTXNEXT,
			OS_FLAG_WAIT_SET_ANY+OS_FLAG_CONSUME, 0, &err);
		
		if (events & FTXNEXT)	//继续处理
		{
			PRI645SCHEDULE(Info->PortID);
		}		
		//定时处理区(100MS)
		if(events & TIME100MS)
		{
			if(ComApp[i]->AppDevs[ComApp[i]->CurDevNo].FactDelayTime)
			{
				ComApp[i]->AppDevs[ComApp[i]->CurDevNo].FactDelayTime--;
				if(!ComApp[i]->AppDevs[ComApp[i]->CurDevNo].FactDelayTime)
				{
					if(ComApp[i]->AppDevs[ComApp[i]->CurDevNo].ComError > MAXCOMERROR)
					{
						if(ReadComYxStatus(i+1))
							SetComYxStatus(i+1,FALSE);						//写通讯状态 分
						ComApp[i]->AppDevs[ComApp[i]->CurDevNo].ComError = 0;
						ComApp[i]->AppDevs[ComApp[i]->CurDevNo].ReadDataFlag = 0;
						OSFlagPost(ComDb[i]->Event, FTXNEXT, OS_FLAG_SET, &err);
					}
					else
					{
						ComApp[i]->AppDevs[ComApp[i]->CurDevNo].ComError++;
						SendBakData(i+1);//发重复帧
					}
				}
			}
			
			ComApp[i]->AllDataCount++;
			if(ComApp[i]->AllDataCount >= ComApp[i]->AllData)
			{
				SetAllDataFlag(i+1);//置全数据标志
				ComApp[i]->AllDataCount = 0;
				OSFlagPost(ComDb[i]->Event, FTXNEXT, OS_FLAG_SET, &err);
			}
			
			ComApp[i]->SetClockCount++;
			if(ComApp[i]->SetClockCount >= ComApp[i]->SetClock)
			{
				SetClockFlag(i+1);//置对钟标志
				ComApp[i]->SetClockCount = 0;
				OSFlagPost(ComDb[i]->Event, FTXNEXT, OS_FLAG_SET, &err);
			}
			
			ComApp[i]->DDCounter++;
			if(ComApp[i]->DDCounter >= ComApp[i]->Counter)
			{
				SetKWHFlag(i+1);//置读电度标志
				ComApp[i]->DDCounter = 0;
				OSFlagPost(ComDb[i]->Event, FTXNEXT, OS_FLAG_SET, &err);
			}
			
			DLT645RecMISIData(Info->PortID,TRUE);
		}	
		
	}
}
BOOL DLT645InitPriLink(INT8U Port, struct PortAppInfo* PortCfg)
{
	INT8U	i;
	struct PPri645Pad *pPad;
	
	i = Port - 1;
	pPad = (struct PPri645Pad*)(PortCfg->pPad);
	
	ComLink[i]->Port = PortCfg->Port;
	ComLink[i]->Attr = PortCfg->Attr;
	ComLink[i]->RTSONDelay = PortCfg->RTSONDelay;
	ComLink[i]->Medium = PortCfg->Medium;
	ComLink[i]->Baudrate = PortCfg->Baudrate;
	ComLink[i]->MeterCount = pPad->MeterCount;
	ComLink[i]->DMeterAddr = (struct MeterAddr*)malloc(sizeof(struct MeterAddr)*ComLink[i]->MeterCount);
	if(ComLink[i]->DMeterAddr == NULL)
			return FALSE;

	ComLink[i]->RxdHead = 0;
	ComLink[i]->RxdTail = 0;
	ComLink[i]->RxdLength = 0;
	return TRUE;
}
BOOL DLT645InitPriApp(INT8U Port, struct PortAppInfo* PortCfg)
{
	INT8U	i, j, k;
	INT16U xuhao;
	struct PPri645Pad *pPad;
	
	i = Port - 1;
	pPad = (struct PPri645Pad*)(PortCfg->pPad);
	

	if((pPad->CmdControl&BIT0) != FALSE)				//对钟使能
		ComApp[i]->EnSetClock = TRUE;
		
	if((pPad->CmdControl&BIT1) != FALSE)				//定时召唤全数据
		ComApp[i]->TimeAllData = TRUE;

	if((pPad->CmdControl&BIT2) != FALSE)				//定时召唤电度
		ComApp[i]->TimeCounter = TRUE;

	if((pPad->CmdControl&BIT3) != FALSE)				//广播对钟
		ComApp[i]->BroadCastClock = TRUE;

	if(pPad->AllData < 1)
		pPad->AllData = 1;
	if(pPad->SetClock < 1440)
		pPad->SetClock = 1440;
	if(pPad->Counter < 1)
		pPad->Counter = 1;
	
	ComApp[i]->AllData = pPad->AllData*60*10;
	ComApp[i]->SetClock = pPad->SetClock*60*10;
	ComApp[i]->Counter = pPad->Counter*60*10;

	ComApp[i]->AllDataCount = 0;
	ComApp[i]->SetClockCount = 0;
	ComApp[i]->DDCounter = 0;
	
	ComApp[i]->DelayVal = pPad->DelayVal;
	ComApp[i]->DevNum = pPad->MeterCount;
	
	ComApp[i]->AppDevs = (struct PDevInfo*)malloc(sizeof(struct PDevInfo)*ComApp[i]->DevNum);
	if(ComApp[i]->AppDevs == NULL)
		return FALSE;

	for(j = 0;j < ComApp[i]->DevNum; j++)
	{
		ComApp[i]->AppDevs[j].DevID = GetDevIDOfName(pPad->AddrList[j].UserName);
		for(k = 0;k < 6;k++)
			ComApp[i]->AppDevs[j].Addr[k] = pPad->AddrList[j].ADDR[k];
		xuhao = GetActDevNoByDevID(i+1,ComApp[i]->AppDevs[j].DevID);
		ComApp[i]->AppDevs[j].MAddr = ComDb[i]->DBCfgs[xuhao].MAddress;
		ComApp[i]->AppDevs[j].ComError = 0;
		ComApp[i]->AppDevs[j].FactDelayTime = 0;
		ComApp[i]->AppDevs[j].DevData.AINum = ComDb[i]->DBCfgs[xuhao].YCNum;
		ComApp[i]->AppDevs[j].DevData.BINum = ComDb[i]->DBCfgs[xuhao].YXNum;
		ComApp[i]->AppDevs[j].DevData.CounterNum = ComDb[i]->DBCfgs[xuhao].DDNum;
		if(ComApp[i]->TimeAllData)
			ComApp[i]->AppDevs[j].ReadDataFlag |= ALLDATAFLAG;
		if(ComApp[i]->TimeCounter)
		{
			ComApp[i]->AppDevs[j].ReadDataFlag |= KWHFLAG;
			ComApp[i]->KWHStatus = PosiKWHDB;
		}
		if(ComApp[i]->EnSetClock)
			ComApp[i]->AppDevs[j].ReadDataFlag |= CLOCKFLAG;
		if(ComApp[i]->BroadCastClock)
			ComApp[i]->AppDevs[j].ReadDataFlag |=BROADCAST;
	}
	return TRUE;

}

//设备调度函数
BOOL DevDispatch(INT8U Port)
{
		INT8U i = 0,j = 0;
    INT16U DevNo,OldDevNo;
    INT32U zxd,zxd1;
 		i = Port - 1;   
    DevNo=ComApp[i]->CurDevNo;
    OldDevNo = DevNo;
    zxd = ComApp[i]->AppDevs[DevNo].ReadDataFlag;
    zxd1 = (~(ALLDATAFLAG|KWHFLAG));
    while((ComApp[i]->AppDevs[DevNo].ReadDataFlag & (ALLDATAFLAG|KWHFLAG))== 0)
    {
      DevNo=GetNextActDevNo(Port,DevNo);
      j++;
      ComApp[i]->KWHStatus = PosiKWHDB;
      if(j>=ComApp[i]->DevNum)
              return FALSE;
    }
    ComApp[i]->CurDevNo=DevNo;
    return TRUE;
}

/*----------------------------------------------------------------------------------*/
/*函数名称:GetDevIDByAddr(INT8U Port,INT8U *Addr)																	*/
/*函数功能:通过电能表地址获得设备的ID号																						*/
/*----------------------------------------------------------------------------------*/
INT16U GetDevIDByAddr(INT8U Port,INT8U *Addr)
{
	INT8U i,j;
	i = Port - 1;
	for(j = 0;j < ComApp[i]->DevNum;j++)
	{
		if(!memcmp(ComApp[i]->AppDevs[j].Addr,Addr,6))
			return (ComApp[i]->AppDevs[j].DevID);
	}
	return 0xffff;
}
/*----------------------------------------------------------------------------------*/
/*函数名称:GetActDevNoByDevID(INT8U Port,INT16U DevID)															*/
/*函数功能:通过电能表ID号获得设备的序号																						*/
/*----------------------------------------------------------------------------------*/
INT16U GetActDevNoByDevID(INT8U Port,INT16U DevID)
{
	INT8U i,j;
	i = Port - 1;
	for(j = 0;j < ComDb[i]->DevNum;j++)
	{
		if(DevID == ComDb[i]->DBCfgs[j].DevID)
			return j;
	}
	return 0xffff;
}
INT16U GetNextActDevNo(INT8U Port,INT16U DevNo)
{
	INT8U i;
	i = Port - 1;
	return ((DevNo+1)%ComApp[i]->DevNum);
}
/*BCD转换二进制*/
INT16U BcdToBin(INT16U BCD)
{
        short i;
        i= (BCD&0xf)+(((BCD>>4)&0xf)*10)+(((BCD>>8)&0xf)*100)+(((BCD>>12)&0x7)*1000);
        if(BCD & 0x8000)
                return((~i) + 1);       
        else
                return(i);
}

INT32U BcdToBin8(unsigned char *BCD)
{
        return(((*BCD)&0xf)+((*(BCD)>>4)*10)+((*(BCD+1)&0xf)*100)+((*(BCD+1)>>4)*1000)
        
                +((*(BCD+2)&0xf)*10000)+((*(BCD+2)>>4)*100000)+((*(BCD+3)&0xf)*1000000)+((*(BCD+3)>>4)*10000000));

}

/*二进制转换BCD*/
INT16U  BinToBcd(INT16U i)
{
        return(i%10+((i/10)<<4));
}

/*------------------------------------------------------------------*/
/*函数名称:DLT645RecMISIData()										*/
/*函数功能:接收MISI数据											*/
/*------------------------------------------------------------------*/
void DLT645RecMISIData(INT8U Port, BOOL Flag)
{
	INT16U	i, count;
	
	i = Port - 1;
	count = Readx((INT8U *)&ComLink[i]->RxdBuf[ComLink[i]->RxdTail], RXBUFLEN, Port);
	if (count == 0)
		return ;
	
	lseek(Port, count);
	
	if (Flag)
	{
		ComLink[i]->RxdTail += count;
		DLT645SearchFrame(Port);
	}
}

void DLT645SearchFrame(INT8U Port)
{
	INT8U	i, err, tmp, num;
	i = Port - 1;
	
	while (ComLink[i]->RxdHead < ComLink[i]->RxdTail)
 	{
			if (ComLink[i]->RxdBuf[ComLink[i]->RxdHead] != STARTCODE68)
			{
				ComLink[i]->RxdHead++;
				continue;
			}

 			//找到后,清除无用的缓冲区报文
 			if (ComLink[i]->RxdTail > ComLink[i]->RxdHead)
 			{
 				memcpy (ComLink[i]->RxdBuf, &ComLink[i]->RxdBuf[ComLink[i]->RxdHead], ComLink[i]->RxdTail - ComLink[i]->RxdHead);
 				ComLink[i]->RxdTail -= ComLink[i]->RxdHead;
 				ComLink[i]->RxdHead = 0;
 			}

			ComLink[i]->RxdLength = ComLink[i]->RxdTail - ComLink[i]->RxdHead;
			
			if (ComLink[i]->RxdLength >= 10)
			{
				if (!DLT645HeadFun68(Port))
				{
        	ComLink[i]->RxdHead++;
        	continue;
        }
       	else
       	{
       		num = ComLink[i]->RxdBuf[ComLink[i]->RxdHead+9];
       		if (ComLink[i]->RxdLength >= (num + 12))	//报文收全
					{
						tmp = (INT8U)DLT6465CheckSum((void*)&ComLink[i]->RxdBuf[ComLink[i]->RxdHead], num+10);
						if ((ComLink[i]->RxdBuf[num+10] == tmp)
							&& (ComLink[i]->RxdBuf[num+11] == ENDCODE))
       			{
     						DLT645APP(Port);
     						if (ComLink[i]->RxdTail >= ComLink[i]->RxdHead)
								{
									ComLink[i]->RxdTail -= (num + 12);
									ComLink[i]->RxdHead = 0;
									OSFlagPost(ComDb[i]->Event, FTXNEXT, OS_FLAG_SET, &err);
								}
       			}
   					else
   					{
     						ComLink[i]->RxdHead += (num+12);  
       					if (ComLink[i]->RxdTail > ComLink[i]->RxdHead)
					 			{
					 				ComLink[i]->RxdLength = ComLink[i]->RxdTail - ComLink[i]->RxdHead;
					 				memcpy (ComLink[i]->RxdBuf, &ComLink[i]->RxdBuf[ComLink[i]->RxdHead], ComLink[i]->RxdLength);
					 				ComLink[i]->RxdHead = 0;
					 				ComLink[i]->RxdTail = ComLink[i]->RxdLength;
					 			}
   					}
       		}
       			else
       				break;
       	}
			}
			else
				break;
 				
 		}
 		
}
/*------------------------------------------------------------------*/
/*函数名称:DLT645HeadFun68()											*/
/*函数功能:检测68帧头正确性										*/
/*------------------------------------------------------------------*/
BOOL DLT645HeadFun68(INT8U Port)
{
	INT8U	i;
	
	i = Port - 1;

	if (STARTCODE68 != ComLink[i]->RxdBuf[ComLink[i]->RxdHead])
		return (FALSE);
	if (STARTCODE68 != ComLink[i]->RxdBuf[ComLink[i]->RxdHead + 7])
		return (FALSE);

	return (TRUE);
}

INT8U DLT6465CheckSum(INT8U *Buf,INT8U Num)
{
	INT8U sum = 0;
	while(Num--)
	{
		sum +=*Buf++ & 0xff;
	}
	return sum;

⌨️ 快捷键说明

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