#include "../main/SystemInclude.h" //============================================================================== u8 Total[ACC_MAX],Dis2[20]; u64 flowTotalBuffer; u32 lastRemaining, AccComputeTimeBase; u16 totalPulse; u8 MemoryPointer; u16 flowAccCumulationRemaining, samplingIntervalForTotal; /******************************************************************************/ void ReleaseTotalToDisArray(void) { Dis2[0] = Total[0] >> 4; Dis2[1] = Total[0] & 0x0f; Dis2[2] = Total[1] >> 4; Dis2[3] = Total[1] & 0x0f; Dis2[4] = Total[2] >> 4; Dis2[5] = Total[2] & 0x0f; Dis2[6] = Total[3] >> 4; Dis2[7] = Total[3] & 0x0f; Dis2[8] = Total[4] >> 4; Dis2[9] = Total[4] & 0x0f; Dis2[10] = Total[5] >> 4; Dis2[11] = Total[5] & 0x0f; Dis2[12] = Total[MIN_BIT] >> 4; Dis2[13] = Total[MIN_BIT] & 0x0f; } /******************************************************************************/ void ReleaseToIntAndDecimalBuf(void) { u16 I; flowTotalBuffer = 0; for(I=0; I<=ACC_DOT6; I++) { flowTotalBuffer *= 10; flowTotalBuffer += Dis2[I]; } } /******************************************************************************/ void ReleaseToIntAndDecimalBufForUart(void) { u16 I; u16 DotStartBit; flowAccumulationInteger = 0; flowAccumulationDecimal = 0; // Update V2006 DotStartBit = ACC_DOT1; switch(AccComUnit) { case ML: DotStartBit = ACC_DOT4; break; case SL: if(FR_STD_UNIT == SCCM) DotStartBit = ACC_DOT1; else DotStartBit = ACC_DOT4; break; //case NM3: DotStartBit = ACC_DOT1; break; //case SCF: DotStartBit = ACC_DOT1; break; //case PPM: lastUnit = (float)ONE_PPM_TO_STD_ACC; break; //case KG: DotStartBit = ACC_DOT1; break; default: ; } #ifndef ACC_INT_7BIT #pragma message("[undefined] ACC_INT_7BIT") #elif(ACC_INT_7BIT) I = DotStartBit - 7; #endif #ifndef ACC_INT_6BIT #pragma message("[undefined] ACC_INT_6BIT") #elif(ACC_INT_6BIT) I = DotStartBit - 6; #endif #ifndef ACC_INT_8BIT #pragma message("[undefined] ACC_INT_8BIT") #elif(ACC_INT_8BIT) I = DotStartBit - 8; #endif //---------------------------------------------------------------------------- for(; I REC_DEPTH) MemoryPointer = 0; if (WriteCounter > REC_DEPTH) return 1; blockAddr = REC_BASE + MemoryPointer * REC_WIDTH; WriteMultiByteToFRAM(blockAddr,Total,7); ReadMultiByteFromFRAM(blockAddr,temp,7); for(I=0; I < (u16)BLOCK_WIDTH; I++) { if(temp[I] != Total[I]) goto FRAMWriteRepeat; } blockAddr += BLOCK2_START; WriteMultiByteToFRAM(blockAddr,Total,7); ReadMultiByteFromFRAM(blockAddr,temp,7); for(I=0; I 0x09) return false; block1[I] &= 0xf0; if(block1[I] > 0x90) return false; } return true; } /******************************************************************************/ // Routines for flow calculations u16 RetrieveLastAccumulationFromFRAM(void) { u32 voltPartA, tempPartA; u16 voltPartB, tempPartB; unsigned char I, max_g; unsigned char good_ind[REC_DEPTH+1]; if(ReadFRAMDeviceID()) return 0; //find EPROMPointer with good data max_g = 0; for(I = 0; I <= REC_DEPTH; I++) { if(FRAMCheckSaveTotalFlow(I)) { good_ind[max_g] = I; max_g++; } } if(max_g == 0) return 0; // among all the valid data, get the largest one voltPartA = 0; voltPartB = 0; MemoryPointer = 0; for(I = 0; I < max_g; I++) { ReadMultiByteFromFRAM(REC_BASE + (u16)good_ind[I]* REC_WIDTH, Total, 7); //tempPartA = make32(Total[0],Total[1],Total[2],Total[3]); //tempPartB = make16(Total[4],Total[5]); tempL.Byte[3] = Total[0]; tempL.Byte[2] = Total[1]; tempL.Byte[1] = Total[2]; tempL.Byte[0] = Total[3]; tempPartA = tempL.DWord; tempL.Byte[1] = Total[4]; tempL.Byte[0] = Total[5]; tempPartB = tempL.Word[0]; if(voltPartA > tempPartA) continue; else if(voltPartA == tempPartA) { if(voltPartB > tempPartB) continue; } voltPartA = tempPartA; voltPartB = tempPartB; MemoryPointer = good_ind[I]; } ReadMultiByteFromFRAM(REC_BASE + (u16)MemoryPointer* REC_WIDTH, Total, 7); ReleaseTotalToDisArray(); ReadMultiByteFromFRAM(REC_PULSE_REMAINING+ MemoryPointer * PULSE_REMAINING_WIDTH, tempDev.Byte, PULSE_REMAINING_WIDTH); if(tempDev.Byte[PULSE_REMAINING_CRC] != CRC8(tempDev.Byte, PULSE_REMAINING_CRC)) lastRemaining = 0; else lastRemaining = tempDev.DWord[0]; //ReadMultiByteFromFRAM(PULSE_COUNTER, tempDev.Byte, PULSE_COUNTER_WIDTH); //if(tempDev.Byte[PULSE_COUNTER_CRC] != CRC8(tempDev.Byte, PULSE_COUNTER_CRC)) pulseCounter = 0; //else pulseCounter = tempDev.DWord[0]; flowAccCumulationRemaining = 0; //lastRemaining = 0; Total[MIN_BIT] = 0; return 1; } /******************************************************************************/ // Routines for flow calculations void RetrieveLastAccumulation(void) { u16 I; u8 temp[HISTORY_WIDTH]; if(RetrieveLastAccumulationFromFRAM()) return; flowAccCumulationRemaining = 0; //pulseCounter = 0; lastRemaining = 0; //=========================================================================== #ifndef REC_HISTORY_DATA #pragma message("[undefined] REC_HISTORY_DATA") #elif(REC_HISTORY_DATA) if(ReadRecentHistoryData(temp)) { Total[0] = temp[5]; Total[1] = temp[6]; Total[2] = temp[7]; Total[3] = temp[8]; Total[4] = temp[9]; Total[5] = temp[10]; Total[CRC_CHK] = CRC8(Total, 6); ReleaseTotalToDisArray(); return; } #endif //=========================================================================== #ifndef REC_DATE_DATA #pragma message("[undefined] REC_DATE_DATA") #elif(REC_DATE_DATA) if(ReadRecentDateAccData(temp)) { Total[0] = temp[5]; Total[1] = temp[6]; Total[2] = temp[7]; Total[3] = temp[8]; Total[4] = temp[9]; Total[5] = temp[10]; Total[CRC_CHK] = CRC8(Total, 6); ReleaseTotalToDisArray(); } #endif for (I = 0; I < CRC_CHK; I++) Total[I] = 0; Total[CRC_CHK] = CRC8(Total, CRC_CHK); ReleaseTotalToDisArray(); } /******************************************************************************/ void BcdIncOperate(u8 *addendA, u8 *addendB) { u16 Symbol = 0; for(u16 I = 13; ; I--) { addendA[I] += addendB[I]; addendA[I] += Symbol; if(addendA[I] >= 10) { Symbol = 1; addendA[I] -= 10; } else Symbol = 0; if(I==0) break; } } /******************************************************************************/ void BcdDecOperate(u8 *minuend, u8 *subtrahend) { for(u16 I=13; I>0 ; I--){ if(minuend[I] >= subtrahend[I]) minuend[I] -= subtrahend[I]; else { minuend[I] += 10; minuend[I] -= subtrahend[I]; subtrahend[I-1]++; } } } /******************************************************************************/ // compute acc flowrate //void ComputeFlowRateToTotal(void) void ComputeFlowRateToTotal(void) { u32 tempInt; u8 tempF[14]; // V2004 // FRUnitForHour: 放大1000倍 // 总流量: 若标定单位:SLPM, NCMH // [8位整数模式]总共计算14位: 12345678.123456,总共6位小数,流量需放大1000倍,保存 12345678.1234 4位小数,最后2位56不参与校验及保存 // [8位整数模式]流量单位为SLPM,NCMH时,最小单位 1mL // [8位整数模式]Flow Unit = SLPM: (((Flow*60)/1000)*1000)/TimeBase // [8位整数模式]Flow Unit = NCMH: (Flow*1000)/TimeBase // [6位整数模式]总共计算14位: 123456.78123456,总共8位小数,流量需放大100000倍,保存 123456.781234 6位小数,最后2位56不参与校验及保存 // if FR_STD_UNIT = SCCM, ACC_UNIT = SL, 12345678.123456 SL // if FR_STD_UNIT = SLPM, ACC_UNIT = NM3, 12345678.123456 NM3 // if FR_STD_UNIT = NCMH, ACC_UNIT = NM3, 12345678.123456 NM3 // 如果流量单位和总量单位在同一数量单位上,则需要放大1000 /****************************************************************************/ // 最大流量判断: /****************************************************************************/ // 保证位数计算不超出 // Step 1: A = Flow / (time 基数) // Step 2: B = Flow - A * (time 基数) // Step 3: B *= 1000; A *= 1000; // 流量放大 // Step 4: B += flowAccCumulationRemaining; // 上次计算剩余 // Step 5: C = B/(time 基数) // Step 6: A += C (增加总量);flowAccCumulationRemaining = B-C*(time 基数) tmpIA = ConvertTimeBaseAndUnit(flowComUnit, samplingIntervalForTotal); //------------------------------------------------------------------------------ #ifndef ENABLE_FLOW_GAIN #pragma message("[undefined] ENABLE_FLOW_GAIN") #elif(ENABLE_FLOW_GAIN) if(tmpIA < calibFlowGain) AccComputeTimeBase *= (u32)calibFlowGain; else tmpIA /= calibFlowGain; #endif //------------------------------------------------------------------------------ tempInt = (u32)flowRate/(u32)AccComputeTimeBase; tmpLB = flowRate - tempInt*AccComputeTimeBase; tempInt *= (u32)tmpIA; tmpLB = tmpLB*(u32)tmpIA + flowAccCumulationRemaining; tmpLA = tmpLB/(u32)AccComputeTimeBase; tempInt += tmpLA; flowAccCumulationRemaining = tmpLB - tmpLA*(u32)AccComputeTimeBase; // 确定已保存的总量 // Determine the total flow if(Total[CRC_CHK] != CRC8(Total, 6)) RetrieveLastAccumulation(); ReleaseTotalToDisArray(); tempF[0] = 0; tempF[1] = 0; tempF[2] = 0; tempF[3] = 0; //------------------------------------------------------------------------------ #ifndef ENABLE_ACC_GAIN #pragma message("[undefined] ENABLE_ACC_GAIN") #elif(ENABLE_ACC_GAIN) if(currentMode.Bit.CalibMode) ConvertHEXToBCDArray(tempInt, &tempF[4], 10, HIGH_FIRST); else ConvertHEXToBCDArray(tempInt*102/100), &tempF[4], 10, HIGH_FIRST); #else ConvertHEXToBCDArray(tempInt, &tempF[4], 10, HIGH_FIRST); #endif //------------------------------------------------------------------------------ // V2004 #ifndef ENABLE_ACC_DEC_COMPUTE #pragma message("[undefined] ENABLE_ACC_DEC_COMPUTE") #elif(ENABLE_ACC_DEC_COMPUTE) u16 Symbol, I; if(Dis2[0] != 0) BcdIncOperate(Dis2, tempF); else { if(CompareAcc(Dis2, tempF)) { BcdDecOperate(tempF, Dis2); Dis2[0] = 1; } else BcdDecOperate(Dis2, tempF); } tempF[0] = 0; tempF[1] = 0; tempF[2] = 0; tempF[3] = 0; ConvertHEXToBCDArray(alarmAcc, &tempF[4], 10, HIGH_FIRST); //检验码 isAlarmAcc = CompareAcc(Dis2, tempF) #else BcdIncOperate(Dis2, tempF); #endif //------------------------------------------------------------------------------ SendToTotalArray(); Total[CRC_CHK] = CRC8(Total, 6); //------------------------------------------------------------------------------ #ifndef ENABLE_ACCPULSE #pragma message("[undefined] ENABLE_ACCPULSE") #elif(ENABLE_ACCPULSE) lastRemaining += (u32)tempInt; totalPulse = (u16)(lastRemaining / unitPerPulse); lastRemaining -= (u32)totalPulse * (u32)unitPerPulse; if(totalPulse > MaxPulseOutput[samplingIntervalForTotal]) totalPulse = MaxPulseOutput[samplingIntervalForTotal]; #endif //------------------------------------------------------------------------------ #ifndef REC_ACC_PER #pragma message("[undefined] REC_ACC_PER") #elif(REC_ACC_PER) FRAMWriteTotal(); #endif } /******************************************************************************/ void ReadACCFRByCom(void) { u16 I; for(I=0; I<12; I++) MBBuf.RxPointer[MBBuf.Index++] = Dis2[I]+0x30; MBBuf.DataByte = 12; ModbusVariablePointerDec(); } /******************************************************************************/ void SetupACCArray(void) { u16 I; lastRemaining = 0; //pulseCounter = 0; flowAccCumulationRemaining = 0; SendToTotalArray(); ReleaseToIntAndDecimalBufForUart(); #ifndef REC_ACC_PER #pragma message("[undefined] REC_ACC_PER") #elif(REC_ACC_PER) for(I=0; I <= REC_DEPTH; I++) FRAMWriteTotal(); #endif } /******************************************************************************/ void WriteACCFRByCom(void) { MBBuf.DataByte = 12; if(MBBuf.ByteNumber < 12) { MBBuf.ByteNumber = 0; MBBuf.BusError = ILLEGAL_DATA_VALUE; return; } u8 I, K; for(I=0; I<12; I++) { K = MBBuf.RxPointer[MBBuf.Index++]; if(K == 0x20) Dis2[I] = 0; else if((K < 0x30) || (K > 0x39)) { MBBuf.BusError = ILLEGAL_DATA_VALUE; MBBuf.ByteNumber = 0; return; } else Dis2[I] = K & 0x0f; } Dis2[12] = 0; Dis2[13] = 0; SetupACCArray(); } /******************************************************************************/ void ClearACC(void) { u8 I; for(I=0; I<14; I++) Dis2[I] = 0; SetupACCArray(); } /******************************************************************************/ u16 CompareAcc(u8 *compaerA, u8 *compaerB) { if(compaerA[0] != 0) return 1; for(u16 I=1; I<14; I++) { if(compaerA[I] > compaerB[I]) return 0; else if(compaerA[I] < compaerB[I]) return 1; } return 0; }