Browse Source

feat:增加rdson电流采样校准单元测试

CN\guohui27 2 năm trước cách đây
mục cha
commit
0eb2203728

+ 1 - 1
User project/1.FrameLayer/Source/gd32f30x_it.c

@@ -232,7 +232,7 @@ void TIMER0_UP_TIMER9_IRQHandler(void)
                 };
                 
                 /* ADC0 trigger set */
-                TIMER_CH3CV(TIMER0) = (uint32_t) pwm_stGenOut.uwRDSONTrig;
+                TIMER_CH3CV(TIMER0) = (uint32_t) pwm_stGenOut.uwRdsonTrig;
                 adc_enable(ADC0);
                 /* Software trigger for regular sampling*/
                 adc_software_trigger_enable(ADC0, ADC_REGULAR_CHANNEL); 

+ 14 - 3
User project/2.MotorDrive/Include/adc.h

@@ -21,6 +21,9 @@ Revising History (ECL of this file):
 #ifndef ADCDRV_H
 #define ADCDRV_H
 
+#ifdef __cplusplus
+extern "C" {
+#endif // __cplusplus
 /************************************************************************
  Compiler Directives
 *************************************************************************/
@@ -50,6 +53,7 @@ typedef struct
     UWORD uwIbAbsPu;  // Q14, Phase B current absolute value
     UWORD uwIcAbsPu;  // Q14, Phase C current absolute value
     UWORD uwIpeakPu;  // Q14, Max value of phase current
+    UWORD ulISamplePeakPu;
 
     UWORD uwIaAvgPu; // Ia register value
     UWORD uwIbAvgPu; // Ib register value
@@ -136,6 +140,7 @@ typedef struct
     SWORD swMotorTempKcof;
     UWORD uwCalibCoefK;
 
+    BOOL blCalibCalFlag;
 } ADC_COF;
 
 /************************************************************************
@@ -165,6 +170,8 @@ _ADCDRV_EXT UWORD adc_uwRdsonUReg;
 _ADCDRV_EXT UWORD adc_uwRdsonVReg;
 _ADCDRV_EXT UWORD adc_uwRdsonWReg;
 
+_ADCDRV_EXT BOOL tsttstFlg = FALSE;
+
 #else
 _ADCDRV_EXT ADC_COF      adc_stCof;
 _ADCDRV_EXT ADC_UP_OUT   adc_stUpOut;
@@ -185,6 +192,8 @@ _ADCDRV_EXT UWORD adc_uwRdsonUReg;
 _ADCDRV_EXT UWORD adc_uwRdsonVReg;
 _ADCDRV_EXT UWORD adc_uwRdsonWReg;
 
+_ADCDRV_EXT BOOL tsttstFlg;
+
 #endif
 /************************************************************************
  RAM ALLOCATION:
@@ -199,21 +208,23 @@ _ADCDRV_EXT void adc_voSampleUp(const ADC_COF *cof, ADC_UP_OUT *out);
 _ADCDRV_EXT void adc_voSampleDown(const ADC_COF *cof, ADC_DOWN_OUT *out);
 _ADCDRV_EXT void adc_voSampleCoef(ADC_COF *cof);
 _ADCDRV_EXT void adc_voSampleInit(void);
-_ADCDRV_EXT void adc_voSRCalibration(ADC_COF *cof, const ADC_UP_OUT *up_out, const ADC_DOWN_OUT *down_out);
+_ADCDRV_EXT void adc_voSRCalibration(ADC_COF *cof, const ADC_UP_OUT *up_out, ADC_DOWN_OUT *down_out);
 #else
 _ADCDRV_EXT void adc_voCalibration(ADC_COF *cof, ADC_DOWN_OUT *out1, ADC_UP_OUT *out2); // Phase A and B current zero point, other A/D sample value
 _ADCDRV_EXT void adc_voSampleUp(const ADC_COF *cof, ADC_UP_OUT *out);
 _ADCDRV_EXT void adc_voSampleDown(const ADC_COF *cof, ADC_DOWN_OUT *out);
 _ADCDRV_EXT void adc_voSampleCoef(ADC_COF *cof);
 _ADCDRV_EXT void adc_voSampleInit(void);
-_ADCDRV_EXT void adc_voSRCalibration(ADC_COF *cof, const ADC_UP_OUT *up_out, const ADC_DOWN_OUT *down_out);
+_ADCDRV_EXT void adc_voSRCalibration(ADC_COF *cof, const ADC_UP_OUT *up_out, ADC_DOWN_OUT *down_out);
 #endif
 
 /************************************************************************
  Flag Define (N/A)
 *************************************************************************/
+#ifdef __cplusplus
+}
+#endif // __cplusplus
 
-/***********************************************************************/
 #endif
 /************************************************************************
  Copyright (c) 2018 Welling Motor Technology(Shanghai) Co. Ltd.

+ 9 - 1
User project/2.MotorDrive/Include/pwm.h

@@ -20,6 +20,10 @@
 ************************************************************************/
 #ifndef PWM_H
 #define PWM_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif // __cplusplus
 /************************************************************************
  Compiler Directives (N/A)
 ************************************************************************/
@@ -119,7 +123,7 @@ typedef struct
     RDSON_SAMPLE_AREA   uwSampleArea;
     SINGELR_SAMPLE_AREA uwSingelRSampleAreaLast;
     SINGELR_SAMPLE_AREA uwSingelRSampleArea;
-    UWORD               uwRDSONTrig;
+    UWORD               uwRdsonTrig;
     UWORD               uwSigRTrig;
     BOOL                blOvmFlag;
     BOOL                blSampleCalibFlag;
@@ -175,6 +179,10 @@ PWM_EXT void pwm_voInit(void);
 ************************************************************************/
 
 /***********************************************************************/
+#ifdef __cplusplus
+}
+#endif // __cplusplus
+
 #endif
 /************************************************************************
  Copyright (c) 2018 Welling Motor Technology(Shanghai) Co. Ltd.

+ 7 - 1
User project/2.MotorDrive/Include/spdctrmode.h

@@ -22,6 +22,10 @@ Revising History (ECL of this file):
 #define SPDCTRMODE_H
 #include "spdctrFSM.h"
 #include "mathtool.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif // __cplusplus
 /************************************************************************
  Compiler Directives (N/A)
 *************************************************************************/
@@ -264,8 +268,10 @@ _SPDCTRMODE_EXT SWORD scm_swStopPWMOffFlag;
 /************************************************************************
  Flag Define (N/A)
 *************************************************************************/
+#ifdef __cplusplus
+}
+#endif // __cplusplus
 
-/***********************************************************************/
 #endif
 /************************************************************************
  Copyright (c) 2018 Welling Motor Technology(Shanghai) Co. Ltd.

+ 93 - 37
User project/2.MotorDrive/Source/adc.c

@@ -28,6 +28,10 @@ Revising History (ECL of this file):
 #include "syspar.h"
 #include "user.h"
 #include "Temp.h"
+
+#ifdef RUN_ARCH_SIM
+#include "test_user.h"
+#endif
 /************************************************************************
  Constant Table:
 *************************************************************************/
@@ -44,6 +48,9 @@ Revising History (ECL of this file):
  Subroutine Call: N/A
  Reference: N/A
 ****************************************************************/
+#ifdef RUN_ARCH_SIM
+
+#else
 void adc_voCalibration(ADC_COF *cof, ADC_DOWN_OUT *out1, ADC_UP_OUT *out2)
 {
 
@@ -57,7 +64,7 @@ void adc_voCalibration(ADC_COF *cof, ADC_DOWN_OUT *out1, ADC_UP_OUT *out2)
         {
             if(cp_stFlg.CurrentSampleModelSelect == COMBINATION)
             {
-                pwm_stGenOut.uwRDSONTrig = 129; 
+                pwm_stGenOut.uwRdsonTrig = 129; 
                 pwm_stGenOut.uwSigRTrig = HW_HHHPWM_PERIOD;
                 pwm_stGenOut.blSampleCalibFlag = TRUE;
                 if (out1->uwADCCalibCt < (1 << ADC_CALIB_INDEX))
@@ -144,6 +151,7 @@ void adc_voCalibration(ADC_COF *cof, ADC_DOWN_OUT *out1, ADC_UP_OUT *out2)
         }
     }
 }
+#endif
 /***************************************************************
  Function: adc_voSample;
  Description: Get three-phase current value after zero point and gain process
@@ -360,22 +368,24 @@ void adc_voSampleUp(const ADC_COF *cof, ADC_UP_OUT *out)
     }
 
     ////////////////// PCB TEMP//////////////////////////////////////////////////////
-    out->PCBTempR = (UWORD)((ULONG)4096 * PCB_TEMP_SAMPLER / out->PCBTempReg - PCB_TEMP_SAMPLER); // Q14=Q24-Q10;
+    if(out->PCBTempReg != 0)
+    {
+        out->PCBTempR = (UWORD)((ULONG)4096 * PCB_TEMP_SAMPLER / out->PCBTempReg - PCB_TEMP_SAMPLER); // Q14=Q24-Q10;
+    }
     PcbTempCal((SWORD)out->PCBTempR);
     out->PCBTemp = tmp_PcbTemp;
 }
 
-static SWORD adc_pvt_swSingleReg;
-static SLONG adc_pvt_slRdsonReg;
-static LPF_OUT adc_pvt_stRdsonCoefLpf;
-static UWORD adc_pvt_uwCalGainFlg;
-static ULONG adc_pvt_ulGainTemp1;
-void adc_voSRCalibration(ADC_COF *cof, const ADC_UP_OUT *up_out, const ADC_DOWN_OUT *down_out)
+static SWORD adc_pvt_swSingleReg = 0;
+static SLONG adc_pvt_slRdsonReg = 0;
+static LPF_OUT adc_pvt_stRdsonCoefLpf = {.slY.sw.hi = 1024, .slY.sw.low = 0};
+static BOOL adc_pvt_blCalGainFlg = FALSE;
+static ULONG adc_pvt_ulGainTemp1 = 0;
+static ULONG adc_pvt_ulIaAbsPu, adc_pvt_ulIbAbsPu, adc_pvt_ulIcAbsPu, adc_pvt_ulIPeakPu;
+void adc_voSRCalibration(ADC_COF *cof, const ADC_UP_OUT *up_out, ADC_DOWN_OUT *down_out)
 { 
-
     if (pwm_stGenOut.blSampleCalibFlag == TRUE)
     {             
-
         switch (pwm_stGenOut.uwSingelRSampleArea)
         {
         case 0:
@@ -415,21 +425,57 @@ void adc_voSRCalibration(ADC_COF *cof, const ADC_UP_OUT *up_out, const ADC_DOWN_
             break;
         }
       
-        adc_pvt_uwCalGainFlg = 1;
-           
+        adc_pvt_blCalGainFlg = TRUE;
     }
     else
-    {
-         if(scm_uwSpdFbkLpfAbsPu <= 2500)
+    {         
+         ULONG ulOverflowCurPu = (ULONG)(4095 - cof->uwIaOffset) * cof->uwCurReg2Pu >> 10;
+
+         if(scm_uwSpdFbkLpfAbsPu < 2500)
          {
+            adc_pvt_ulIaAbsPu = abs(down_out->slSampIaPu);
+            adc_pvt_ulIbAbsPu = abs(down_out->slSampIbPu);
+            adc_pvt_ulIcAbsPu = abs(down_out->slSampIcPu);
+            
+            adc_pvt_ulIPeakPu = adc_pvt_ulIaAbsPu > adc_pvt_ulIbAbsPu ? adc_pvt_ulIaAbsPu : adc_pvt_ulIbAbsPu;
+            down_out->ulISamplePeakPu = adc_pvt_ulIcAbsPu > adc_pvt_ulIPeakPu ? adc_pvt_ulIcAbsPu : adc_pvt_ulIPeakPu;
+
+            if(down_out->ulISamplePeakPu > 32767)  
+            {
+                adc_pvt_ulGainTemp1 = 780;     ///< Rdson电流采样溢出SWORD时校准系数需小于1024
+                adc_pvt_stRdsonCoefLpf.slY.sw.hi = (SWORD)adc_pvt_ulGainTemp1;  ///< 系数立刻变化,不经过滤波,防止down_out->swIaPu溢出
+            }
+            // else if(down_out->ulISamplePeakPu > 25800) ///<  25800 = 32767 / (1300 / 1024)
+            // {
+            //     adc_pvt_ulGainTemp1 = 1024;
+            //     adc_pvt_stRdsonCoefLpf.slY.sw.hi = (SWORD)adc_pvt_ulGainTemp1;
+            // }
+            else
+            {
+                adc_pvt_ulGainTemp1 = 1024;    ///< 允许其他数值,但大于1024需注意溢出SWORD
+            }
 
-            adc_pvt_ulGainTemp1 = 1300;
+            cof->blCalibCalFlag = FALSE;
+            adc_pvt_blCalGainFlg = FALSE;
          }
          else
          {
-            if(adc_pvt_uwCalGainFlg ==1)
+            if(adc_pvt_blCalGainFlg)
             {
-                adc_pvt_ulGainTemp1 = (SLONG)((SLONG)adc_pvt_swSingleReg << 10) / (SLONG)adc_pvt_slRdsonReg;               
+                if(adc_pvt_slRdsonReg != 0 && abs(adc_pvt_slRdsonReg) < ulOverflowCurPu)
+                {
+                    adc_pvt_ulGainTemp1 = (SLONG)((SLONG)adc_pvt_swSingleReg << 10) / (SLONG)adc_pvt_slRdsonReg;
+                }
+                else if(abs(adc_pvt_slRdsonReg) >= ulOverflowCurPu)
+                {
+                    adc_pvt_ulGainTemp1 = 780;     ///< Rdson电流采样削顶时不再校准电流,强制输出为119A防止溢出,尽快报出过流故障
+                    adc_pvt_stRdsonCoefLpf.slY.sw.hi = (SWORD)adc_pvt_ulGainTemp1;
+                }
+                else 
+                {
+                    // do nothing
+                }
+                                
                 if(adc_pvt_ulGainTemp1 > cof->uwCalibcoefMax)
                 {
                     adc_pvt_ulGainTemp1 = cof->uwCalibcoefMax;
@@ -440,23 +486,23 @@ void adc_voSRCalibration(ADC_COF *cof, const ADC_UP_OUT *up_out, const ADC_DOWN_
                 }
                 else
                 {
-                	//do nothing
+                    //do nothing
                 }
-                adc_pvt_uwCalGainFlg = 0;
-               
-               }
-            else
+
+                cof->blCalibCalFlag = TRUE;
+                adc_pvt_blCalGainFlg = FALSE;
+            }
+            else 
             {
                 adc_pvt_swSingleReg = 0;
                 adc_pvt_slRdsonReg = 0;
             }
-         }
+            
+        }
                   
         mth_voLPFilter((SWORD)adc_pvt_ulGainTemp1, &adc_pvt_stRdsonCoefLpf);
         cof->uwCalibcoef = adc_pvt_stRdsonCoefLpf.slY.sw.hi; 
-    }
-      ////////////////////////////////////////////////////////////////////////////////////
-       
+    }     
 }
 
 /***************************************************************
@@ -510,6 +556,16 @@ void adc_voSampleInit(void)
     adc_stDownOut.uwIaAvgPu = 0;
     adc_stDownOut.uwIbAvgPu = 0;
     adc_stDownOut.uwIcAvgPu = 0;
+    adc_stDownOut.ulUaRegSum = 0;
+    adc_stDownOut.ulUbRegSum = 0;
+    adc_stDownOut.ulUcRegSum = 0;
+    adc_stDownOut.ulIdcRegSum = 0;
+    adc_stDownOut.ulIaRegSum = 0;
+    adc_stDownOut.ulIbRegSum = 0;
+    adc_stDownOut.ulIcRegSum = 0;
+    adc_stDownOut.uwADCCalibCt = 0;
+    adc_stDownOut.blADCCalibFlg = FALSE;
+    adc_stDownOut.ulISamplePeakPu = 0;
 
     adc_stUpOut.uwVdcPu = 0;
     adc_stUpOut.uwVdcLpfPu = 0;
@@ -529,20 +585,20 @@ void adc_voSampleInit(void)
     adc_stUpOut.swCalibIaPu = 0;
     adc_stUpOut.swCalibIbPu = 0;
     adc_stUpOut.swCalibIcPu = 0;
-
-    adc_stDownOut.ulUaRegSum = 0;
-    adc_stDownOut.ulUbRegSum = 0;
-    adc_stDownOut.ulUcRegSum = 0;
-    adc_stDownOut.ulIdcRegSum = 0;
-    adc_stDownOut.ulIaRegSum = 0;
-    adc_stDownOut.ulIbRegSum = 0;
-    adc_stDownOut.ulIcRegSum = 0;
-    adc_stDownOut.uwADCCalibCt = 0;
-    adc_stDownOut.blADCCalibFlg = FALSE;
-
     adc_stUpOut.uwADCCalibCt = 0;
     adc_stUpOut.blADCCalibFlg = FALSE;
     adc_stUpOut.swIPMTempCe = 0;
+
+    adc_pvt_swSingleReg = 0;
+    adc_pvt_slRdsonReg = 0;
+    adc_pvt_stRdsonCoefLpf.slY.sw.hi = 1024;
+    adc_pvt_stRdsonCoefLpf.slY.sw.low = 0;
+    adc_pvt_blCalGainFlg = FALSE;
+    adc_pvt_ulGainTemp1 = 0;
+    adc_pvt_ulIaAbsPu = 0;
+    adc_pvt_ulIbAbsPu = 0;
+    adc_pvt_ulIcAbsPu = 0;
+    adc_pvt_ulIPeakPu = 0;
 }
 
 /*************************************************************************

+ 7 - 16
User project/2.MotorDrive/Source/pwm.c

@@ -79,8 +79,9 @@ void pwm_voInit(void)
     pwm_stGenOut.uwOldTrig = 0;
     pwm_stGenOut.uwNewTrig = 0;
     pwm_stGenOut.uwSampleArea = IgnoreNone;
-    pwm_stGenOut.uwRDSONTrig = 129;
+    pwm_stGenOut.uwRdsonTrig = 129;
     pwm_stGenOut.uwSigRTrig = HW_HHHPWM_PERIOD;
+    pwm_stGenOut.blSampleCalibFlag = FALSE;
 }
 
 /************************************************************************
@@ -163,7 +164,6 @@ void pwm_voGenCoef(PWM_COF_IN *in, PWM_CALC_COF *coef)
  Subroutine Call: N/A;
  Reference: N/A;
 ************************************************************************/
-static UWORD testkjsahfjkahj,testkjsahfjkahj1;
 static SWORD swOvmT1, swOvmT2;
 void pwm_voGen(PWM_GEN_IN *in, const PWM_CALC_COF *coef, PWM_GEN_OUT *out) /* parasoft-suppress METRICS-28 "本项目圈复杂度无法更改,后续避免" */
 { /* parasoft-suppress GJB5369-4_2_2_2 "本项目函数行数无法更改,后续应避免" */
@@ -524,7 +524,7 @@ void pwm_voGen(PWM_GEN_IN *in, const PWM_CALC_COF *coef, PWM_GEN_OUT *out) /* pa
         out->swUalphaPu = (swUaPu + swUaPu - swUbPu - swUcPu) * PWM_1DIV3 >> 14; // Q14=Q14+Q14-Q14
         out->swUbetaPu = (swUbPu - swUcPu) * PWM_SQRT3_INV >> 14;                // Q14=Q14+Q14-Q14
 
-        out->uwRDSONTrig = 129;
+        out->uwRdsonTrig = 129;
     }    
     else if(cp_stFlg.CurrentSampleModelSelect == SINGLERESISITANCE)
     {
@@ -546,8 +546,6 @@ void pwm_voGen(PWM_GEN_IN *in, const PWM_CALC_COF *coef, PWM_GEN_OUT *out) /* pa
         swPWMPRD22 = swPWMPRD2;
         swPWMPRD32 = swPWMPRD3;
         /* comparision value correction when two vectors are both too short*/
-      testkjsahfjkahj1=0;
-      testkjsahfjkahj=0;
         if ((swOvmT1 + swOvmT2) < (pwm_pvt_swMin_Double_Cur_Smpl_Pu << 1))
         {
 
@@ -555,14 +553,12 @@ void pwm_voGen(PWM_GEN_IN *in, const PWM_CALC_COF *coef, PWM_GEN_OUT *out) /* pa
             {
                 swPWMPRD31 = swPWMPRD2 - pwm_pvt_swMin_Cur_Smpl_Ct;
                 swPWMPRD32 = (swPWMPRD3 << 1) - swPWMPRD31;
-                testkjsahfjkahj1=1;
                 
             }
             if ((swOvmT2 - pwm_pvt_swMin_Double_Cur_Smpl_Pu) < 0)
             {
                 swPWMPRD11 = swPWMPRD2 + pwm_pvt_swMin_Cur_Smpl_Ct;
                 swPWMPRD12 = (swPWMPRD1 << 1) - swPWMPRD11;
-                testkjsahfjkahj=2;
             }
         }
         else
@@ -583,14 +579,11 @@ void pwm_voGen(PWM_GEN_IN *in, const PWM_CALC_COF *coef, PWM_GEN_OUT *out) /* pa
                     swPWMPRD32 = swPWMPRD3;
                     swPWMPRD22 = (SWORD)coef->uwHPWMPd;
                     swPWMPRD21 = (swPWMPRD2 << 1) - swPWMPRD22;
-                    testkjsahfjkahj=3;
                 }
                 else
                 {
                     swPWMPRD21 = swPWMPRD1 - pwm_pvt_swMin_Cur_Smpl_Ct;
-                    swPWMPRD22 = (swPWMPRD2 << 1) - swPWMPRD21;
-                    testkjsahfjkahj=4;
-                    
+                    swPWMPRD22 = (swPWMPRD2 << 1) - swPWMPRD21;                  
                 }
             }
             else if ((swOvmT1 - pwm_pvt_swMin_Double_Cur_Smpl_Pu) < 0)
@@ -607,13 +600,11 @@ void pwm_voGen(PWM_GEN_IN *in, const PWM_CALC_COF *coef, PWM_GEN_OUT *out) /* pa
                     swPWMPRD21 = (swPWMPRD2 << 1) - swPWMPRD22;
                     swPWMPRD31 = 0;
                     swPWMPRD32 = (swPWMPRD3 << 1) - swPWMPRD31;
-                    testkjsahfjkahj=5;
                 }
                 else
                 {
                     swPWMPRD21 = swPWMPRD3 + pwm_pvt_swMin_Cur_Smpl_Ct;
                     swPWMPRD22 = (swPWMPRD2 << 1) - swPWMPRD21;
-                    testkjsahfjkahj=6;
                 }
             }
             else
@@ -814,7 +805,7 @@ void pwm_voGen(PWM_GEN_IN *in, const PWM_CALC_COF *coef, PWM_GEN_OUT *out) /* pa
         if ((16384 - swOvmT1 - swOvmT2) > coef->uwPWMMinSample1Pu)
         {
             out->uwSampleArea = IgnoreNone;
-            out->uwRDSONTrig = 129;
+            out->uwRdsonTrig = 129;
         }
         else
         {
@@ -844,7 +835,7 @@ void pwm_voGen(PWM_GEN_IN *in, const PWM_CALC_COF *coef, PWM_GEN_OUT *out) /* pa
                     out->uwSampleArea = IgnoreNone;
                     break;
                 }
-                out->uwRDSONTrig = swPWMPRD3 + coef->uwSampleSteadyCt;
+                out->uwRdsonTrig = swPWMPRD3 + coef->uwSampleSteadyCt;
             }
             else
             {
@@ -872,7 +863,7 @@ void pwm_voGen(PWM_GEN_IN *in, const PWM_CALC_COF *coef, PWM_GEN_OUT *out) /* pa
                     out->uwSampleArea = IgnoreNone;
                     break;
                 }
-                out->uwRDSONTrig = swPWMPRD2 + coef->uwSampleSteadyCt;
+                out->uwRdsonTrig = swPWMPRD2 + coef->uwSampleSteadyCt;
             }
         }
     }

+ 1 - 0
User project/3.BasicFunction/Include/bikespeed.h

@@ -114,6 +114,7 @@ typedef struct
     BIKESPEED_FSM bikespeed_fsm;
     
     UWORD uwCaputureOverflowMinCnt;
+    UWORD uwCaputureOverflowMinCntTest;
     UWORD uwBikeForwardCnt;   // Count number to calculate trip
     BOOL  blUpdateTripCntFlg; // Unit the same as BIKESPEED_COF.uwMinTriptoUpdate ��need clear after update trip.
     UWORD uwOverflowfirst;

+ 2 - 0
User project/3.BasicFunction/Source/bikespeed.c

@@ -189,6 +189,7 @@ static void bikespeed_voBikeSpeedWork(UWORD source)
             {
                 //do noting
             }
+            bikespeed_stFreGetOut.uwCaputureOverflowMinCntTest = bikespeed_stFreGetOut.uwCaputureOverflowMinCnt;
 
             /* BikeSpeed Freq Cal */
             bikespeed_pvt_FreqPu = (ULONG)(((UQWORD)720000 << 20) / ((UQWORD)ulCaputureCntErr * bikespeed_stFreGetCof.uwNumbersPulses * FBASE));
@@ -341,6 +342,7 @@ void bikespeed_voBikeSpeedInit(void)
     bikespeed_stFreGetOut.uwBikespeedPwrErrorCnt = 0;
     bikespeed_stFreGetOut.uwBikespeedPwrErrorCnt = 0;
     bikespeed_stFreGetOut.uwBikespeedPwrRecoverCnt = 0;
+    bikespeed_stFreGetOut.uwCaputureOverflowMinCntTest = 0;
 }
 
 /***************************************************************

+ 7 - 0
User project/4.BasicHardwSoftwLayer/2.BasicSoftwLayer/Include/CodePara.h

@@ -21,6 +21,9 @@
 #ifndef CODE_PARA_H
 #define CODE_PARA_H
 
+#ifdef __cplusplus
+extern "C" {
+#endif // __cplusplus
 /************************************************************************
  Definitions & Macros
 *************************************************************************/
@@ -324,6 +327,10 @@ void CPHistoryInfoCalTiming(void);
 /************************************************************************
  Flag Define (N/A)
 *************************************************************************/
+#ifdef __cplusplus
+}
+#endif // __cplusplus
+
 #endif
 /************************************************************************
  Copyright (c) 2018 Welling Motor Technology(Shanghai) Co. Ltd.

+ 6 - 1
User project/4.BasicHardwSoftwLayer/2.BasicSoftwLayer/Include/macroequ.h

@@ -21,6 +21,9 @@
 #ifndef MACROEQU_H
 #define MACROEQU_H
 
+#ifdef __cplusplus
+extern "C" {
+#endif // __cplusplus
 /************************************************************************
  Compiler Directives (N/A)
 ************************************************************************/
@@ -76,8 +79,10 @@ _MACROEQU_EXT UWORD FUNCTION_BUFFER[0x20];
 /************************************************************************
  Flag Define (N/A)
 ************************************************************************/
+#ifdef __cplusplus
+}
+#endif // __cplusplus
 
-/***********************************************************************/
 #endif
 /************************************************************************
  Copyright (c) 2018 Welling Motor Technology(Shanghai) Co. Ltd.

+ 8 - 0
User project/4.BasicHardwSoftwLayer/2.BasicSoftwLayer/Include/user.h

@@ -18,6 +18,10 @@
  Compiler Directives
 *************************************************************************/
 #include "typedefine.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif // __cplusplus
 /************************************************************************
  Definitions & Macros
 *************************************************************************/
@@ -551,6 +555,10 @@ Update Time
 /************************************************************************
  Flag Define (N/A)
 *************************************************************************/
+#ifdef __cplusplus
+}
+#endif // __cplusplus
+
 #endif
 /*************************************************************************
  Copyright (c) 2019 Welling Motor Technology(Shanghai) Co. Ltd.

+ 2 - 2
unit_test/test_bikespeed.cpp

@@ -98,7 +98,7 @@ TEST_P(BikeSpeedTest1, FreCal)
 
     double bikeSpeedFreqPu = (double)TIM1CLK_KHZ * 1000 * 1048576 / bikeSpeedPrd / FBASE / bikespeed_stFreGetCof.uwNumbersPulses;  // Q20
 
-    if(bikeSpeedFreqPu > bikespeed_stFreGetCof.uwMaxBikeSpeedFre || bikespeed_stFreGetOut.uwCaputureOverflowCnt > bikespeed_stFreGetOut.uwCaputureOverflowMinCnt)
+    if(bikeSpeedFreqPu > bikespeed_stFreGetCof.uwMaxBikeSpeedFre || bikespeed_stFreGetOut.uwCaputureOverflowCnt > bikespeed_stFreGetOut.uwCaputureOverflowMinCntTest)
     {
         EXPECT_NEAR(bikespeed_stFreGetOut.uwFrequencyPu, 0, 0.1);
     }
@@ -109,7 +109,7 @@ TEST_P(BikeSpeedTest1, FreCal)
 }
 
 INSTANTIATE_TEST_SUITE_P(DiffBikeSpeedPeriod, BikeSpeedTest1,
-                         ::testing::Values(0, 500, 3000, 18000, 100000,1000000));
+                         ::testing::Values(0, 500, 3000, 18000, 100000,10000000));
 
 TEST_F(BikeSpeedTest, FreCal2)
 {

+ 296 - 0
unit_test/test_cursample_calib.cpp

@@ -0,0 +1,296 @@
+#include "gtest/gtest.h"
+#include <gtest/gtest.h>
+#include <stdint.h>
+#include <tuple>
+#include "scope.h"
+#include "test_user.h"
+
+class CurSampleCalibTest : public testing::Test
+{
+protected:
+    static void SetUpTestSuite()
+    {
+        CodeParaInit();
+        adc_voSampleInit();
+        pwm_voInit();
+        scm_uwSpdFbkLpfAbsPu = 0;
+    }
+    virtual void SetUp() override
+    {}
+    virtual void TearDown() override
+    {
+        adc_voSampleInit();
+        pwm_voInit();
+        scm_uwSpdFbkLpfAbsPu = 0;
+    }
+};
+
+class CurSampleCalibTest1 : public CurSampleCalibTest, public testing::WithParamInterface<::std::tuple<double, double, double>>
+{};
+
+TEST_P(CurSampleCalibTest1, SingResCalib)
+{
+    int    timerPrd = HW_PWM_PERIOD;
+    int    timerCnt = 0, timerCntDir = 0, prdCnt = 0;
+    double phase, ia, ib, ic, iaRdson, ibRdson, icRdson;
+    double currentFreqHz = 100;             // unit: Hz
+    double currentMod = get<0>(GetParam()); // unit: A
+    double rdsonCoef = get<1>(GetParam());
+    double voltageMod = get<2>(GetParam()); // unit: V
+    double loopNum = 100000000;
+    double spdAbsTarget = voltageMod * 32768 * 1000 / M_FLUX_WB / 2 / 3.14 * 1000 / FBASE; // 2600
+
+    /* Coef Cal */
+    adc_voSampleCoef(&adc_stCof);
+    adc_stCof.uwIaOffset = 2048;
+    adc_stCof.uwIbOffset = 2048;
+    adc_stCof.uwIcOffset = 2048;
+    adc_stCof.uwIdcOffset = 0;
+
+    pwm_stGenCoefIn.uwPWMDutyMax = cp_stControlPara.swPWMMaxDuty;
+    pwm_stGenCoefIn.uwPWM7To5Duty = cp_stControlPara.swPWM7to5Duty;
+    pwm_stGenCoefIn.uwPWMMinSample1Pu = cp_stControlPara.swPWMMinSampleDuty1;
+    pwm_stGenCoefIn.uwPWMMinSample2Pu = cp_stControlPara.swPWMMinSampleDuty2;
+    pwm_stGenCoefIn.uwPWMMinSample3Pu = cp_stControlPara.swPWMMinSampleDuty3;
+    pwm_stGenCoefIn.uwSampleSteadyPu = cp_stControlPara.swPWMSampleToSteady;
+    pwm_stGenCoefIn.uwSingelResisSamplePu = cp_stControlPara.swPWMSampleSigR;
+    pwm_stGenCoefIn.uwOvmNo = cp_stControlPara.swPWMOverMdlMode;
+    pwm_stGenCoefIn.uwPWMPd = HW_PWM_PERIOD;
+    pwm_voGenCoef(&pwm_stGenCoefIn, &pwm_stGenCoef);
+
+    for (int i = 0; i < loopNum; i++)
+    {
+        /* Current */
+        phase = currentFreqHz * 2 * 3.14 * i / (TIM0CLK_KHZ * 1000);
+        ia = currentMod * sin(phase);
+        ib = currentMod * sin(phase + (double)2 / 3 * 3.14);
+        ic = currentMod * sin(phase + (double)4 / 3 * 3.14);
+
+        iaRdson = ia * rdsonCoef;
+        ibRdson = ib * rdsonCoef;
+        icRdson = ic * rdsonCoef;
+
+        /* Timer: centre-aligned */
+        if (timerCntDir == 0)
+        {
+            timerCnt++;
+            if (timerCnt == (timerPrd / 2))
+            {
+                testTimerIntFlg[TIMER0][TIMER_INT_FLAG_UP] = 1;
+                timerCntDir = 1;
+            }
+        }
+        else
+        {
+            timerCnt--;
+            if (timerCnt == 0)
+            {
+                testTimerIntFlg[TIMER0][TIMER_INT_FLAG_UP] = 1;
+                timerCntDir = 0;
+                prdCnt++;
+            }
+        }
+
+        /* ADC Trigger */
+        if (timerCntDir == 0)
+        {
+            if (prdCnt % 2 == 1)
+            {
+                if (timerCnt == pwm_stGenOut.uwRdsonTrig)
+                {
+                    double iaReg = (double)adc_stCof.uwIaOffset - iaRdson * 100 * 2048 / ADC_IPHASE_CUR_MAX_AP; // Negative direction current
+                    if (iaReg < 0)
+                    {
+                        iaReg = 0;
+                    }
+                    if (iaReg > 4096)
+                    {
+                        iaReg = 4096;
+                    }
+
+                    double ibReg = (double)adc_stCof.uwIbOffset - ibRdson * 100 * 2048 / ADC_IPHASE_CUR_MAX_AP; // Negative direction current
+                    if (ibReg < 0)
+                    {
+                        ibReg = 0;
+                    }
+                    if (ibReg > 4096)
+                    {
+                        ibReg = 4096;
+                    }
+
+                    double icReg = (double)adc_stCof.uwIcOffset - icRdson * 100 * 2048 / ADC_IPHASE_CUR_MAX_AP; // Negative direction current
+                    if (icReg < 0)
+                    {
+                        icReg = 0;
+                    }
+                    if (icReg > 4096)
+                    {
+                        icReg = 4096;
+                    }
+
+                    ADC_IDATA0(ADC0) = iaReg;
+                    ADC_IDATA1(ADC0) = ibReg;
+                    ADC_IDATA2(ADC0) = icReg;
+
+                    testAdcIntFlg[ADC0][ADC_INT_FLAG_EOIC] = 1;
+                }
+            }
+            else
+            {
+                if (timerCnt == pwm_stGenOut.uwSigRTrig)
+                {
+                    switch (pwm_stGenOut.uwSingelRSampleArea)
+                    {
+                    case SampleA:
+                        ADC_IDATA0(ADC1) = (UWORD)(adc_stCof.uwIdcOffset + abs(ia) * 100 * 4096 / ADC_IDC_CUR_MAX_AP);
+                        if (ADC_IDATA0(ADC1) > 4096)
+                        {
+                            ADC_IDATA0(ADC1) = 4096;
+                        }
+
+                        break;
+                    case SampleB:
+                        ADC_IDATA0(ADC1) = (UWORD)(adc_stCof.uwIdcOffset + abs(ib) * 100 * 4096 / ADC_IDC_CUR_MAX_AP);
+                        if (ADC_IDATA0(ADC1) > 4096)
+                        {
+                            ADC_IDATA0(ADC1) = 4096;
+                        }
+
+                        break;
+                    case SampleC:
+                        ADC_IDATA0(ADC1) = (UWORD)(adc_stCof.uwIdcOffset + abs(ic) * 100 * 4096 / ADC_IDC_CUR_MAX_AP);
+                        if (ADC_IDATA0(ADC1) > 4096)
+                        {
+                            ADC_IDATA0(ADC1) = 4096;
+                        }
+
+                        break;
+                    default:
+                        break;
+                    }
+
+                    testAdcIntFlg[ADC1][ADC_INT_FLAG_EOIC] = 1;
+                }
+            }
+        }
+
+        /* ADC Interrupt */
+        if (testAdcIntFlg[ADC0][ADC_INT_FLAG_EOIC] == 1)
+        {
+            adc_uwRdsonUReg = ADC_IDATA0(ADC0);
+            adc_uwRdsonVReg = ADC_IDATA1(ADC0);
+            adc_uwRdsonWReg = ADC_IDATA2(ADC0);
+
+            testAdcIntFlg[ADC0][ADC_INT_FLAG_EOIC] = 0;
+        }
+
+        if (testAdcIntFlg[ADC1][ADC_INT_FLAG_EOIC] == 1)
+        {
+            adc_uwADDMAPhase1 = ADC_IDATA0(ADC1);
+
+            testAdcIntFlg[ADC1][ADC_INT_FLAG_EOIC] = 0;
+        }
+
+        /* Timer Interrupt */
+        if (testTimerIntFlg[TIMER0][TIMER_INT_FLAG_UP] == 1)
+        {
+            if ((timerCntDir == 1) && (prdCnt % 2 == 1))
+            {
+                /* Speed Mock */             
+                if(scm_uwSpdFbkLpfAbsPu < spdAbsTarget)
+                {
+                    scm_uwSpdFbkLpfAbsPu += 20;     ///< 转速需模拟实际从0上升,否则采样校准系数会计算为0
+                }
+                else 
+                {
+                    scm_uwSpdFbkLpfAbsPu = spdAbsTarget;
+                }
+
+                /* Sample and Calibration */ 
+                adc_voSampleUp(&adc_stCof, &adc_stUpOut);
+                adc_voSampleDown(&adc_stCof, &adc_stDownOut);
+                adc_voSRCalibration(&adc_stCof, &adc_stUpOut, &adc_stDownOut);
+
+                /* ADC Trigger Cal */ 
+                pwm_stGenIn.swUalphaPu = (SWORD)(voltageMod * 10 * sin(phase + (double)3.14 / 36) * 16384 / VBASE); // Q14
+                pwm_stGenIn.swUbetaPu = (SWORD)(voltageMod * 10 * cos(phase + (double)3.14 / 36) * 16384 / VBASE);  // Q14
+                pwm_stGenIn.uwVdcPu = (UWORD)(36 * 10 * 16384 / VBASE);                                             // Q14
+                pwm_voGen(&pwm_stGenIn, &pwm_stGenCoef, &pwm_stGenOut);
+
+                /* Scope */ 
+                //UdpScope::Send(0, adc_stDownOut.slSampIcPu, adc_stUpOut.swCalibIcPu, adc_stDownOut.swIcPu);
+                //UdpScope::Send(0, scm_uwSpdFbkLpfAbsPu, pwm_stGenOut.blSampleCalibFlag);
+
+                /* Determine whether the unit test pass */
+                if (prdCnt > (loopNum / HW_PWM_PERIOD - 5))
+                {
+                    if (!adc_stCof.blCalibCalFlag)
+                    {
+                        if(adc_stDownOut.ulISamplePeakPu > 32767)  
+                        {
+                            EXPECT_NEAR((double)adc_stDownOut.slSampIaPu * 780 / 1024, adc_stDownOut.swIaPu, 10);   ///< 系数为立即数,程序中更改后测试用例需要随之更改
+                            EXPECT_NEAR((double)adc_stDownOut.slSampIbPu * 780 / 1024, adc_stDownOut.swIbPu, 10);
+                            EXPECT_NEAR((double)adc_stDownOut.slSampIcPu * 780 / 1024, adc_stDownOut.swIcPu, 10);
+                        }
+                        // else if(adc_stDownOut.ulISamplePeakPu > 25800) 
+                        // {
+                        //     EXPECT_NEAR((double)adc_stDownOut.slSampIaPu * 1024 / 1024, adc_stDownOut.swIaPu, 10);  ///< 系数为立即数,程序中更改后测试用例需要随之更改
+                        //     EXPECT_NEAR((double)adc_stDownOut.slSampIbPu * 1024 / 1024, adc_stDownOut.swIbPu, 10);
+                        //     EXPECT_NEAR((double)adc_stDownOut.slSampIcPu * 1024 / 1024, adc_stDownOut.swIcPu, 10);
+                        // }
+                        else
+                        {
+                            EXPECT_NEAR((double)adc_stDownOut.slSampIaPu * 1024 / 1024, adc_stDownOut.swIaPu, 10);  ///< 系数为立即数,程序中更改后测试用例需要随之更改
+                            EXPECT_NEAR((double)adc_stDownOut.slSampIbPu * 1024 / 1024, adc_stDownOut.swIbPu, 10);
+                            EXPECT_NEAR((double)adc_stDownOut.slSampIcPu * 1024 / 1024, adc_stDownOut.swIcPu, 10);
+                        }
+                    }
+                    else
+                    {
+                        if (1024 / rdsonCoef < adc_stCof.uwCalibcoefMin)
+                        {
+                            if (currentMod * rdsonCoef * 100 >= ADC_IPHASE_CUR_MAX_AP)
+                            {
+                                EXPECT_NEAR((double)adc_stDownOut.slSampIaPu * 780 / 1024, adc_stDownOut.swIaPu, 50);
+                                EXPECT_NEAR((double)adc_stDownOut.slSampIbPu * 780 / 1024, adc_stDownOut.swIbPu, 50);
+                                EXPECT_NEAR((double)adc_stDownOut.slSampIcPu * 780 / 1024, adc_stDownOut.swIcPu, 50);
+                            }
+                            else
+                            {
+                                EXPECT_NEAR((double)adc_stDownOut.slSampIaPu * adc_stCof.uwCalibcoefMin / 1024, adc_stDownOut.swIaPu, 10);
+                                EXPECT_NEAR((double)adc_stDownOut.slSampIbPu * adc_stCof.uwCalibcoefMin / 1024, adc_stDownOut.swIbPu, 10);
+                                EXPECT_NEAR((double)adc_stDownOut.slSampIcPu * adc_stCof.uwCalibcoefMin / 1024, adc_stDownOut.swIcPu, 10);
+                            }
+                        }
+                        else if (1024 / rdsonCoef > adc_stCof.uwCalibcoefMax)
+                        {
+                            EXPECT_NEAR((double)adc_stDownOut.slSampIaPu * adc_stCof.uwCalibcoefMax / 1024, adc_stDownOut.swIaPu, 10);
+                            EXPECT_NEAR((double)adc_stDownOut.slSampIbPu * adc_stCof.uwCalibcoefMax / 1024, adc_stDownOut.swIbPu, 10);
+                            EXPECT_NEAR((double)adc_stDownOut.slSampIcPu * adc_stCof.uwCalibcoefMax / 1024, adc_stDownOut.swIcPu, 10);
+                        }
+                        else
+                        {
+                            if (currentMod < 20)
+                            {
+                                EXPECT_NEAR(ia * 100 * 16384 / IBASE, adc_stDownOut.swIaPu, 0.5 * 100 * 16384 / IBASE);
+                                EXPECT_NEAR(ib * 100 * 16384 / IBASE, adc_stDownOut.swIbPu, 0.5 * 100 * 16384 / IBASE);
+                                EXPECT_NEAR(ic * 100 * 16384 / IBASE, adc_stDownOut.swIcPu, 0.5 * 100 * 16384 / IBASE);
+                            }
+                            else
+                            {
+                                EXPECT_NEAR(ia * 100 * 16384 / IBASE, adc_stDownOut.swIaPu, 1.1 * 100 * 16384 / IBASE);
+                                EXPECT_NEAR(ib * 100 * 16384 / IBASE, adc_stDownOut.swIbPu, 1.1 * 100 * 16384 / IBASE);
+                                EXPECT_NEAR(ic * 100 * 16384 / IBASE, adc_stDownOut.swIcPu, 1.1 * 100 * 16384 / IBASE);
+                            }
+                        }
+                    }
+                }
+            }
+
+            testTimerIntFlg[TIMER0][TIMER_INT_FLAG_UP] = 0;
+        }
+    }
+}
+
+INSTANTIATE_TEST_SUITE_P(DiffCurMod, CurSampleCalibTest1,
+                         ::testing::Combine(::testing::Values(5, 19, 39, 55), ::testing::Values(0.4, 0.8, 2.1, 6), ::testing::Values(1, 2, 10)));

+ 1 - 1
unit_test/test_torquesensor.cpp

@@ -149,7 +149,7 @@ TEST_P(TorqueSensorTest2, OffsetUpdate)
         torsensor_voOffsetUpdate();
 
         //UdpScope::Send(0, torsensor_stTorSensorCof.uwTorqueOffset); 
-        // UdpScope::Send(0, torsensor_stTorSensorCof.uwTorqueOffsetConfirmFlg); 
+        //UdpScope::Send(0, torsensor_stTorSensorCof.uwTorqueOffsetConfirmFlg); 
         
     }
 

+ 6 - 0
unit_test/test_user.c

@@ -1,10 +1,16 @@
 #include "test_user.h"
 
+int testAdcInjectData0[2];
+int testAdcInjectData1[2];
+int testAdcInjectData2[2];
+int testAdcIntFlg[2][2];
 int testTimerIntFlg[2][4];
 int testCh2CapValue[2];
 int testCh3CapValue[2];
 int testGpioBValue[2];
 
+
+UWORD scm_uwSpdFbkLpfAbsPu;
 UWORD hw_uwADC0[ADC0_DMA_NUM];
 MC_UpperPCInfo_Struct_t MC_UpcInfo;
 

+ 22 - 3
unit_test/test_user.h

@@ -1,10 +1,17 @@
 #include "Cadence.h"
 #include "bikespeed.h"
 #include "torquesensor.h"
+#include "adc.h"
+#include "pwm.h"
 
+#include "typedefine.h"
+#include "CodePara.h"
+#include "macroequ.h"
 #include "canAppl.h"
 #include "hwsetup.h"
-#include "typedefine.h"
+#include "Temp.h"
+#include "spdctrmode.h"
+#include "user.h"
 
 #ifndef _TEST_USER_H_
 #define _TEST_USER_H_
@@ -13,6 +20,11 @@
 extern "C" {
 #endif // __cplusplus
 
+#define ADC0              0
+#define ADC1              1
+#define ADC_INT_FLAG_EOIC 0
+
+#define TIMER0             0
 #define TIMER1             1
 #define TIMER_INT_FLAG_UP  0
 #define TIMER_INT_FLAG_CH1 1
@@ -22,18 +34,25 @@ extern "C" {
 #define GPIOB 1
 #define GPIOC 2
 
+#define ADC_IDATA0(adcx)   testAdcInjectData0[adcx]
+#define ADC_IDATA1(adcx)   testAdcInjectData1[adcx]
+#define ADC_IDATA2(adcx)   testAdcInjectData2[adcx]
 #define TIMER_CH2CV(timex) testCh2CapValue[timex]
 #define TIMER_CH3CV(timex) testCh3CapValue[timex]
 #define GPIO_ISTAT(gpiox)  testGpioBValue[gpiox]
 
-#define abs(x)    ((x) >= 0 ? (x) : (-(x)))
-
+#define abs(x) ((x) >= 0 ? (x) : (-(x)))
 
+extern int testAdcInjectData0[2];
+extern int testAdcInjectData1[2];
+extern int testAdcInjectData2[2];
+extern int testAdcIntFlg[2][2];
 extern int testTimerIntFlg[2][4];
 extern int testCh2CapValue[2];
 extern int testCh3CapValue[2];
 extern int testGpioBValue[2];
 
+
 int  timer_interrupt_flag_get(int timer_periph, int interrupt);
 void timer_interrupt_flag_clear(int timer_periph, int interrupt);
 

+ 3 - 0
xmake.lua

@@ -8,7 +8,10 @@ target("unittest")
 
     add_files("unit_test/*.cpp","unit_test/tools/*.cpp","unit_test/tools/*.c", "unit_test/*.c")
     add_files("User project/4.BasicHardwSoftwLayer/2.BasicSoftwLayer/Source/CodePara.c", "User project/4.BasicHardwSoftwLayer/2.BasicSoftwLayer/Source/mathtool.c")
+    add_files("User project/4.BasicHardwSoftwLayer/2.BasicSoftwLayer/Source/macroequ.c")
     add_files("User project/3.BasicFunction/Source/Cadence.c", "User project/3.BasicFunction/Source/bikespeed.c", "User project/3.BasicFunction/Source/torquesensor.c")
+    add_files("User project/2.MotorDrive/Source/adc.c", "User project/2.MotorDrive/Source/pwm.c")
+    add_files("User project/3.BasicFunction/Source/Temp.c")
 
     -- add_includedirs("Std project/CMSIS")
     -- add_includedirs("Std project/CMSIS/GD/GD32F30x/Inc_GD")