//----------------------start RN8209 地址定义---------------------------------------------------// #define ADSYSCON 0x00 #define ADEMUCON 0x01 #define ADHFConst 0x02 #define ADPStart 0x03 #define ADDStart 0x04 #define ADGPQA 0x05 #define ADGPQB 0x06 #define ADPhsA 0x07 #define ADPhsB 0x08 #define ADQPHSCAL 0x09 #define ADAPOSA 0x0a #define ADAPOSB 0x0b #define ADRPOSA 0x0c #define ADRPOSB 0x0d #define ADIARMSOS 0x0e #define ADIBRMSOS 0x0f #define ADIBGain 0x10 #define ADD2FPL 0x11 #define ADD2FPH 0x12 #define ADDCIAH 0x13 #define ADDCIBH 0x14 #define ADDCUH 0x15 #define ADDCL 0x16 #define ADEMUCON2 0x17 #define ADPFCnt 0x20 #define ADDFcnt 0x21 #define ADIARMS 0x22 #define ADIBRMS 0x23 #define ADURMS 0x24 #define ADUFreq 0x25 #define ADPowerPA 0x26 #define ADPowerPB 0x27 #define ADEnergyP 0x29 #define ADEnergyP2 0x2a #define ADEnergyD 0x2b #define ADEnergyD2 0x2c #define ADEMUStatus 0x2d #define ADSPL_IA 0x30 #define ADSPL_IB 0x31 #define ADSPL_U 0x32 #define ADIE 0x40 #define ADIF 0x41 #define ADRIF 0x42 #define ADSysStatus 0x43 #define ADRData 0x44 #define ADWData 0x45 #define ADDeviceID 0x7f #define WriteEn 0xea //----------------------end RN8209 地址定义-----------------------------------------------// //---start 校表参数文件-------(可根据计量芯片更改) typedef struct { u16 SYSCON; u16 EMUCON; u16 HFConst; u16 PStart; u16 QStart; //10 u16 GPQA; u16 GPQB; u16 IAGain; u16 UGain; u16 IBGain; u16 PhsA; u16 PhsB; u16 QPhsCal; //22 u16 APOSA; u16 APOSB; u16 RPOSA; u16 RPOSB; u16 IARMSOS; //32 u16 IBRMSOS; //34 u16 EMUCON2; float KUrms; // 电压系数 float KIArms; // A通道电流系数 float KIBrms; // B通道电流系数 float KPrms; // 功率系数 u16 RealUI[2]; // 功率显示值,功率大于此值时显示 0.2% u32 RealPw; // 电流显示值,电流大于此值时显示 0.2% u32 ChkSum; u16 RTCDota0; // RTC校正寄存器 u8 TemperAdj[2]; // 高低温补偿值 u8 RTCAdj[4]; // RTC高低温时补偿值 u8 CurAdj; // 自热影响补偿值 u8 OfsetAdjAcVolt[2]; //根据电压调整OFFSET的值 u16 CorrectionTemper; //校表时刻表计的温度 }sDl645FirmParaFile_TypeDef; //58 Byte //---end 校表参数文件-------(可根据计量芯片更改) //---start 计量值瞬时值中转文件------- typedef struct { u8 ChkErrCnt; u32 Pw[2]; //pa,pb u32 UI[3]; // Ia=UI[0] Inal U u16 Frequency; //电网频率,单位: u32 Pulse; //前台脉冲 u16 Pstart; //---电能脉冲--- u32 Pulse_Eg; //脉冲个数 u32 PDirect; //功率方向 u32 ChkSum1; //读出EMU的校表参数校验 // 校表使用参数 u16 RatintU; // 额定电压 u16 RatingI; // 额定电流 u32 TempU; // 当前校正点电压 u32 TempI; // 当前校正点电流 u32 TempPw; // 当前校正点功率 } sDl645FrontTmp_TypeDef; //---end 计量值瞬时值中转文件------- //---start 计量值瞬时值文件------- typedef struct { struct sDl645FrontPubData_TypeDef { u16 U; //---电压---NNN.N u32 Ia; //---电流NNNN.NNNN(电流值要求3整3小,整定值要求2整4小,最高位表示方向)--- u32 In; //---零线电流 sDF09 Pw; //---瞬时有功p u16 Pf; //---功率因数N.NNN--- 最高位表示方向{Pf Pfa Pfb Pfc} u16 Angle; //---相角NNN.N--- u16 Frequency; //---频率NN.NN u32 PPwave; //---一分钟平均功率NN.NNNN u8 Chnsel; u16 Temperature; //---NNN.N 温度 u16 ClockBat; //---NN.NN 电池电压 u32 tWorkBat; //---NNNN 时钟工作时间(分钟) u8 PDirect; //---原功率方向 u16 CfIn; //脉冲输入电平判断 u8 CfTime; // u8 Step; u16 FrontStamp; u16 tMaxI; // 最大电流持续时间,0.5s为单位 u8 SafeCurFlag; // 电流门限不为零标志 } PubData; struct sDl645FrontPriData_TypeDef { u8 Flag; //---工作异常标志--- } PriData; struct sDl645FrontPriPara_TypeDef { u32 PConstE; //有功常数 u16 Crc; } PriPara; } sDl645Front_TypeDef; //---end 计量值瞬时值文件------- //---start 串口通讯变量文件------- typedef struct { u16 EFlag; //通讯状态 u16 RxLen; //接收数据长度 u16 TxLen; u32 TimeOutStamp; //发送数据长度 u8 *pTx; u8 fBps; //波特率变更标志 u8 NewBps; //新波特率 u32 NewBpsStamp; //新速率时标 //u8 TxAddr; u8 RxBuf[MAX_COMPACK_SIZE];//接收缓存 u8 TxBuf[MAX_COMPACK_SIZE];//发送缓存 }sComPack_TypeDef; //---end 通讯变量文件------- /***************************************************************************** ** Function name: fnUSART_RN8209_Init(u8 Cfg) ** ** Description: 计量UART初始化(波特率、数据字节格式控制、发送、接收引脚配置),主控芯片初始化时执行 ** ** Parameters: 波特率 ** ** Returned value: NONE ** ******************************************************************************/ #define PinMode_RN8209RX(x) ( (x == GPIO_MODE_OUT) ? (GPIO->PMA &= 0xfbffffff) : (GPIO->PMA |= 0x04000000) ) // P3.2 #define PinMode_RN8209TX(x) ( (x == GPIO_MODE_OUT) ? (GPIO->PMA &= 0xf7ffffff) : (GPIO->PMA |= 0x08000000) ) // P3.3 void fnUSART_RN8209_Init(u8 Cfg) { u32 ClkDiv; ClkDiv = fnDl645MainClock_Get();//获取系统当前时钟频率 switch(Cfg & 0xE0) { case USART_BPS_600: //600 ClkDiv=ClkDiv/(600*16)-1;//根据系统当前时钟频率与串口通讯速率,计算UART2->BAUD值 break; case USART_BPS_1200: //1200 ClkDiv=ClkDiv/(1200*16)-1; break; case USART_BPS_2400: //2400 ClkDiv=ClkDiv/(2400*16)-1; break; case USART_BPS_4800: //RN8209C仅支持波特率:4800 ClkDiv=ClkDiv/(4800*16)-1; break; case USART_BPS_9600: //9600 ClkDiv=ClkDiv/(9300*16)-1; break; default: ClkDiv=ClkDiv/(2400*16)-1; //2400 break; } //UART2用于RN8209通讯. UART2->BAUD = ClkDiv; UART2->CTRL = (3 << 0) | /* uart enable 使能*/ (3 << 6) | /* data bit: 8 数据位*/ (2 << 8); /* even 偶校验*/ PinMode_RN8209RX(GPIO_MODE_IN);//MCU串口接收引脚配置 PinMode_RN8209TX(GPIO_MODE_OUT);//MCU串口发送引脚配置 return; } /***************************************************************************** ** Function name: USART_ITConfig(u8 ComPort, FunctionalMODE USART_IT, FunctionalState NewState) ** ** Description: 端口管理及工作方式控制函数 ** ** Parameters: ComPort:串口选择(串口0、1、2、3); USART_IT:串口工作方式选择(接收或发送); ** NewState:串口状态选择(使能或关闭) ** ** Returned value: NONE ** ******************************************************************************/ void USART_ITConfig(u8 ComPort, FunctionalMODE USART_IT, FunctionalState NewState) { u8 Compose; Compose=(ComPort<<2)|(USART_IT<<1)|(NewState); switch(Compose) { //----------------RN8209----------------------------- case (SCOM_PORT_RN8209<<2)|(USART_IT_RX<<1)|DISABLE: //RN8209通信口|接收|关闭 UART2->CTRL &=0xffe7; //屏蔽接收中断,屏蔽接收错误中断 UART2->STA = 0x3d; //清接收中断标志及接收错误标志 break; case (SCOM_PORT_RN8209<<2)|(USART_IT_RX<<1)|ENABLE: //RN8209通信口|接收|打开 UART2->CTRL |=0x18; //允许接收中断,允许接收错误中断 UART2->STA = 0x3d; //清接收中断标志及接收错误标志 break; case (SCOM_PORT_RN8209<<2)|(USART_IT_TX<<1)|DISABLE: //RN8209通信口|发送|关闭 UART2->CTRL &=0xfff9; //屏蔽发送中断 UART2->STA = 0x02; //清发送中断标志 break; case (SCOM_PORT_RN8209<<2)|(USART_IT_TX<<1)|ENABLE: //RN8209通信口|发送|打开 UART2->CTRL |=0x06; //屏蔽发送中断 UART2->STA = 0x02; //清发送中断标志 UART2->TXD=*(ComPack[SCOM_PORT_RN8209].pTx++); ComPack[SCOM_PORT_RN8209].TxLen--; break; default: return; } return; } /***************************************************************************** ** Function name:UART2_HANDLER(void) ** ** Description:与RN8209进行底层通讯的串口中断函数,进行RN8209数据的接收及发送 ** ** Parameters: NONE ** ** Returned value: NONE ** ******************************************************************************/ void UART2_HANDLER(void) { u32 status; u8 temp; status = UART2->STA; /* UART error irq 串口错误处理*/ if((UART2->CTRL & 0x10) && (status & 0x3c)) { ComPack[SCOM_PORT_RN8209].RxLen=0; ComPack[SCOM_PORT_RN8209].EFlag=SCOMPK_EFLAG_IDLE; UART2->STA = status; } /* receive data complete irq 接收中断处理*/ if((UART2->CTRL & 0x8) && (status & 0x1)) { temp = UART2->RXD; ComPack[SCOM_PORT_RN8209].RxBuf[ComPack[SCOM_PORT_RN8209].RxLen++]=temp; UART2->STA = 0x1; // clear receive IF } /* transmit data complete irq 发送中断处理*/ if((UART2->CTRL & 0x4) && (status & 0x2)) { if(ComPack[SCOM_PORT_RN8209].TxLen>0) { //for(i=0;i<30;i++) __NOP(); UART2->TXD=*(ComPack[SCOM_PORT_RN8209].pTx++); ComPack[SCOM_PORT_RN8209].TxLen--; UART2->STA = 0x2; } } UART2->STA = status;//清中断标识位 return; } /***************************************************************************** ** Function name:Rn8209Delay(u16 t) ** ** Description:延时函数 ** ** Parameters: t :延时时间 ** ** Returned value: NONE ** ******************************************************************************/ void Rn8209Delay(u16 t) { u16 i; if(Dl645Inactive.PubData.InactiveStamp) return; while(t--) { for (i = 0;i < 400;i++) ; WDT->EN = 0xbb; } } /***************************************************************************** ** Function name:fnRN8209_Write(u8 wReg,u8 *pBuf,u8 ucLen) ** ** Description:写RN8209寄存器 ** ** Parameters:wReg 寄存器地址,*pBuf待写入值的存放地址,ucLen:待写入值的长度 ** ** Returned value: 操作标识-成功或失败 ** ******************************************************************************/ ErrorStatus fnRN8209_Write(u8 wReg,u8 *pBuf,u8 ucLen) { u8 i,j,temp,chksum,Repeat; ErrorStatus err; if( (ucLen == 0) || (ucLen > 4) ) return(ERROR); for( Repeat =2; Repeat != 0 ; Repeat--) { err = SUCCESS; ComPack[SCOM_PORT_RN8209].pTx=&ComPack[SCOM_PORT_RN8209].TxBuf[0]; //写数据前,先发送命令字节,命令字节的最高位bit[7]=0:读操作;1:写操作;bit[6:0]为待操作寄存的地址 temp =wReg|0x80;//待操作寄存器地址最高位或1,使命令字节为写命令 *(ComPack[SCOM_PORT_RN8209].pTx++)=temp; chksum = temp; for(i = ucLen; i > 0;i-- ) { *(ComPack[SCOM_PORT_RN8209].pTx++)=pBuf[i-1]; //向RN8209发送数据 chksum +=pBuf[i-1]; } chksum = ~chksum; *(ComPack[SCOM_PORT_RN8209].pTx++)=chksum; ComPack[SCOM_PORT_RN8209].TxLen = ucLen+2; ComPack[SCOM_PORT_RN8209].pTx=&ComPack[SCOM_PORT_RN8209].TxBuf[0]; USART_ITConfig(SCOM_PORT_RN8209 , USART_IT_TX, ENABLE); //发送使能 Rn8209Delay(30);//等待串口发送完成 //RN8209写使能或写保护、读写入WData寄存器检查(是否正确写入)----------------------- ComPack[SCOM_PORT_RN8209].pTx=&ComPack[SCOM_PORT_RN8209].TxBuf[0]; if(wReg == 0xEA) {//RN8209写使能或写保护 *(ComPack[SCOM_PORT_RN8209].pTx)=0X43; } else {//读写入WData寄存器检查 *(ComPack[SCOM_PORT_RN8209].pTx)=wReg; } ComPack[SCOM_PORT_RN8209].TxLen = 1; ComPack[SCOM_PORT_RN8209].RxLen=0; USART_ITConfig(SCOM_PORT_RN8209 , USART_IT_RX, ENABLE); //接收使能 USART_ITConfig(SCOM_PORT_RN8209 , USART_IT_TX, ENABLE); //发送使能 memset(&ComPack[SCOM_PORT_RN8209].RxBuf[0] , 0x00 , 10); Rn8209Delay(25);//等待通讯完成 fnWDT_Restart(); j = 0; if(wReg == 0xEA) {//RN8209写使能或写保护 if(pBuf[0] == 0XE5) {//RN8209写使能 temp = ComPack[SCOM_PORT_RN8209].RxBuf[0]; if(!(temp&0x10)) err = ERROR; } else if(pBuf[0] == 0XDC) {//RN8209写保护 temp = ComPack[SCOM_PORT_RN8209].RxBuf[0]; if(temp&0x10) err = ERROR; } } else { //读写入WData寄存器检查(接收数据ComPack[SCOM_PORT_RN8209].RxBuf[j++];发送数据pBuf[i-1]) for(i = ucLen; i > 0;i--) { temp = ComPack[SCOM_PORT_RN8209].RxBuf[j++]; if((wReg == 0)&&(i==2)) temp = 0;//异常处理 if(temp != pBuf[i-1]) { err = ERROR; break; } } } fnWDT_Restart(); if(err == SUCCESS) break; fnScomPk_Init(SCOM_PORT_RN8209); } USART_ITConfig(SCOM_PORT_RN8209 , USART_IT_TX, DISABLE); //发送使能关闭 return(err); } /***************************************************************************** ** Function name:fnRN8209_Read(u8 wReg,u8 *pBuf,u8 ucLen) ** ** Description:读RN8209寄存器 ** ** Parameters:wReg 寄存器地址,*pBuf读出值的存放地址,ucLen:待读值的长度 ** ** Returned value: 操作标识-成功或失败 ** ******************************************************************************/ ErrorStatus fnRN8209_Read(u8 wReg,u8 *pBuf,u8 ucLen) { u8 i,temp,Repeat; u8 j=0; u8 chksum=0; ErrorStatus err; if(ucLen == 0) return(ERROR); for( Repeat=2; Repeat != 0 ; Repeat--) { err = SUCCESS; temp = wReg ; chksum=wReg; j = 0; ComPack[SCOM_PORT_RN8209].pTx=&ComPack[SCOM_PORT_RN8209].TxBuf[0]; //读数据前,先发送命令字节,命令字节的最高位bit[7]=0:读操作;1:写操作;bit[6:0]为待操作寄存的地址 *(ComPack[SCOM_PORT_RN8209].pTx)=temp; ComPack[SCOM_PORT_RN8209].TxLen = 1; USART_ITConfig(SCOM_PORT_RN8209 , USART_IT_RX, ENABLE); //接收使能 USART_ITConfig(SCOM_PORT_RN8209 , USART_IT_TX, ENABLE); //发送使能 memset(&ComPack[SCOM_PORT_RN8209].RxBuf[0] , 0x00 , 10); Rn8209Delay(25);//延迟,以等待数据接收完成 fnWDT_Restart(); for(i = ucLen; i > 0;i--) { pBuf[i-1] = ComPack[SCOM_PORT_RN8209].RxBuf[j++]; //将接收到的数据保存到数组pBuf[] chksum += pBuf[i-1];//计算接收数据的校验和 } chksum = ~chksum; temp=ComPack[SCOM_PORT_RN8209].RxBuf[j++]; if(temp!=chksum) {//若校验和错误,清接收数据 err = ERROR; for(i = ucLen; i > 0;i--) pBuf[i-1] = 0; } if(err == SUCCESS) break; fnScomPk_Init(SCOM_PORT_RN8209); } USART_ITConfig(SCOM_PORT_RN8209 , USART_IT_TX, DISABLE); //发送使能关闭 ComPack[SCOM_PORT_RN8209].RxLen=0; // return(err); } /***************************************************************************** ** Function name: fnDl645_ComInitRN8209(void) ** ** Description: 清计量(校表)参数函数,清RN8209寄存器 ** ** Parameters: NONE ** ** Returned value: NONE ** ******************************************************************************/ void fnDl645_ComInitRN8209(void) { Dl645FirmPara.HFConst = 0x1000; Dl645FirmPara.PStart = 0x0060; Dl645FirmPara.QStart = 0x0120; Dl645FirmPara.GPQA = 0x0000; Dl645FirmPara.GPQB = 0x0000; Dl645FirmPara.PhsA= 0x0000; Dl645FirmPara.PhsB= 0x0000; Dl645FirmPara.QPhsCal = 0x0000; Dl645FirmPara.APOSA = 0x0000; Dl645FirmPara.APOSB = 0x0000; Dl645FirmPara.RPOSA = 0x0000; Dl645FirmPara.RPOSB = 0x0000; Dl645FirmPara.IARMSOS = 0x0000; Dl645FirmPara.IBRMSOS = 0x0000; Dl645FirmPara.IBGain = 0x0000; //Dl645FirmPara.KUrms= 0x00000000; //Dl645FirmPara.KIArms= 0x00000000; //Dl645FirmPara.KIBrms= 0x00000000; Dl645FirmPara.KPrms= 0x00000000; Dl645RN8209DataComm.ucTemp8 =0XE5; //if(fnRN8209_Write( 0xEA , Dl645RN8209DataComm.ucTempBuf , 1 ) == ERROR) return ; //写使能 fnRN8209_Write( 0xEA , Dl645RN8209DataComm.ucTempBuf , 1 ); //if(fnRN8209_Write( 0x00 , (u8 *)&Dl645FirmPara.SYSCON , 2 ) == ERROR) return ; //写系统控制寄存器 //if(fnRN8209_Write( 0x01 , (u8 *)&Dl645FirmPara.EMUCON , 2 ) == ERROR) return ; //写计量控制寄存器 if(fnRN8209_Write( ADHFConst , (u8 *)&Dl645FirmPara.HFConst , 2 ) == ERROR) return ; if(fnRN8209_Write( ADPStart , (u8 *)&Dl645FirmPara.PStart , 2 ) == ERROR) return ; if(fnRN8209_Write( ADDStart , (u8 *)&Dl645FirmPara.QStart , 2 ) == ERROR) return ; if(fnRN8209_Write( ADGPQA , (u8 *)&Dl645FirmPara.GPQA , 2 ) == ERROR) return; //写功率增益寄存器 if(fnRN8209_Write( ADGPQB , (u8 *)&Dl645FirmPara.GPQB , 2 ) == ERROR) return; //写功率增益寄存器 if(fnRN8209_Write( ADPhsA , (u8 *)&Dl645FirmPara.PhsA , 1 ) == ERROR) return; //写相位校正寄存器 if(fnRN8209_Write( ADPhsB , (u8 *)&Dl645FirmPara.PhsB , 1 ) == ERROR) return; //写相位校正寄存器 if(fnRN8209_Write( ADQPHSCAL , (u8 *)&Dl645FirmPara.QPhsCal , 2 ) == ERROR) return; if(fnRN8209_Write( ADAPOSA , (u8 *)&Dl645FirmPara.APOSA , 2 ) == ERROR) return; if(fnRN8209_Write( ADAPOSB , (u8 *)&Dl645FirmPara.APOSB , 2 ) == ERROR) return; if(fnRN8209_Write( ADRPOSA , (u8 *)&Dl645FirmPara.RPOSA , 2 ) == ERROR) return; if(fnRN8209_Write( ADRPOSB , (u8 *)&Dl645FirmPara.RPOSB , 2 ) == ERROR) return; if(fnRN8209_Write( ADIARMSOS , (u8 *)&Dl645FirmPara.IARMSOS , 2 ) == ERROR) return; if(fnRN8209_Write( ADIBRMSOS , (u8 *)&Dl645FirmPara.IBRMSOS , 2 ) == ERROR) return; if(fnRN8209_Write( ADIBGain , (u8 *)&Dl645FirmPara.IBGain , 2 ) == ERROR) return; if(fnRN8209_Write( ADEMUCON2 , (u8 *)&Dl645FirmPara.EMUCON2 , 2 ) == ERROR) return; fnWDT_Restart(); Dl645RN8209DataComm.ucTemp8 =0XDC; fnRN8209_Write( 0xEA , Dl645RN8209DataComm.ucTempBuf , 1 ) ; fnDl645File_Write(Dl645FileId_FirmPara,Dl645FileItemInfoOffAddr_FirmPara_HFConst,(u8 *)&Dl645FirmPara.HFConst,42); } /***************************************************************************** ** Function name: fnEMU_Init(void) ** ** Description: 计量EMU初始化函数,初始化RN8209寄存器 ** ** Parameters: NONE ** ** Returned value: NONE ** ******************************************************************************/ void fnEMU_Init(void) { //写计量芯片相关配置 Dl645FirmPara.EMUCON2 = 0x300; Dl645RN8209DataComm.ucTemp8 =0XE5; //if(fnRN8209_Write( 0xEA , Dl645RN8209DataComm.ucTempBuf , 1 ) == ERROR) return ; //写使能 fnRN8209_Write( 0xEA , Dl645RN8209DataComm.ucTempBuf , 1 ); //if(fnRN8209_Write( ADSYSCON , (u8 *)&Dl645FirmPara.SYSCON , 2 ) == ERROR) return ; //写系统控制寄存器 //if(fnRN8209_Write( ADEMUCON , (u8 *)&Dl645FirmPara.EMUCON , 2 ) == ERROR) return ; //写计量控制寄存器 if(fnRN8209_Write( ADHFConst , (u8 *)&Dl645FirmPara.HFConst , 2 ) == ERROR) return ; if(fnRN8209_Write( ADPStart , (u8 *)&Dl645FirmPara.PStart , 2 ) == ERROR) return ; if(fnRN8209_Write( ADDStart , (u8 *)&Dl645FirmPara.QStart , 2 ) == ERROR) return ; if(fnRN8209_Write( ADGPQA , (u8 *)&Dl645FirmPara.GPQA , 2 ) == ERROR) return; //写功率增益寄存器 if(fnRN8209_Write( ADGPQB , (u8 *)&Dl645FirmPara.GPQB , 2 ) == ERROR) return; //写功率增益寄存器 if(fnRN8209_Write( ADPhsA , (u8 *)&Dl645FirmPara.PhsA , 1 ) == ERROR) return; //写相位校正寄存器 if(fnRN8209_Write( ADPhsB , (u8 *)&Dl645FirmPara.PhsB , 1 ) == ERROR) return; //写相位校正寄存器 if(fnRN8209_Write( ADQPHSCAL , (u8 *)&Dl645FirmPara.QPhsCal , 2 ) == ERROR) return; if(fnRN8209_Write( ADAPOSA , (u8 *)&Dl645FirmPara.APOSA , 2 ) == ERROR) return; if(fnRN8209_Write( ADAPOSB , (u8 *)&Dl645FirmPara.APOSB , 2 ) == ERROR) return; if(fnRN8209_Write( ADRPOSA , (u8 *)&Dl645FirmPara.RPOSA , 2 ) == ERROR) return; if(fnRN8209_Write( ADRPOSB , (u8 *)&Dl645FirmPara.RPOSB , 2 ) == ERROR) return; if(fnRN8209_Write( ADIARMSOS , (u8 *)&Dl645FirmPara.IARMSOS , 2 ) == ERROR) return; if(fnRN8209_Write( ADIBRMSOS , (u8 *)&Dl645FirmPara.IBRMSOS , 2 ) == ERROR) return; if(fnRN8209_Write( ADIBGain , (u8 *)&Dl645FirmPara.IBGain , 2 ) == ERROR) return; if(fnRN8209_Write( ADEMUCON2 , (u8 *)&Dl645FirmPara.EMUCON2 , 2 ) == ERROR) return; fnWDT_Restart(); Dl645RN8209DataComm.ucTemp8 =0XDC; fnRN8209_Write( 0xEA , Dl645RN8209DataComm.ucTempBuf , 1 ) ; //关闭写使能 } /***************************************************************************** ** Function name: fnDl645Front_Init(void) ** ** Description: 计量模块初始化函数,将计量用到的RAM数据进行初始化 ** ** Parameters: NONE ** ** Returned value: NONE ** ******************************************************************************/ void fnDl645Front_Init(void) { u8 i,j; u32 ChkSum; Dl645Front.PriData.Flag |= FRONT_FLAG_RN8209RST;//置RN8209初始化标识位 memset(&Dl645FrontTmp , 0 , sizeof(sDl645FrontTmp_TypeDef) );//清计量用到的RAM数据 memset(&Dl645Front , 0 , sizeof(sDl645Front_TypeDef) );//清计量用到的RAM数据 //写入校表寄存器,检查校验是否正确。正确退出,不正确再次写入。最多循环写入次数5次。 fnDl645File_Read(Dl645FileId_FirmPara , 0 , (u8 *)&Dl645FirmPara , sizeof(sDl645FirmParaFile_TypeDef) );//读E2中保存的校表参数 Dl645FrontTmp.ChkSum1 = Dl645FirmPara.ChkSum; for(i=0;i<5;i++) { fnEMU_Init(); SystemDelay(10); ChkSum = 0; for(j=0;j<5;j++) { fnRN8209_Read( ADEMUStatus , (u8 *)&ChkSum , 3 ) ; if(!(ChkSum & 0x010000)) break; SystemDelay(10); } fnWDT_Restart(); ChkSum = ChkSum & 0x0000ffff; if(Dl645FrontTmp.ChkSum1 == ChkSum) { Dl645Front.PriData.Flag &= ~FRONT_FLAG_RN8209RST; break; } } if(i>=5) {//若校验值连续5次错误,则重新计算校验值 Dl645FirmPara.ChkSum = 0; SystemDelay(1); Dl645FirmPara.ChkSum = ChkSum & 0x0000ffff; Dl645FrontTmp.ChkSum1 = Dl645FirmPara.ChkSum; fnDl645File_Write(Dl645FileId_FirmPara,Dl645FileItemInfoOffAddr_FirmPara_ChkSum,(u8 *)&Dl645FirmPara.ChkSum,4); } } /***************************************************************************** ** Function name: fnDl645Front_Exec(void) ** ** Description: 从计量芯片读取数据(电压、电流、功率、脉冲数),及电压、电流、频率、功率因素计算 ** ** Parameters: NONE ** ** Returned value: NONE ** ******************************************************************************/ void fnDl645Front_Exec(void) { u8 i; u32 TempU,TempI,TempIn; u32 TempStatus; u16 TempAngle; u8 PFlag; if(Dl645Front.PriData.Flag & FRONT_FLAG_RN8209RST)//RN8209复位 { fnDl645Front_Init(); Dl645Front.PriData.Flag &= ~FRONT_FLAG_RN8209RST; return; } //读计量状态及校验和 TempStatus = 0; fnRN8209_Read( 0x2d , (u8 *)&TempStatus , 3 ) ; if(!(TempStatus & 0x010000)) {//校表数据校验和计算已完成,校验值可用 if(Dl645FrontTmp.ChkSum1 == (TempStatus&0x0000ffff)) {//校验值正确,清校验错误次数 Dl645FrontTmp.ChkErrCnt = 0 ; } else { Dl645FrontTmp.ChkErrCnt++; if(Dl645FrontTmp.ChkErrCnt > 3) {//校验错误次数大于3次后,复位RN8209 Dl645Front.PriData.Flag |= FRONT_FLAG_RN8209RST; Dl645FrontTmp.ChkErrCnt = 0 ; } return; } } //判断功率方向 if(TempStatus & 0x020000) { Dl645Front.PubData.PDirect = INVERSION ; } //判断功率方向是反的。 else { Dl645Front.PubData.PDirect = POSITIVE ; } //读电压、电流到缓冲区,读数为负进行处理 for(i = 0 ; i < 3 ; i++) { Dl645FrontTmp.UI[i] = 0;//清电压、电流变量 fnRN8209_Read( 0x22+i , (u8 *)&Dl645FrontTmp.UI[i] , 3 ) ; if(Dl645FrontTmp.UI[i]&0x00800000) Dl645FrontTmp.UI[i]=0; } //读频率 fnRN8209_Read( 0x25 , (u8 *)&Dl645FrontTmp.Frequency , 2 ) ; //读功率到缓冲区,读数为负进行处理 fnRN8209_Read( 0x26 , (u8 *)&Dl645FrontTmp.Pw[0] , 4 ) ; fnRN8209_Read( 0x27 , (u8 *)&Dl645FrontTmp.Pw[1] , 4 ) ; if(Dl645FrontTmp.Pw[0]&0x80000000) { Dl645FrontTmp.Pw[0]=(~Dl645FrontTmp.Pw[0])+1;PFlag = 1; } else PFlag = 0; //计算功率 Dl645Front.PubData.Pw = fnDFConver_Hex32ToDF09((s32)((Dl645FrontTmp.Pw[0])*((Dl645FirmPara.KPrms)))); if(PFlag) Dl645Front.PubData.Pw.S = 1; //电流电压计算 Dl645Front.PubData.U = 0x7fff&(fnDFConver_Bcd16To16((s16)(Dl645FrontTmp.UI[2]/(10*(Dl645FirmPara.KUrms))))); //电压 TempI = (s32)(Dl645FrontTmp.UI[0]/(Dl645FirmPara.KIArms)); TempIn = (s32)(Dl645FrontTmp.UI[1]/(Dl645FirmPara.KIBrms)); Dl645Front.PubData.Ia = fnDFConver_Bcd32To32(TempI); Dl645Front.PubData.In = fnDFConver_Bcd32To32(TempIn); if(PFlag) Dl645Front.PubData.Ia |= 0x80000000; //功率有效值计算,功率因数计算 //计算功率因数 TempU &=0x00ffffff; if(TempU&0x00800000) TempU=((~TempU)&0x00ffffff)+1; Dl645Front.PubData.Pf = fnHexToBcd_u16((u16)((float)TempU/8388.608)); Dl645Front.PubData.Angle= fnHexToBcd_u16(TempAngle*3600/32768); //功率小于0.0030,清零,功率因数置0.999 if(((Dl645Front.PubData.Pw.Dat2&0x7f)==0)&&(Dl645Front.PubData.Pw.Dat1==0)&&(Dl645Front.PubData.Pw.Dat0<0x30)) { Dl645Front.PubData.Pw.Dat0 = 0; Dl645Front.PubData.Pw.Dat1 = 0; Dl645Front.PubData.Pw.Dat2 = 0; } //电流小于起动电流,清零 if((Dl645Front.PubData.Ia&0x7fffffff) < 0x00000150) {Dl645Front.PubData.Ia = 0;Dl645Front.PubData.Pf = 0x0999;} if((Dl645Front.PubData.In&0x7fffffff) < 0x00000150) Dl645Front.PubData.In = 0; //电压频率计算 Dl645Front.PubData.Frequency = fnHexToBcd_u16((u16)(((u32)357954500)/((u32)8*Dl645FrontTmp.Frequency))); if((Dl645Front.PubData.Ia&0x7fffffff) > 0x00550000) { if(Dl645Front.PubData.tMaxI < 2405) Dl645Front.PubData.tMaxI++; } else Dl645Front.PubData.tMaxI = 0; if(Dl645Front.PubData.Pw.S) Dl645Front.PubData.Pf |=0x8000; //读电能脉冲,加入脉冲计数器 Dl645FrontTmp.Pulse = 0; fnRN8209_Read( 0x2a , (u8 *)&Dl645FrontTmp.Pulse , 3 ) ; if(Dl645FrontTmp.Pulse > 100) Dl645FrontTmp.Pulse = 0; //容错,脉冲个数过大,清除 Dl645FrontTmp.Pulse_Eg+=Dl645FrontTmp.Pulse; #if DL645SOFT_DEBUG Dl645FrontTmp.Pulse_Eg+=1; #endif }