Post Go back to editing

Problem at reported Impedance data by CN0510: Invalid Impedance Values

Category: Software
Product Number: AD5941

Hi! I am working with CN0510 Board with NUCLEo-F411RE and I have Loaded my board with BATImpedance Project which is available on Github. I am currently using 50 m ohm Resistor with a Lead Acid battery to study the impedance spectrum of The battery but the problem is that I don't get valid impedance! could you please help me solve the problem?

Parents
  • Hi,

    Could you please check with the below code:

    /*BATImpedance.c*/
    #include "BATImpedance.h"
    
    /* 
      Application configuration structure. Specified by user from template.
      The variables are usable in this whole application.
      It includes basic configuration for sequencer generator and application related parameters
    */
    AppBATCfg_Type AppBATCfg = 
    {
      .state = STATE_IDLE,
      .bParaChanged = bFALSE,
      .SeqStartAddr = 0,
      .MaxSeqLen = 0,
      
      .SeqStartAddrCal = 0,
      .MaxSeqLenCal = 0,
    
      .SysClkFreq = 16000000.0,
      .WuptClkFreq = 32000.0,
      .AdcClkFreq = 16000000.0,
      .BatODR = 20.0, /* 20.0 Hz*/
      .NumOfData = -1,
    
      .PwrMod = AFEPWR_LP,
      .ACVoltPP = 800.0,
      .DCVolt = 1100.0f,
      .SinFreq = 50000.0, /* 50kHz */
      .RcalVal = 50.0, /* 50mOhm */
    
      .ADCSinc3Osr = ADCSINC3OSR_4,
      .ADCSinc2Osr = ADCSINC2OSR_22,
    
      .DftNum = DFTNUM_16384,
      .DftSrc = DFTSRC_SINC3,
      .HanWinEn = bTRUE,
    
      .FifoThresh = 4,
      .BATInited = bFALSE,
      .StopRequired = bFALSE,
      .MeasSeqCycleCount = 0,
    	
    	.SweepCfg.SweepEn = bTRUE,
      .SweepCfg.SweepStart = 1000,
      .SweepCfg.SweepStop = 100000.0,
      .SweepCfg.SweepPoints = 101,
      .SweepCfg.SweepLog = bFALSE,
      .SweepCfg.SweepIndex = 0,
    };
    
    /**
       This function is provided for upper controllers that want to change 
       application parameters specially for user defined parameters.
    */
    AD5940Err AppBATGetCfg(void *pCfg)
    {
      if(pCfg){
        *(AppBATCfg_Type**)pCfg = &AppBATCfg;
        return AD5940ERR_OK;
      }
      return AD5940ERR_PARA;
    }
    
    
    static void PreCharge(unsigned char channel) 
    {
      void Arduino_WriteDn(uint32_t Dn, BoolFlag bHigh);
      switch(channel)
      {
        case PRECHARGE_CH1: //00
        Arduino_WriteDn(1<<3, bFALSE);  //d3
        Arduino_WriteDn(1<<4, bFALSE);  //d4
        break;
        case PRECHARGE_CH2: //01
        Arduino_WriteDn(1<<3, bTRUE);
        Arduino_WriteDn(1<<4, bFALSE);
        break;
        case PRECHARGE_CH3://10
        Arduino_WriteDn(1<<3, bFALSE);
        Arduino_WriteDn(1<<4, bTRUE);
        break;
        default:
        break;
      }
      AD5940_Delay10us(PRECHARGE_WAIT_MS*100);
      Arduino_WriteDn(1<<3, bTRUE);  //d3
      Arduino_WriteDn(1<<4, bTRUE);  //d4
    }
    
    AD5940Err AppBATCtrl(int32_t BatCtrl, void *pPara)
    {
      switch (BatCtrl)
      {
        case BATCTRL_START:
        {
          if(AD5940_WakeUp(10) > 10)  /* Wakeup AFE by read register, read 10 times at most */
            return AD5940ERR_WAKEUP;  /* Wakeup Failed */
          if(AppBATCfg.BATInited == bFALSE)
            return AD5940ERR_APPERROR;
          AD5940_WriteReg(REG_AFE_SWMUX, 1<<0); 				/* control ADG636 to measure battery */
    			AD5940_WriteReg(REG_AFE_SYNCEXTDEVICE, 0x0);
          PreCharge(PRECHARGE_BAT);
          PreCharge(PRECHARGE_AMP);
          AD5940_FIFOCtrlS(FIFOSRC_DFT, bFALSE);
          AD5940_FIFOThrshSet(AppBATCfg.FifoThresh);  /* DFT result contains both real and image. */
          AD5940_FIFOCtrlS(FIFOSRC_DFT, bTRUE);
    			AppBATCfg.state = STATE_BATTERY;
          /* Trigger sequence using MMR write */
    			AD5940_SEQMmrTrig(SEQID_0);
          AppBATCfg.FifoDataCount = 0;  /* restart */
          
          break;
        }
        case BATCTRL_STOPNOW:
        {
          if(AD5940_WakeUp(10) > 10)  /* Wakeup AFE by read register, read 10 times at most */
            return AD5940ERR_WAKEUP;  /* Wakeup Failed */
          /* Start Wupt right now */
          AD5940_WUPTCtrl(bFALSE);
          /* There is chance this operation will fail because sequencer could put AFE back 
            to hibernate mode just after waking up. Use STOPSYNC is better. */
          AD5940_WUPTCtrl(bFALSE);
          break;
        }
        case BATCTRL_STOPSYNC:
        {
          AppBATCfg.StopRequired = bTRUE;
          break;
        }
    		case BATCTRL_GETFREQ:
        if(pPara)
        {
          if(AppBATCfg.SweepCfg.SweepEn == bTRUE)
            *(float*)pPara = AppBATCfg.FreqofData;
          else
            *(float*)pPara = AppBATCfg.SinFreq;
        }
    		break;
        case BATCTRL_SHUTDOWN:
        {
          AppBATCtrl(BATCTRL_STOPNOW, 0);  /* Stop the measurement if it's running. */
          /* Turn off LPloop related blocks which are not controlled automatically by sleep operation */
          AFERefCfg_Type aferef_cfg;
          LPLoopCfg_Type lp_loop;
          memset(&aferef_cfg, 0, sizeof(aferef_cfg));
          AD5940_REFCfgS(&aferef_cfg);
          memset(&lp_loop, 0, sizeof(lp_loop));
          AD5940_LPLoopCfgS(&lp_loop);
          AD5940_EnterSleepS();  /* Enter Hibernate */
        }
        break;
        case BATCTRL_MRCAL:
        if(AD5940_WakeUp(10) > 10)
            return AD5940ERR_WAKEUP;
        //Settle input RC filter.
        AD5940_WriteReg(REG_AFE_SWMUX, 0); //control ADG636 to measure rcal
    		AD5940_WriteReg(REG_AFE_SYNCEXTDEVICE, 0x4);
        PreCharge(PRECHARGE_RCAL);
        PreCharge(PRECHARGE_AMP);
        AD5940_FIFOCtrlS(FIFOSRC_DFT, bFALSE);
    		AD5940_FIFOThrshSet(2);
        AD5940_FIFOCtrlS(FIFOSRC_DFT, bTRUE); //enable FIFO
    		AppBATMeasureRCAL();
        break;
        default:
        break;
      }
      return AD5940ERR_OK;
    }
    
    /* Generate init sequence */
    static AD5940Err AppBATSeqCfgGen(void)
    {
      AD5940Err error = AD5940ERR_OK;
      uint32_t const *pSeqCmd;
      uint32_t SeqLen;
      AFERefCfg_Type aferef_cfg;
      HSLoopCfg_Type hs_loop;
      LPLoopCfg_Type lp_loop;
      DSPCfg_Type dsp_cfg;
    	float sin_freq;
    
      /* Start sequence generator here */
      AD5940_SEQGenCtrl(bTRUE);
    
      AD5940_AFECtrlS(AFECTRL_ALL, bFALSE);  /* Disable all firstly. */
      aferef_cfg.HpBandgapEn = bTRUE;
      aferef_cfg.Hp1V1BuffEn = bTRUE;
      aferef_cfg.Hp1V8BuffEn = bTRUE;
      aferef_cfg.Disc1V1Cap = bFALSE;
      aferef_cfg.Disc1V8Cap = bFALSE;
      aferef_cfg.Hp1V8ThemBuff = bFALSE;
      aferef_cfg.Hp1V8Ilimit = bFALSE;
      aferef_cfg.Lp1V1BuffEn = bFALSE;
      aferef_cfg.Lp1V8BuffEn = bFALSE;
      /* LP reference control, Use LP loop to provide DC Bias voltage. */
      aferef_cfg.LpBandgapEn = bTRUE;
      aferef_cfg.LpRefBufEn = bTRUE;
      aferef_cfg.LpRefBoostEn = bFALSE;
      AD5940_REFCfgS(&aferef_cfg);
      /* Determine buffer gain according to ACVoltPP */
      hs_loop.HsDacCfg.ExcitBufGain = EXCITBUFGAIN_2;
      hs_loop.HsDacCfg.HsDacGain = HSDACGAIN_1;
      hs_loop.HsDacCfg.HsDacUpdateRate = 0x1B; //the maximum update rate is 16MHz/7
    
      hs_loop.HsTiaCfg.DiodeClose = bFALSE;
      hs_loop.HsTiaCfg.HstiaBias = HSTIABIAS_1P1;
      hs_loop.HsTiaCfg.HstiaCtia = 31;  //HSTIA is not used.
      hs_loop.HsTiaCfg.HstiaDeRload = HSTIADERLOAD_OPEN;
      hs_loop.HsTiaCfg.HstiaDeRtia = HSTIADERTIA_OPEN;
      hs_loop.HsTiaCfg.HstiaRtiaSel = HSTIARTIA_10K;
    
      hs_loop.SWMatCfg.Dswitch = SWD_CE0;
      hs_loop.SWMatCfg.Pswitch = SWP_AIN1;
      hs_loop.SWMatCfg.Nswitch = SWN_AIN0;  //AIN0 is connected to AIN4 externally by JP3.
      hs_loop.SWMatCfg.Tswitch = 0; //T switch is not used.
    
      hs_loop.WgCfg.WgType = WGTYPE_SIN;
      hs_loop.WgCfg.GainCalEn = bFALSE;
      hs_loop.WgCfg.OffsetCalEn = bFALSE;
    	if(AppBATCfg.SweepCfg.SweepEn == bTRUE)
      {
        AppBATCfg.FreqofData = AppBATCfg.SweepCfg.SweepStart;
        AppBATCfg.SweepCurrFreq = AppBATCfg.SweepCfg.SweepStart;
    		AD5940_SweepNext(&AppBATCfg.SweepCfg, &AppBATCfg.SweepNextFreq);
    		sin_freq = AppBATCfg.SweepCurrFreq;    
      }
      else
      {
        sin_freq = AppBATCfg.SinFreq;
        AppBATCfg.FreqofData = sin_freq;
      }
      hs_loop.WgCfg.SinCfg.SinFreqWord = AD5940_WGFreqWordCal(sin_freq, AppBATCfg.SysClkFreq);
      hs_loop.WgCfg.SinCfg.SinAmplitudeWord = (uint32_t)(AppBATCfg.ACVoltPP/800.0f*2047 + 0.5f);
      hs_loop.WgCfg.SinCfg.SinOffsetWord = 0;
      hs_loop.WgCfg.SinCfg.SinPhaseWord = 0;
      AD5940_HSLoopCfgS(&hs_loop);
      //Use LP loop to output bias voltage on AIN4 pin, which provides voltage on AIN0(N switch).
      lp_loop.LpDacCfg.LpdacSel = LPDAC0;
      lp_loop.LpDacCfg.LpDacSrc = LPDACSRC_MMR;
      lp_loop.LpDacCfg.LpDacSW = LPDACSW_VZERO2LPTIA|LPDACSW_VZERO2PIN;
      lp_loop.LpDacCfg.LpDacVzeroMux = LPDACVZERO_12BIT;
      lp_loop.LpDacCfg.LpDacVbiasMux = LPDACVBIAS_6BIT;
      lp_loop.LpDacCfg.LpDacRef = LPDACREF_2P5;
      lp_loop.LpDacCfg.DataRst = bFALSE;
      lp_loop.LpDacCfg.PowerEn = bTRUE;
      lp_loop.LpDacCfg.DacData12Bit = (uint32_t)((AppBATCfg.DCVolt-200)/2200.0f*4095);
      lp_loop.LpDacCfg.DacData6Bit = 31;  //not used. Set it to middle value.
    
      lp_loop.LpAmpCfg.LpAmpSel = LPAMP0;
      lp_loop.LpAmpCfg.LpAmpPwrMod = LPAMPPWR_NORM;
      lp_loop.LpAmpCfg.LpPaPwrEn = bFALSE;
      lp_loop.LpAmpCfg.LpTiaPwrEn = bTRUE;
      lp_loop.LpAmpCfg.LpTiaRf = LPTIARF_20K; //External cap is 1uF.
      lp_loop.LpAmpCfg.LpTiaRload = LPTIARLOAD_SHORT;
      lp_loop.LpAmpCfg.LpTiaRtia = LPTIARTIA_OPEN;
      lp_loop.LpAmpCfg.LpTiaSW = LPTIASW(7)|LPTIASW(5)|LPTIASW(9);
      AD5940_LPLoopCfgS(&lp_loop);
    
      dsp_cfg.ADCBaseCfg.ADCMuxN = ADCMUXN_AIN2;
      dsp_cfg.ADCBaseCfg.ADCMuxP = ADCMUXP_AIN3;
      dsp_cfg.ADCBaseCfg.ADCPga = ADCPGA_1P5;
      memset(&dsp_cfg.ADCDigCompCfg, 0, sizeof(dsp_cfg.ADCDigCompCfg));
      dsp_cfg.ADCFilterCfg.ADCAvgNum = ADCAVGNUM_16;  /* Don't care because it's disabled */
      dsp_cfg.ADCFilterCfg.ADCRate = ADCRATE_800KHZ;
      dsp_cfg.ADCFilterCfg.ADCSinc2Osr = AppBATCfg.ADCSinc2Osr;
      dsp_cfg.ADCFilterCfg.ADCSinc3Osr = AppBATCfg.ADCSinc3Osr;
      dsp_cfg.ADCFilterCfg.BpSinc3 = bFALSE;
      dsp_cfg.ADCFilterCfg.BpNotch = bTRUE;
      dsp_cfg.ADCFilterCfg.Sinc2NotchEnable = bTRUE;
      dsp_cfg.DftCfg.DftNum = AppBATCfg.DftNum;
      dsp_cfg.DftCfg.DftSrc = AppBATCfg.DftSrc;
      dsp_cfg.DftCfg.HanWinEn = AppBATCfg.HanWinEn;
      memset(&dsp_cfg.StatCfg, 0, sizeof(dsp_cfg.StatCfg)); /* Don't care about Statistic */
      AD5940_DSPCfgS(&dsp_cfg);
      /* Enable all of them. They are automatically turned off during hibernate mode to save power */
      AD5940_AFECtrlS(AFECTRL_HPREFPWR|AFECTRL_INAMPPWR|AFECTRL_EXTBUFPWR|\
                    AFECTRL_WG|AFECTRL_DACREFPWR|AFECTRL_HSDACPWR|\
                    AFECTRL_SINC2NOTCH, bTRUE);
      /* Sequence end. */
      AD5940_SEQGenInsert(SEQ_STOP()); /* Add one external command to disable sequencer for initialization sequence because we only want it to run one time. */
    
      /* Stop here */
      error = AD5940_SEQGenFetchSeq(&pSeqCmd, &SeqLen);
      AD5940_SEQGenCtrl(bFALSE); /* Stop sequencer generator */
      if(error == AD5940ERR_OK)
      {
        AppBATCfg.InitSeqInfo.SeqId = SEQID_1;
        AppBATCfg.InitSeqInfo.SeqRamAddr = AppBATCfg.SeqStartAddr;
        AppBATCfg.InitSeqInfo.pSeqCmd = pSeqCmd;
        AppBATCfg.InitSeqInfo.SeqLen = SeqLen;
        /* Write command to SRAM */
        AD5940_SEQCmdWrite(AppBATCfg.InitSeqInfo.SeqRamAddr, pSeqCmd, SeqLen);
      }
      else
        return error; /* Error */
      return AD5940ERR_OK;
    }
    
    //the sequence used to measure battery response voltage.
    static AD5940Err AppBATSeqMeasureGen(void)
    {
      AD5940Err error = AD5940ERR_OK;
      uint32_t const *pSeqCmd;
      uint32_t SeqLen;
      uint32_t WaitClks;
      ClksCalInfo_Type clks_cal;
    
      clks_cal.DataType = DATATYPE_DFT;
      clks_cal.DftSrc = AppBATCfg.DftSrc;
      clks_cal.DataCount = 1L<<(AppBATCfg.DftNum+2); /* 2^(DFTNUMBER+2) */
      clks_cal.ADCSinc2Osr = AppBATCfg.ADCSinc2Osr;
      clks_cal.ADCSinc3Osr = AppBATCfg.ADCSinc3Osr;
      clks_cal.ADCAvgNum = 0;
      clks_cal.RatioSys2AdcClk = AppBATCfg.SysClkFreq/AppBATCfg.AdcClkFreq;
      AD5940_ClksCalculate(&clks_cal, &WaitClks);
      /* Start sequence generator here */
      AD5940_SEQGenCtrl(bTRUE);
      AD5940_SEQGenInsert(SEQ_WAIT(16*250));  /* wait 250us for reference power up from hibernate mode. */
      AD5940_AFECtrlS(AFECTRL_WG|AFECTRL_ADCPWR|AFECTRL_SINC2NOTCH, bTRUE);  /* Enable Waveform generator, ADC power */
      AD5940_SEQGenInsert(SEQ_WAIT(16*50));   /* Wait for ADC ready. */
      AD5940_AFECtrlS(AFECTRL_ADCCNV|AFECTRL_DFT, bTRUE);  /* Start ADC convert and DFT */
      AD5940_SEQGenFetchSeq(NULL, &AppBATCfg.SeqWaitAddr[0]); /* Record the start address of the next command. */
    
      AD5940_SEQGenInsert(SEQ_WAIT(WaitClks/2));
       AD5940_SEQGenInsert(SEQ_WAIT(WaitClks/2));  
      AD5940_AFECtrlS(AFECTRL_ADCCNV|AFECTRL_DFT/*|AFECTRL_WG*/|AFECTRL_ADCPWR|AFECTRL_SINC2NOTCH, bFALSE);  /* Stop ADC convert and DFT */
      //AD5940_EnterSleepS();/* Goto hibernate */
      /* Sequence end. */
      error = AD5940_SEQGenFetchSeq(&pSeqCmd, &SeqLen);
      AD5940_SEQGenCtrl(bFALSE); /* Stop sequencer generator */
    
      AppBATCfg.MeasSeqCycleCount = AD5940_SEQCycleTime();
      AppBATCfg.MaxODR = 1/(((AppBATCfg.MeasSeqCycleCount + 10) / 16.0)* 1E-6)  ;
      if(AppBATCfg.BatODR > AppBATCfg.MaxODR)
      {
        /* We have requested a sampling rate that cannot be achieved with the time it
           takes to acquire a sample.
        */
        AppBATCfg.BatODR = AppBATCfg.MaxODR;
      }
    
      if(error == AD5940ERR_OK)
      {
        AppBATCfg.MeasureSeqInfo.SeqId = SEQID_0;
        AppBATCfg.MeasureSeqInfo.SeqRamAddr = AppBATCfg.InitSeqInfo.SeqRamAddr + AppBATCfg.InitSeqInfo.SeqLen ;
        AppBATCfg.MeasureSeqInfo.pSeqCmd = pSeqCmd;
        AppBATCfg.MeasureSeqInfo.SeqLen = SeqLen;
        /* Write command to SRAM */
        AD5940_SEQCmdWrite(AppBATCfg.MeasureSeqInfo.SeqRamAddr, pSeqCmd, SeqLen);
      }
      else
        return error; /* Error */
      return AD5940ERR_OK;
    }
    
    /* This function provide application initialize.   */
    AD5940Err AppBATInit(uint32_t *pBuffer, uint32_t BufferSize)
    {
      AD5940Err error = AD5940ERR_OK;
      SEQCfg_Type seq_cfg;
      FIFOCfg_Type fifo_cfg;
    
      if(AD5940_WakeUp(10) > 10)  /* Wakeup AFE by read register, read 10 times at most */
        return AD5940ERR_WAKEUP;  /* Wakeup Failed */
    
      /* Configure sequencer and stop it */
      seq_cfg.SeqMemSize = SEQMEMSIZE_2KB;  /* 2kB SRAM is used for sequencer, others for data FIFO */
      seq_cfg.SeqBreakEn = bFALSE;
      seq_cfg.SeqIgnoreEn = bFALSE;
      seq_cfg.SeqCntCRCClr = bTRUE;
      seq_cfg.SeqEnable = bFALSE;
      seq_cfg.SeqWrTimer = 0;
      AD5940_SEQCfg(&seq_cfg);
    
      /* Reconfigure FIFO */
      AD5940_FIFOCtrlS(FIFOSRC_DFT, bFALSE);									/* Disable FIFO firstly */
      fifo_cfg.FIFOEn = bTRUE;
      fifo_cfg.FIFOMode = FIFOMODE_FIFO;
      fifo_cfg.FIFOSize = FIFOSIZE_4KB;                       /* 4kB for FIFO, The reset 2kB for sequencer */
      fifo_cfg.FIFOSrc = FIFOSRC_DFT;
      fifo_cfg.FIFOThresh = AppBATCfg.FifoThresh;              /* DFT result. One pair for RCAL, another for Rz. One DFT result have real part and imaginary part */
      AD5940_FIFOCfg(&fifo_cfg);
    
      AD5940_INTCClrFlag(AFEINTSRC_ALLINT);
      
      /* Start sequence generator */
      /* Initialize sequencer generator */
      if((AppBATCfg.BATInited == bFALSE)||\
           (AppBATCfg.bParaChanged == bTRUE))
      {
        if(pBuffer == 0)  return AD5940ERR_PARA;
        if(BufferSize == 0) return AD5940ERR_PARA;   
        AD5940_SEQGenInit(pBuffer, BufferSize);
        /* Generate initialize sequence */
        error = AppBATSeqCfgGen(); /* Application initialization sequence using either MCU or sequencer */
        if(error != AD5940ERR_OK) return error;
        /* Generate measurement sequence */
        error = AppBATSeqMeasureGen();
        if(error != AD5940ERR_OK) return error;
        AppBATCfg.bParaChanged = bFALSE; /* Clear this flag as we already implemented the new configuration */
      }
      /* Initialization sequencer  */
      AppBATCfg.InitSeqInfo.WriteSRAM = bFALSE;
      AD5940_SEQInfoCfg(&AppBATCfg.InitSeqInfo);
      seq_cfg.SeqEnable = bTRUE;
      AD5940_SEQCfg(&seq_cfg);  /* Enable sequencer */
      AD5940_SEQMmrTrig(AppBATCfg.InitSeqInfo.SeqId);
      while(AD5940_INTCTestFlag(AFEINTC_1, AFEINTSRC_ENDSEQ) == bFALSE);
      
    	AppBATCheckFreq(AppBATCfg.SweepCfg.SweepStart);
      /* Measurement sequence  */
      AppBATCfg.MeasureSeqInfo.WriteSRAM = bFALSE;
      AD5940_SEQInfoCfg(&AppBATCfg.MeasureSeqInfo);
      seq_cfg.SeqEnable = bTRUE;
      AD5940_SEQCfg(&seq_cfg);  /* Enable sequencer, and wait for trigger */
      AD5940_ClrMCUIntFlag();   /* Clear interrupt flag generated before */
      AD5940_AFEPwrBW(AppBATCfg.PwrMod, AFEBW_250KHZ);
      AD5940_WriteReg(REG_AFE_SWMUX, 1<<1);
      AppBATCfg.BATInited = bTRUE;  /* BAT application has been initialized. */
      return AD5940ERR_OK;
    }
    
    /* Depending on frequency of Sin wave set optimum filter settings */
    AD5940Err AppBATCheckFreq(float freq)
    {
    	ADCFilterCfg_Type filter_cfg;
      DFTCfg_Type dft_cfg;
      HSDACCfg_Type hsdac_cfg;
      uint32_t WaitClks;
      ClksCalInfo_Type clks_cal;
      FreqParams_Type freq_params;
      uint32_t SeqCmdBuff[32];
      uint32_t SRAMAddr = 0;;
      /* Step 1: Check Frequency */
      freq_params = AD5940_GetFreqParameters(freq);
      
           if(freq < 0.51)
    	{
    	hsdac_cfg.ExcitBufGain = EXCITBUFGAIN_2;
        hsdac_cfg.HsDacGain = HSDACGAIN_1;
        hsdac_cfg.HsDacUpdateRate = 0x1B;
        AD5940_HSDacCfgS(&hsdac_cfg);
        AD5940_HSRTIACfgS(HSTIARTIA_40K);
        
        /*Update ADC rate */
        filter_cfg.ADCRate = ADCRATE_800KHZ;
        AppBATCfg.AdcClkFreq = 16e6;
        
        /* Change clock to 16MHz oscillator */
        AD5940_HPModeEn(bFALSE);
    	}
            else if(freq < 5 )
    	{
    	hsdac_cfg.ExcitBufGain = EXCITBUFGAIN_2;
        hsdac_cfg.HsDacGain = HSDACGAIN_1;
        hsdac_cfg.HsDacUpdateRate = 0x1B;
        AD5940_HSDacCfgS(&hsdac_cfg);
        AD5940_HSRTIACfgS(HSTIARTIA_40K);
        
        /*Update ADC rate */
        filter_cfg.ADCRate = ADCRATE_800KHZ;
        AppBATCfg.AdcClkFreq = 16e6;
        
        /* Change clock to 16MHz oscillator */
        AD5940_HPModeEn(bFALSE);
        
    	}else if(freq < 450)
    	{
        hsdac_cfg.ExcitBufGain = EXCITBUFGAIN_2;
        hsdac_cfg.HsDacGain = HSDACGAIN_1;
        hsdac_cfg.HsDacUpdateRate = 0x1B;
        AD5940_HSDacCfgS(&hsdac_cfg);
        AD5940_HSRTIACfgS(HSTIARTIA_5K);
        
        /*Update ADC rate */
        filter_cfg.ADCRate = ADCRATE_800KHZ;
        AppBATCfg.AdcClkFreq = 16e6;
        
        /* Change clock to 16MHz oscillator */
        AD5940_HPModeEn(bFALSE);
    	}
           else if(freq<80000)
           {
    	hsdac_cfg.ExcitBufGain = EXCITBUFGAIN_2;
        hsdac_cfg.HsDacGain = HSDACGAIN_1;
        hsdac_cfg.HsDacUpdateRate = 0x1B;
        AD5940_HSDacCfgS(&hsdac_cfg);
        AD5940_HSRTIACfgS(HSTIARTIA_5K);
        
        /*Update ADC rate */
        filter_cfg.ADCRate = ADCRATE_800KHZ;
        AppBATCfg.AdcClkFreq = 16e6;
        
        /* Change clock to 16MHz oscillator */
        AD5940_HPModeEn(bFALSE);
           }
            /* High power mode */
    	if(freq >= 80000)
    	{
    	hsdac_cfg.ExcitBufGain = EXCITBUFGAIN_2;
        hsdac_cfg.HsDacGain = HSDACGAIN_1;
        hsdac_cfg.HsDacUpdateRate = 0x07;
        AD5940_HSDacCfgS(&hsdac_cfg);
        AD5940_HSRTIACfgS(HSTIARTIA_5K);
        
        /*Update ADC rate */
        filter_cfg.ADCRate = ADCRATE_1P6MHZ;
        AppBATCfg.AdcClkFreq = 32e6;
        
        /* Change clock to 32MHz oscillator */
        AD5940_HPModeEn(bTRUE);
    	}
      
      /* Step 2: Adjust ADCFILTERCON and DFTCON to set optimumn SINC3, SINC2 and DFTNUM settings  */
      filter_cfg.ADCAvgNum = ADCAVGNUM_16;  /* Don't care because it's disabled */ 
      filter_cfg.ADCSinc2Osr = freq_params.ADCSinc2Osr;
      filter_cfg.ADCSinc3Osr = freq_params.ADCSinc3Osr;
      filter_cfg.BpSinc3 = bFALSE;
      filter_cfg.BpNotch = bTRUE;
      filter_cfg.Sinc2NotchEnable = bTRUE;
      dft_cfg.DftNum = freq_params.DftNum;
      dft_cfg.DftSrc = freq_params.DftSrc;
      dft_cfg.HanWinEn = AppBATCfg.HanWinEn;
      AD5940_ADCFilterCfgS(&filter_cfg);
      AD5940_DFTCfgS(&dft_cfg);
      
      /* Step 3: Calculate clocks needed to get result to FIFO and update sequencer wait command */
      clks_cal.DataType = DATATYPE_DFT;
      clks_cal.DftSrc = freq_params.DftSrc;
      clks_cal.DataCount = 1L<<(freq_params.DftNum+2); /* 2^(DFTNUMBER+2) */
      clks_cal.ADCSinc2Osr = freq_params.ADCSinc2Osr;
      clks_cal.ADCSinc3Osr = freq_params.ADCSinc3Osr;
      clks_cal.ADCAvgNum = 0;
      clks_cal.RatioSys2AdcClk = AppBATCfg.SysClkFreq/AppBATCfg.AdcClkFreq;
      AD5940_ClksCalculate(&clks_cal, &WaitClks);		
    	
    	
    	  SRAMAddr = AppBATCfg.MeasureSeqInfo.SeqRamAddr + AppBATCfg.SeqWaitAddr[0];
    	   
               SeqCmdBuff[0] =SEQ_WAIT(WaitClks/2);
               SeqCmdBuff[1] =SEQ_WAIT(WaitClks/2);
          
    		AD5940_SEQCmdWrite(SRAMAddr, SeqCmdBuff, 2);
    		
      return AD5940ERR_OK;
    }

    /*AD5940Main.c*/
    #include "ad5940.h"
    #include <stdio.h>
    #include "string.h"
    #include "math.h"
    #include "BATImpedance.h"
    
    #define APPBUFF_SIZE 512
    uint32_t AppBuff[APPBUFF_SIZE];
    
    /* It's your choice here how to do with the data. Here is just an example to print them to UART */
    int32_t BATShowResult(uint32_t *pData, uint32_t DataCount)
    {
      fImpCar_Type *pImp = (fImpCar_Type*)pData;
    	float freq;
    	AppBATCtrl(BATCTRL_GETFREQ, &freq);
      /*Process data*/
      for(int i=0;i<DataCount;i++)
      {
        printf("Freq: %f (real, image) = ,%f , %f ,mOhm \n",freq, pImp[i].Real,pImp[i].Image);
      }
      return 0;
    }
    
    /* Initialize AD5940 basic blocks like clock */
    static int32_t AD5940PlatformCfg(void)
    {
      CLKCfg_Type clk_cfg;
      FIFOCfg_Type fifo_cfg;
      AGPIOCfg_Type gpio_cfg;
      /* Use hardware reset */
      AD5940_HWReset();
      /* Platform configuration */
      AD5940_Initialize();
      /* Step1. Configure clock */
      clk_cfg.ADCClkDiv = ADCCLKDIV_1;
      clk_cfg.ADCCLkSrc = ADCCLKSRC_HFOSC;
      clk_cfg.SysClkDiv = SYSCLKDIV_1;
      clk_cfg.SysClkSrc = SYSCLKSRC_HFOSC; //on battery board, there is a 32MHz crystal.
      clk_cfg.HfOSC32MHzMode = bFALSE;
      clk_cfg.HFOSCEn = bTRUE;
      clk_cfg.HFXTALEn = bFALSE;
      clk_cfg.LFOSCEn = bTRUE;
      AD5940_CLKCfg(&clk_cfg);
      /* Step2. Configure FIFO and Sequencer*/
      fifo_cfg.FIFOEn = bFALSE;
      fifo_cfg.FIFOMode = FIFOMODE_FIFO;
      fifo_cfg.FIFOSize = FIFOSIZE_4KB;                       /* 4kB for FIFO, The reset 2kB for sequencer */
      fifo_cfg.FIFOSrc = FIFOSRC_DFT;
      fifo_cfg.FIFOThresh = 4;//AppBATCfg.FifoThresh;        /* DFT result. One pair for RCAL, another for Rz. One DFT result have real part and imaginary part */
      AD5940_FIFOCfg(&fifo_cfg);                             /* Disable to reset FIFO. */
      fifo_cfg.FIFOEn = bTRUE;  
      AD5940_FIFOCfg(&fifo_cfg);                             /* Enable FIFO here */
      
      /* Step3. Interrupt controller */
      AD5940_INTCCfg(AFEINTC_1, AFEINTSRC_ALLINT, bTRUE);           /* Enable all interrupt in Interrupt Controller 1, so we can check INTC flags */
      AD5940_INTCCfg(AFEINTC_0, AFEINTSRC_DATAFIFOTHRESH, bTRUE);   /* Interrupt Controller 0 will control GP0 to generate interrupt to MCU */
      AD5940_INTCClrFlag(AFEINTSRC_ALLINT);
      /* Step4: Reconfigure GPIO */
      gpio_cfg.FuncSet = GP0_INT|GP2_SYNC;
      gpio_cfg.InputEnSet = AGPIO_Pin2;
      gpio_cfg.OutputEnSet = AGPIO_Pin0|AGPIO_Pin2;
      gpio_cfg.OutVal = 0;
      gpio_cfg.PullEnSet = 0;
      AD5940_AGPIOCfg(&gpio_cfg);
      AD5940_SleepKeyCtrlS(SLPKEY_UNLOCK);  /* Allow AFE to enter sleep mode. */
      return 0;
    }
    
    void AD5940BATStructInit(void)
    {
      AppBATCfg_Type *pBATCfg;
      AppBATGetCfg(&pBATCfg);
      pBATCfg->SeqStartAddr = 0;
      pBATCfg->MaxSeqLen = 512;
      pBATCfg->RcalVal = 50.0;  							/* Value of RCAL on EVAL-AD5941BATZ board is 50mOhm */
      pBATCfg->ACVoltPP = 300.0f;							/* Pk-pk amplitude is 300mV */
      pBATCfg->DCVolt = 1200.0f;							/* Offset voltage of 1.2V*/
      pBATCfg->DftNum = DFTNUM_8192;
      
      pBATCfg->FifoThresh = 2;      					/* 2 results in FIFO, real and imaginary part. */
    	
    	pBATCfg->SinFreq = 200;									/* Sin wave frequency. THis value has no effect if sweep is enabled */
    	
    	pBATCfg->SweepCfg.SweepEn = bTRUE;			/* Set to bTRUE to enable sweep function */
    	pBATCfg->SweepCfg.SweepStart = 1.0f;		/* Start sweep at 1Hz  */
    	pBATCfg->SweepCfg.SweepStop = 50000.0f;	/* Finish sweep at 1000Hz */
    	pBATCfg->SweepCfg.SweepPoints = 50;			/* 100 frequencies in the sweep */
    	pBATCfg->SweepCfg.SweepLog = bTRUE;			/* Set to bTRUE to use LOG scale. Set bFALSE to use linear scale */
    	
    }
    
    void AD5940_Main(void)
    {
      uint32_t temp;
      AD5940PlatformCfg();
      
      AD5940BATStructInit(); /* Configure your parameters in this function */
      
      AppBATInit(AppBuff, APPBUFF_SIZE);    /* Initialize BAT application. Provide a buffer, which is used to store sequencer commands */
      AppBATCtrl(BATCTRL_MRCAL, 0);     /* Measur RCAL each point in sweep */
    	AppBATCtrl(BATCTRL_START, 0); 
      while(1)
      {
        /* Check if interrupt flag which will be set when interrupt occurred. */
        if(AD5940_GetMCUIntFlag())
        {
    				AD5940_ClrMCUIntFlag(); 				/* Clear this flag */
    				temp = APPBUFF_SIZE;
    				AppBATISR(AppBuff, &temp); 			/* Deal with it and provide a buffer to store data we got */
    				AD5940_Delay10us(100000);
    				BATShowResult(AppBuff, temp);		/* Print measurement results over UART */		
    				AD5940_SEQMmrTrig(SEQID_0);  		/* Trigger next measurement ussing MMR write*/      
       }
      }
    }

    #ifndef _BAT_IMPEDANCE_H_
    #define _BAT_IMPEDANCE_H_
    #include "ad5940.h"
    #include "stdio.h"
    #include "string.h"
    #include "math.h"
    
    #define PRECHARGE_WAIT_MS   4000    //precharge time in ms.
    
    #define PRECHARGE_CH1       1
    #define PRECHARGE_CH2       2
    #define PRECHARGE_CH3       3
    
    #define PRECHARGE_RCAL      PRECHARGE_CH1
    #define PRECHARGE_BAT       PRECHARGE_CH2
    #define PRECHARGE_AMP       PRECHARGE_CH3
    /* 
      Note: this example will use SEQID_0 as measurement sequence, and use SEQID_1 as init sequence. 
      SEQID_3 is used for calibration.
    */
    
    #define STATE_IDLE        0   /**< Initial state. */
    #define STATE_RCAL        1   /**< Measure Rcal response voltage. */
    #define STATE_BATTERY     2   /**< Measure battery response voltage. */
    typedef struct
    {
    /* Common configurations for all kinds of Application. */
      uint32_t state;               /* 0: Init, 1: measure Rcal, 2: Measure Battery. */
      BoolFlag bParaChanged;        /* Indicate to generate sequence again. It's auto cleared by AppBATInit */
      BoolFlag bDoCal;              /* Need to do calibration. */
      uint32_t SeqStartAddr;        /* Initialaztion sequence start address in SRAM of AD5940  */
      uint32_t MaxSeqLen;           /* Limit the maximum sequence.   */
      uint32_t SeqStartAddrCal;     /* Measurement sequence start address in SRAM of AD5940 */
      uint32_t MaxSeqLenCal;
    /* Application related parameters */ 
      float SysClkFreq;             /* The real frequency of system clock */
      float WuptClkFreq;            /* The clock frequency of Wakeup Timer in Hz. Typically it's 32kHz. Leave it here in case we calibrate clock in software method */
      float AdcClkFreq;             /* The real frequency of ADC clock */
      uint32_t FifoThresh;           /* FIFO threshold. Should be N*4 */   
      float BatODR;                 /* in Hz. ODR decides the period of WakeupTimer who will trigger sequencer periodically. DFT number and sample frequency decides the maxim ODR. */
      int32_t NumOfData;            /* By default it's '-1'. If you want the engine stops after get NumofData, then set the value here. Otherwise, set it to '-1' which means never stop. */
      uint32_t PwrMod;              /* Control Chip power mode(LP/HP) */
      float ACVoltPP;               /* Final AC excitation voltage on pin AIN1 in mV peak to peak unit. */
      float DCVolt;                 /* The DC bias voltage on AIN1 pin. Unit is mV. */
      float RcalVal;                /* Rcal value in mOhm */
      float SinFreq;                /* Frequency of excitation signal */
      uint8_t ADCSinc3Osr;          /* SINC3 OSR selection. ADCSINC3OSR_2, ADCSINC3OSR_4 */
      uint8_t ADCSinc2Osr;          /* SINC2 OSR selection. ADCSINC2OSR_22...ADCSINC2OSR_1333 */
      uint32_t DftNum;              /* DFT number */
      uint32_t DftSrc;              /* DFT Source */
      BoolFlag HanWinEn;            /* Enable Hanning window */
      uint32_t SeqWaitAddr[3];    
    /* Sweep Function Control */
      SoftSweepCfg_Type SweepCfg;
    /* Private variables for internal usage */
      float SweepCurrFreq;
      float SweepNextFreq;
      float FreqofData;  
      BoolFlag BATInited;           /* If the program run firstly, generated sequence commands */
      SEQInfo_Type InitSeqInfo;
      SEQInfo_Type MeasureSeqInfo;
      BoolFlag StopRequired;        /* After FIFO is ready, stop the measurement sequence */
      uint32_t FifoDataCount;       /* Count how many times impedance have been measured */
      uint32_t MeasSeqCycleCount;   /* How long the measurement sequence will take */
      float MaxODR;                 /* Max ODR for sampling in this config */
      fImpCar_Type RcalVolt;        /* The measured Rcal resistor(R1) response voltage. */
      float RcalVoltTable[100][2];    
    /* End */
    }AppBATCfg_Type;
    
    #define BATCTRL_START          0
    #define BATCTRL_STOPNOW        1
    #define BATCTRL_STOPSYNC       2
    #define BATCTRL_SHUTDOWN       4   /* Note: shutdown here means turn off everything and put AFE to hibernate mode. The word 'SHUT DOWN' is only used here. */
    #define BATCTRL_MRCAL          5   /* Measure RCAL response voltage */
    #define BATCTRL_GETFREQ				 6
    
    AD5940Err AppBATGetCfg(void *pCfg);
    AD5940Err AppBATInit(uint32_t *pBuffer, uint32_t BufferSize);
    AD5940Err AppBATISR(void *pBuff, uint32_t *pCount);
    AD5940Err AppBATCtrl(int32_t BatCtrl, void *pPara);
    AD5940Err AppBATCheckFreq(float freq);
    AD5940Err AppBATMeasureRCAL(void);
    
    #endif

Reply
  • Hi,

    Could you please check with the below code:

    /*BATImpedance.c*/
    #include "BATImpedance.h"
    
    /* 
      Application configuration structure. Specified by user from template.
      The variables are usable in this whole application.
      It includes basic configuration for sequencer generator and application related parameters
    */
    AppBATCfg_Type AppBATCfg = 
    {
      .state = STATE_IDLE,
      .bParaChanged = bFALSE,
      .SeqStartAddr = 0,
      .MaxSeqLen = 0,
      
      .SeqStartAddrCal = 0,
      .MaxSeqLenCal = 0,
    
      .SysClkFreq = 16000000.0,
      .WuptClkFreq = 32000.0,
      .AdcClkFreq = 16000000.0,
      .BatODR = 20.0, /* 20.0 Hz*/
      .NumOfData = -1,
    
      .PwrMod = AFEPWR_LP,
      .ACVoltPP = 800.0,
      .DCVolt = 1100.0f,
      .SinFreq = 50000.0, /* 50kHz */
      .RcalVal = 50.0, /* 50mOhm */
    
      .ADCSinc3Osr = ADCSINC3OSR_4,
      .ADCSinc2Osr = ADCSINC2OSR_22,
    
      .DftNum = DFTNUM_16384,
      .DftSrc = DFTSRC_SINC3,
      .HanWinEn = bTRUE,
    
      .FifoThresh = 4,
      .BATInited = bFALSE,
      .StopRequired = bFALSE,
      .MeasSeqCycleCount = 0,
    	
    	.SweepCfg.SweepEn = bTRUE,
      .SweepCfg.SweepStart = 1000,
      .SweepCfg.SweepStop = 100000.0,
      .SweepCfg.SweepPoints = 101,
      .SweepCfg.SweepLog = bFALSE,
      .SweepCfg.SweepIndex = 0,
    };
    
    /**
       This function is provided for upper controllers that want to change 
       application parameters specially for user defined parameters.
    */
    AD5940Err AppBATGetCfg(void *pCfg)
    {
      if(pCfg){
        *(AppBATCfg_Type**)pCfg = &AppBATCfg;
        return AD5940ERR_OK;
      }
      return AD5940ERR_PARA;
    }
    
    
    static void PreCharge(unsigned char channel) 
    {
      void Arduino_WriteDn(uint32_t Dn, BoolFlag bHigh);
      switch(channel)
      {
        case PRECHARGE_CH1: //00
        Arduino_WriteDn(1<<3, bFALSE);  //d3
        Arduino_WriteDn(1<<4, bFALSE);  //d4
        break;
        case PRECHARGE_CH2: //01
        Arduino_WriteDn(1<<3, bTRUE);
        Arduino_WriteDn(1<<4, bFALSE);
        break;
        case PRECHARGE_CH3://10
        Arduino_WriteDn(1<<3, bFALSE);
        Arduino_WriteDn(1<<4, bTRUE);
        break;
        default:
        break;
      }
      AD5940_Delay10us(PRECHARGE_WAIT_MS*100);
      Arduino_WriteDn(1<<3, bTRUE);  //d3
      Arduino_WriteDn(1<<4, bTRUE);  //d4
    }
    
    AD5940Err AppBATCtrl(int32_t BatCtrl, void *pPara)
    {
      switch (BatCtrl)
      {
        case BATCTRL_START:
        {
          if(AD5940_WakeUp(10) > 10)  /* Wakeup AFE by read register, read 10 times at most */
            return AD5940ERR_WAKEUP;  /* Wakeup Failed */
          if(AppBATCfg.BATInited == bFALSE)
            return AD5940ERR_APPERROR;
          AD5940_WriteReg(REG_AFE_SWMUX, 1<<0); 				/* control ADG636 to measure battery */
    			AD5940_WriteReg(REG_AFE_SYNCEXTDEVICE, 0x0);
          PreCharge(PRECHARGE_BAT);
          PreCharge(PRECHARGE_AMP);
          AD5940_FIFOCtrlS(FIFOSRC_DFT, bFALSE);
          AD5940_FIFOThrshSet(AppBATCfg.FifoThresh);  /* DFT result contains both real and image. */
          AD5940_FIFOCtrlS(FIFOSRC_DFT, bTRUE);
    			AppBATCfg.state = STATE_BATTERY;
          /* Trigger sequence using MMR write */
    			AD5940_SEQMmrTrig(SEQID_0);
          AppBATCfg.FifoDataCount = 0;  /* restart */
          
          break;
        }
        case BATCTRL_STOPNOW:
        {
          if(AD5940_WakeUp(10) > 10)  /* Wakeup AFE by read register, read 10 times at most */
            return AD5940ERR_WAKEUP;  /* Wakeup Failed */
          /* Start Wupt right now */
          AD5940_WUPTCtrl(bFALSE);
          /* There is chance this operation will fail because sequencer could put AFE back 
            to hibernate mode just after waking up. Use STOPSYNC is better. */
          AD5940_WUPTCtrl(bFALSE);
          break;
        }
        case BATCTRL_STOPSYNC:
        {
          AppBATCfg.StopRequired = bTRUE;
          break;
        }
    		case BATCTRL_GETFREQ:
        if(pPara)
        {
          if(AppBATCfg.SweepCfg.SweepEn == bTRUE)
            *(float*)pPara = AppBATCfg.FreqofData;
          else
            *(float*)pPara = AppBATCfg.SinFreq;
        }
    		break;
        case BATCTRL_SHUTDOWN:
        {
          AppBATCtrl(BATCTRL_STOPNOW, 0);  /* Stop the measurement if it's running. */
          /* Turn off LPloop related blocks which are not controlled automatically by sleep operation */
          AFERefCfg_Type aferef_cfg;
          LPLoopCfg_Type lp_loop;
          memset(&aferef_cfg, 0, sizeof(aferef_cfg));
          AD5940_REFCfgS(&aferef_cfg);
          memset(&lp_loop, 0, sizeof(lp_loop));
          AD5940_LPLoopCfgS(&lp_loop);
          AD5940_EnterSleepS();  /* Enter Hibernate */
        }
        break;
        case BATCTRL_MRCAL:
        if(AD5940_WakeUp(10) > 10)
            return AD5940ERR_WAKEUP;
        //Settle input RC filter.
        AD5940_WriteReg(REG_AFE_SWMUX, 0); //control ADG636 to measure rcal
    		AD5940_WriteReg(REG_AFE_SYNCEXTDEVICE, 0x4);
        PreCharge(PRECHARGE_RCAL);
        PreCharge(PRECHARGE_AMP);
        AD5940_FIFOCtrlS(FIFOSRC_DFT, bFALSE);
    		AD5940_FIFOThrshSet(2);
        AD5940_FIFOCtrlS(FIFOSRC_DFT, bTRUE); //enable FIFO
    		AppBATMeasureRCAL();
        break;
        default:
        break;
      }
      return AD5940ERR_OK;
    }
    
    /* Generate init sequence */
    static AD5940Err AppBATSeqCfgGen(void)
    {
      AD5940Err error = AD5940ERR_OK;
      uint32_t const *pSeqCmd;
      uint32_t SeqLen;
      AFERefCfg_Type aferef_cfg;
      HSLoopCfg_Type hs_loop;
      LPLoopCfg_Type lp_loop;
      DSPCfg_Type dsp_cfg;
    	float sin_freq;
    
      /* Start sequence generator here */
      AD5940_SEQGenCtrl(bTRUE);
    
      AD5940_AFECtrlS(AFECTRL_ALL, bFALSE);  /* Disable all firstly. */
      aferef_cfg.HpBandgapEn = bTRUE;
      aferef_cfg.Hp1V1BuffEn = bTRUE;
      aferef_cfg.Hp1V8BuffEn = bTRUE;
      aferef_cfg.Disc1V1Cap = bFALSE;
      aferef_cfg.Disc1V8Cap = bFALSE;
      aferef_cfg.Hp1V8ThemBuff = bFALSE;
      aferef_cfg.Hp1V8Ilimit = bFALSE;
      aferef_cfg.Lp1V1BuffEn = bFALSE;
      aferef_cfg.Lp1V8BuffEn = bFALSE;
      /* LP reference control, Use LP loop to provide DC Bias voltage. */
      aferef_cfg.LpBandgapEn = bTRUE;
      aferef_cfg.LpRefBufEn = bTRUE;
      aferef_cfg.LpRefBoostEn = bFALSE;
      AD5940_REFCfgS(&aferef_cfg);
      /* Determine buffer gain according to ACVoltPP */
      hs_loop.HsDacCfg.ExcitBufGain = EXCITBUFGAIN_2;
      hs_loop.HsDacCfg.HsDacGain = HSDACGAIN_1;
      hs_loop.HsDacCfg.HsDacUpdateRate = 0x1B; //the maximum update rate is 16MHz/7
    
      hs_loop.HsTiaCfg.DiodeClose = bFALSE;
      hs_loop.HsTiaCfg.HstiaBias = HSTIABIAS_1P1;
      hs_loop.HsTiaCfg.HstiaCtia = 31;  //HSTIA is not used.
      hs_loop.HsTiaCfg.HstiaDeRload = HSTIADERLOAD_OPEN;
      hs_loop.HsTiaCfg.HstiaDeRtia = HSTIADERTIA_OPEN;
      hs_loop.HsTiaCfg.HstiaRtiaSel = HSTIARTIA_10K;
    
      hs_loop.SWMatCfg.Dswitch = SWD_CE0;
      hs_loop.SWMatCfg.Pswitch = SWP_AIN1;
      hs_loop.SWMatCfg.Nswitch = SWN_AIN0;  //AIN0 is connected to AIN4 externally by JP3.
      hs_loop.SWMatCfg.Tswitch = 0; //T switch is not used.
    
      hs_loop.WgCfg.WgType = WGTYPE_SIN;
      hs_loop.WgCfg.GainCalEn = bFALSE;
      hs_loop.WgCfg.OffsetCalEn = bFALSE;
    	if(AppBATCfg.SweepCfg.SweepEn == bTRUE)
      {
        AppBATCfg.FreqofData = AppBATCfg.SweepCfg.SweepStart;
        AppBATCfg.SweepCurrFreq = AppBATCfg.SweepCfg.SweepStart;
    		AD5940_SweepNext(&AppBATCfg.SweepCfg, &AppBATCfg.SweepNextFreq);
    		sin_freq = AppBATCfg.SweepCurrFreq;    
      }
      else
      {
        sin_freq = AppBATCfg.SinFreq;
        AppBATCfg.FreqofData = sin_freq;
      }
      hs_loop.WgCfg.SinCfg.SinFreqWord = AD5940_WGFreqWordCal(sin_freq, AppBATCfg.SysClkFreq);
      hs_loop.WgCfg.SinCfg.SinAmplitudeWord = (uint32_t)(AppBATCfg.ACVoltPP/800.0f*2047 + 0.5f);
      hs_loop.WgCfg.SinCfg.SinOffsetWord = 0;
      hs_loop.WgCfg.SinCfg.SinPhaseWord = 0;
      AD5940_HSLoopCfgS(&hs_loop);
      //Use LP loop to output bias voltage on AIN4 pin, which provides voltage on AIN0(N switch).
      lp_loop.LpDacCfg.LpdacSel = LPDAC0;
      lp_loop.LpDacCfg.LpDacSrc = LPDACSRC_MMR;
      lp_loop.LpDacCfg.LpDacSW = LPDACSW_VZERO2LPTIA|LPDACSW_VZERO2PIN;
      lp_loop.LpDacCfg.LpDacVzeroMux = LPDACVZERO_12BIT;
      lp_loop.LpDacCfg.LpDacVbiasMux = LPDACVBIAS_6BIT;
      lp_loop.LpDacCfg.LpDacRef = LPDACREF_2P5;
      lp_loop.LpDacCfg.DataRst = bFALSE;
      lp_loop.LpDacCfg.PowerEn = bTRUE;
      lp_loop.LpDacCfg.DacData12Bit = (uint32_t)((AppBATCfg.DCVolt-200)/2200.0f*4095);
      lp_loop.LpDacCfg.DacData6Bit = 31;  //not used. Set it to middle value.
    
      lp_loop.LpAmpCfg.LpAmpSel = LPAMP0;
      lp_loop.LpAmpCfg.LpAmpPwrMod = LPAMPPWR_NORM;
      lp_loop.LpAmpCfg.LpPaPwrEn = bFALSE;
      lp_loop.LpAmpCfg.LpTiaPwrEn = bTRUE;
      lp_loop.LpAmpCfg.LpTiaRf = LPTIARF_20K; //External cap is 1uF.
      lp_loop.LpAmpCfg.LpTiaRload = LPTIARLOAD_SHORT;
      lp_loop.LpAmpCfg.LpTiaRtia = LPTIARTIA_OPEN;
      lp_loop.LpAmpCfg.LpTiaSW = LPTIASW(7)|LPTIASW(5)|LPTIASW(9);
      AD5940_LPLoopCfgS(&lp_loop);
    
      dsp_cfg.ADCBaseCfg.ADCMuxN = ADCMUXN_AIN2;
      dsp_cfg.ADCBaseCfg.ADCMuxP = ADCMUXP_AIN3;
      dsp_cfg.ADCBaseCfg.ADCPga = ADCPGA_1P5;
      memset(&dsp_cfg.ADCDigCompCfg, 0, sizeof(dsp_cfg.ADCDigCompCfg));
      dsp_cfg.ADCFilterCfg.ADCAvgNum = ADCAVGNUM_16;  /* Don't care because it's disabled */
      dsp_cfg.ADCFilterCfg.ADCRate = ADCRATE_800KHZ;
      dsp_cfg.ADCFilterCfg.ADCSinc2Osr = AppBATCfg.ADCSinc2Osr;
      dsp_cfg.ADCFilterCfg.ADCSinc3Osr = AppBATCfg.ADCSinc3Osr;
      dsp_cfg.ADCFilterCfg.BpSinc3 = bFALSE;
      dsp_cfg.ADCFilterCfg.BpNotch = bTRUE;
      dsp_cfg.ADCFilterCfg.Sinc2NotchEnable = bTRUE;
      dsp_cfg.DftCfg.DftNum = AppBATCfg.DftNum;
      dsp_cfg.DftCfg.DftSrc = AppBATCfg.DftSrc;
      dsp_cfg.DftCfg.HanWinEn = AppBATCfg.HanWinEn;
      memset(&dsp_cfg.StatCfg, 0, sizeof(dsp_cfg.StatCfg)); /* Don't care about Statistic */
      AD5940_DSPCfgS(&dsp_cfg);
      /* Enable all of them. They are automatically turned off during hibernate mode to save power */
      AD5940_AFECtrlS(AFECTRL_HPREFPWR|AFECTRL_INAMPPWR|AFECTRL_EXTBUFPWR|\
                    AFECTRL_WG|AFECTRL_DACREFPWR|AFECTRL_HSDACPWR|\
                    AFECTRL_SINC2NOTCH, bTRUE);
      /* Sequence end. */
      AD5940_SEQGenInsert(SEQ_STOP()); /* Add one external command to disable sequencer for initialization sequence because we only want it to run one time. */
    
      /* Stop here */
      error = AD5940_SEQGenFetchSeq(&pSeqCmd, &SeqLen);
      AD5940_SEQGenCtrl(bFALSE); /* Stop sequencer generator */
      if(error == AD5940ERR_OK)
      {
        AppBATCfg.InitSeqInfo.SeqId = SEQID_1;
        AppBATCfg.InitSeqInfo.SeqRamAddr = AppBATCfg.SeqStartAddr;
        AppBATCfg.InitSeqInfo.pSeqCmd = pSeqCmd;
        AppBATCfg.InitSeqInfo.SeqLen = SeqLen;
        /* Write command to SRAM */
        AD5940_SEQCmdWrite(AppBATCfg.InitSeqInfo.SeqRamAddr, pSeqCmd, SeqLen);
      }
      else
        return error; /* Error */
      return AD5940ERR_OK;
    }
    
    //the sequence used to measure battery response voltage.
    static AD5940Err AppBATSeqMeasureGen(void)
    {
      AD5940Err error = AD5940ERR_OK;
      uint32_t const *pSeqCmd;
      uint32_t SeqLen;
      uint32_t WaitClks;
      ClksCalInfo_Type clks_cal;
    
      clks_cal.DataType = DATATYPE_DFT;
      clks_cal.DftSrc = AppBATCfg.DftSrc;
      clks_cal.DataCount = 1L<<(AppBATCfg.DftNum+2); /* 2^(DFTNUMBER+2) */
      clks_cal.ADCSinc2Osr = AppBATCfg.ADCSinc2Osr;
      clks_cal.ADCSinc3Osr = AppBATCfg.ADCSinc3Osr;
      clks_cal.ADCAvgNum = 0;
      clks_cal.RatioSys2AdcClk = AppBATCfg.SysClkFreq/AppBATCfg.AdcClkFreq;
      AD5940_ClksCalculate(&clks_cal, &WaitClks);
      /* Start sequence generator here */
      AD5940_SEQGenCtrl(bTRUE);
      AD5940_SEQGenInsert(SEQ_WAIT(16*250));  /* wait 250us for reference power up from hibernate mode. */
      AD5940_AFECtrlS(AFECTRL_WG|AFECTRL_ADCPWR|AFECTRL_SINC2NOTCH, bTRUE);  /* Enable Waveform generator, ADC power */
      AD5940_SEQGenInsert(SEQ_WAIT(16*50));   /* Wait for ADC ready. */
      AD5940_AFECtrlS(AFECTRL_ADCCNV|AFECTRL_DFT, bTRUE);  /* Start ADC convert and DFT */
      AD5940_SEQGenFetchSeq(NULL, &AppBATCfg.SeqWaitAddr[0]); /* Record the start address of the next command. */
    
      AD5940_SEQGenInsert(SEQ_WAIT(WaitClks/2));
       AD5940_SEQGenInsert(SEQ_WAIT(WaitClks/2));  
      AD5940_AFECtrlS(AFECTRL_ADCCNV|AFECTRL_DFT/*|AFECTRL_WG*/|AFECTRL_ADCPWR|AFECTRL_SINC2NOTCH, bFALSE);  /* Stop ADC convert and DFT */
      //AD5940_EnterSleepS();/* Goto hibernate */
      /* Sequence end. */
      error = AD5940_SEQGenFetchSeq(&pSeqCmd, &SeqLen);
      AD5940_SEQGenCtrl(bFALSE); /* Stop sequencer generator */
    
      AppBATCfg.MeasSeqCycleCount = AD5940_SEQCycleTime();
      AppBATCfg.MaxODR = 1/(((AppBATCfg.MeasSeqCycleCount + 10) / 16.0)* 1E-6)  ;
      if(AppBATCfg.BatODR > AppBATCfg.MaxODR)
      {
        /* We have requested a sampling rate that cannot be achieved with the time it
           takes to acquire a sample.
        */
        AppBATCfg.BatODR = AppBATCfg.MaxODR;
      }
    
      if(error == AD5940ERR_OK)
      {
        AppBATCfg.MeasureSeqInfo.SeqId = SEQID_0;
        AppBATCfg.MeasureSeqInfo.SeqRamAddr = AppBATCfg.InitSeqInfo.SeqRamAddr + AppBATCfg.InitSeqInfo.SeqLen ;
        AppBATCfg.MeasureSeqInfo.pSeqCmd = pSeqCmd;
        AppBATCfg.MeasureSeqInfo.SeqLen = SeqLen;
        /* Write command to SRAM */
        AD5940_SEQCmdWrite(AppBATCfg.MeasureSeqInfo.SeqRamAddr, pSeqCmd, SeqLen);
      }
      else
        return error; /* Error */
      return AD5940ERR_OK;
    }
    
    /* This function provide application initialize.   */
    AD5940Err AppBATInit(uint32_t *pBuffer, uint32_t BufferSize)
    {
      AD5940Err error = AD5940ERR_OK;
      SEQCfg_Type seq_cfg;
      FIFOCfg_Type fifo_cfg;
    
      if(AD5940_WakeUp(10) > 10)  /* Wakeup AFE by read register, read 10 times at most */
        return AD5940ERR_WAKEUP;  /* Wakeup Failed */
    
      /* Configure sequencer and stop it */
      seq_cfg.SeqMemSize = SEQMEMSIZE_2KB;  /* 2kB SRAM is used for sequencer, others for data FIFO */
      seq_cfg.SeqBreakEn = bFALSE;
      seq_cfg.SeqIgnoreEn = bFALSE;
      seq_cfg.SeqCntCRCClr = bTRUE;
      seq_cfg.SeqEnable = bFALSE;
      seq_cfg.SeqWrTimer = 0;
      AD5940_SEQCfg(&seq_cfg);
    
      /* Reconfigure FIFO */
      AD5940_FIFOCtrlS(FIFOSRC_DFT, bFALSE);									/* Disable FIFO firstly */
      fifo_cfg.FIFOEn = bTRUE;
      fifo_cfg.FIFOMode = FIFOMODE_FIFO;
      fifo_cfg.FIFOSize = FIFOSIZE_4KB;                       /* 4kB for FIFO, The reset 2kB for sequencer */
      fifo_cfg.FIFOSrc = FIFOSRC_DFT;
      fifo_cfg.FIFOThresh = AppBATCfg.FifoThresh;              /* DFT result. One pair for RCAL, another for Rz. One DFT result have real part and imaginary part */
      AD5940_FIFOCfg(&fifo_cfg);
    
      AD5940_INTCClrFlag(AFEINTSRC_ALLINT);
      
      /* Start sequence generator */
      /* Initialize sequencer generator */
      if((AppBATCfg.BATInited == bFALSE)||\
           (AppBATCfg.bParaChanged == bTRUE))
      {
        if(pBuffer == 0)  return AD5940ERR_PARA;
        if(BufferSize == 0) return AD5940ERR_PARA;   
        AD5940_SEQGenInit(pBuffer, BufferSize);
        /* Generate initialize sequence */
        error = AppBATSeqCfgGen(); /* Application initialization sequence using either MCU or sequencer */
        if(error != AD5940ERR_OK) return error;
        /* Generate measurement sequence */
        error = AppBATSeqMeasureGen();
        if(error != AD5940ERR_OK) return error;
        AppBATCfg.bParaChanged = bFALSE; /* Clear this flag as we already implemented the new configuration */
      }
      /* Initialization sequencer  */
      AppBATCfg.InitSeqInfo.WriteSRAM = bFALSE;
      AD5940_SEQInfoCfg(&AppBATCfg.InitSeqInfo);
      seq_cfg.SeqEnable = bTRUE;
      AD5940_SEQCfg(&seq_cfg);  /* Enable sequencer */
      AD5940_SEQMmrTrig(AppBATCfg.InitSeqInfo.SeqId);
      while(AD5940_INTCTestFlag(AFEINTC_1, AFEINTSRC_ENDSEQ) == bFALSE);
      
    	AppBATCheckFreq(AppBATCfg.SweepCfg.SweepStart);
      /* Measurement sequence  */
      AppBATCfg.MeasureSeqInfo.WriteSRAM = bFALSE;
      AD5940_SEQInfoCfg(&AppBATCfg.MeasureSeqInfo);
      seq_cfg.SeqEnable = bTRUE;
      AD5940_SEQCfg(&seq_cfg);  /* Enable sequencer, and wait for trigger */
      AD5940_ClrMCUIntFlag();   /* Clear interrupt flag generated before */
      AD5940_AFEPwrBW(AppBATCfg.PwrMod, AFEBW_250KHZ);
      AD5940_WriteReg(REG_AFE_SWMUX, 1<<1);
      AppBATCfg.BATInited = bTRUE;  /* BAT application has been initialized. */
      return AD5940ERR_OK;
    }
    
    /* Depending on frequency of Sin wave set optimum filter settings */
    AD5940Err AppBATCheckFreq(float freq)
    {
    	ADCFilterCfg_Type filter_cfg;
      DFTCfg_Type dft_cfg;
      HSDACCfg_Type hsdac_cfg;
      uint32_t WaitClks;
      ClksCalInfo_Type clks_cal;
      FreqParams_Type freq_params;
      uint32_t SeqCmdBuff[32];
      uint32_t SRAMAddr = 0;;
      /* Step 1: Check Frequency */
      freq_params = AD5940_GetFreqParameters(freq);
      
           if(freq < 0.51)
    	{
    	hsdac_cfg.ExcitBufGain = EXCITBUFGAIN_2;
        hsdac_cfg.HsDacGain = HSDACGAIN_1;
        hsdac_cfg.HsDacUpdateRate = 0x1B;
        AD5940_HSDacCfgS(&hsdac_cfg);
        AD5940_HSRTIACfgS(HSTIARTIA_40K);
        
        /*Update ADC rate */
        filter_cfg.ADCRate = ADCRATE_800KHZ;
        AppBATCfg.AdcClkFreq = 16e6;
        
        /* Change clock to 16MHz oscillator */
        AD5940_HPModeEn(bFALSE);
    	}
            else if(freq < 5 )
    	{
    	hsdac_cfg.ExcitBufGain = EXCITBUFGAIN_2;
        hsdac_cfg.HsDacGain = HSDACGAIN_1;
        hsdac_cfg.HsDacUpdateRate = 0x1B;
        AD5940_HSDacCfgS(&hsdac_cfg);
        AD5940_HSRTIACfgS(HSTIARTIA_40K);
        
        /*Update ADC rate */
        filter_cfg.ADCRate = ADCRATE_800KHZ;
        AppBATCfg.AdcClkFreq = 16e6;
        
        /* Change clock to 16MHz oscillator */
        AD5940_HPModeEn(bFALSE);
        
    	}else if(freq < 450)
    	{
        hsdac_cfg.ExcitBufGain = EXCITBUFGAIN_2;
        hsdac_cfg.HsDacGain = HSDACGAIN_1;
        hsdac_cfg.HsDacUpdateRate = 0x1B;
        AD5940_HSDacCfgS(&hsdac_cfg);
        AD5940_HSRTIACfgS(HSTIARTIA_5K);
        
        /*Update ADC rate */
        filter_cfg.ADCRate = ADCRATE_800KHZ;
        AppBATCfg.AdcClkFreq = 16e6;
        
        /* Change clock to 16MHz oscillator */
        AD5940_HPModeEn(bFALSE);
    	}
           else if(freq<80000)
           {
    	hsdac_cfg.ExcitBufGain = EXCITBUFGAIN_2;
        hsdac_cfg.HsDacGain = HSDACGAIN_1;
        hsdac_cfg.HsDacUpdateRate = 0x1B;
        AD5940_HSDacCfgS(&hsdac_cfg);
        AD5940_HSRTIACfgS(HSTIARTIA_5K);
        
        /*Update ADC rate */
        filter_cfg.ADCRate = ADCRATE_800KHZ;
        AppBATCfg.AdcClkFreq = 16e6;
        
        /* Change clock to 16MHz oscillator */
        AD5940_HPModeEn(bFALSE);
           }
            /* High power mode */
    	if(freq >= 80000)
    	{
    	hsdac_cfg.ExcitBufGain = EXCITBUFGAIN_2;
        hsdac_cfg.HsDacGain = HSDACGAIN_1;
        hsdac_cfg.HsDacUpdateRate = 0x07;
        AD5940_HSDacCfgS(&hsdac_cfg);
        AD5940_HSRTIACfgS(HSTIARTIA_5K);
        
        /*Update ADC rate */
        filter_cfg.ADCRate = ADCRATE_1P6MHZ;
        AppBATCfg.AdcClkFreq = 32e6;
        
        /* Change clock to 32MHz oscillator */
        AD5940_HPModeEn(bTRUE);
    	}
      
      /* Step 2: Adjust ADCFILTERCON and DFTCON to set optimumn SINC3, SINC2 and DFTNUM settings  */
      filter_cfg.ADCAvgNum = ADCAVGNUM_16;  /* Don't care because it's disabled */ 
      filter_cfg.ADCSinc2Osr = freq_params.ADCSinc2Osr;
      filter_cfg.ADCSinc3Osr = freq_params.ADCSinc3Osr;
      filter_cfg.BpSinc3 = bFALSE;
      filter_cfg.BpNotch = bTRUE;
      filter_cfg.Sinc2NotchEnable = bTRUE;
      dft_cfg.DftNum = freq_params.DftNum;
      dft_cfg.DftSrc = freq_params.DftSrc;
      dft_cfg.HanWinEn = AppBATCfg.HanWinEn;
      AD5940_ADCFilterCfgS(&filter_cfg);
      AD5940_DFTCfgS(&dft_cfg);
      
      /* Step 3: Calculate clocks needed to get result to FIFO and update sequencer wait command */
      clks_cal.DataType = DATATYPE_DFT;
      clks_cal.DftSrc = freq_params.DftSrc;
      clks_cal.DataCount = 1L<<(freq_params.DftNum+2); /* 2^(DFTNUMBER+2) */
      clks_cal.ADCSinc2Osr = freq_params.ADCSinc2Osr;
      clks_cal.ADCSinc3Osr = freq_params.ADCSinc3Osr;
      clks_cal.ADCAvgNum = 0;
      clks_cal.RatioSys2AdcClk = AppBATCfg.SysClkFreq/AppBATCfg.AdcClkFreq;
      AD5940_ClksCalculate(&clks_cal, &WaitClks);		
    	
    	
    	  SRAMAddr = AppBATCfg.MeasureSeqInfo.SeqRamAddr + AppBATCfg.SeqWaitAddr[0];
    	   
               SeqCmdBuff[0] =SEQ_WAIT(WaitClks/2);
               SeqCmdBuff[1] =SEQ_WAIT(WaitClks/2);
          
    		AD5940_SEQCmdWrite(SRAMAddr, SeqCmdBuff, 2);
    		
      return AD5940ERR_OK;
    }

    /*AD5940Main.c*/
    #include "ad5940.h"
    #include <stdio.h>
    #include "string.h"
    #include "math.h"
    #include "BATImpedance.h"
    
    #define APPBUFF_SIZE 512
    uint32_t AppBuff[APPBUFF_SIZE];
    
    /* It's your choice here how to do with the data. Here is just an example to print them to UART */
    int32_t BATShowResult(uint32_t *pData, uint32_t DataCount)
    {
      fImpCar_Type *pImp = (fImpCar_Type*)pData;
    	float freq;
    	AppBATCtrl(BATCTRL_GETFREQ, &freq);
      /*Process data*/
      for(int i=0;i<DataCount;i++)
      {
        printf("Freq: %f (real, image) = ,%f , %f ,mOhm \n",freq, pImp[i].Real,pImp[i].Image);
      }
      return 0;
    }
    
    /* Initialize AD5940 basic blocks like clock */
    static int32_t AD5940PlatformCfg(void)
    {
      CLKCfg_Type clk_cfg;
      FIFOCfg_Type fifo_cfg;
      AGPIOCfg_Type gpio_cfg;
      /* Use hardware reset */
      AD5940_HWReset();
      /* Platform configuration */
      AD5940_Initialize();
      /* Step1. Configure clock */
      clk_cfg.ADCClkDiv = ADCCLKDIV_1;
      clk_cfg.ADCCLkSrc = ADCCLKSRC_HFOSC;
      clk_cfg.SysClkDiv = SYSCLKDIV_1;
      clk_cfg.SysClkSrc = SYSCLKSRC_HFOSC; //on battery board, there is a 32MHz crystal.
      clk_cfg.HfOSC32MHzMode = bFALSE;
      clk_cfg.HFOSCEn = bTRUE;
      clk_cfg.HFXTALEn = bFALSE;
      clk_cfg.LFOSCEn = bTRUE;
      AD5940_CLKCfg(&clk_cfg);
      /* Step2. Configure FIFO and Sequencer*/
      fifo_cfg.FIFOEn = bFALSE;
      fifo_cfg.FIFOMode = FIFOMODE_FIFO;
      fifo_cfg.FIFOSize = FIFOSIZE_4KB;                       /* 4kB for FIFO, The reset 2kB for sequencer */
      fifo_cfg.FIFOSrc = FIFOSRC_DFT;
      fifo_cfg.FIFOThresh = 4;//AppBATCfg.FifoThresh;        /* DFT result. One pair for RCAL, another for Rz. One DFT result have real part and imaginary part */
      AD5940_FIFOCfg(&fifo_cfg);                             /* Disable to reset FIFO. */
      fifo_cfg.FIFOEn = bTRUE;  
      AD5940_FIFOCfg(&fifo_cfg);                             /* Enable FIFO here */
      
      /* Step3. Interrupt controller */
      AD5940_INTCCfg(AFEINTC_1, AFEINTSRC_ALLINT, bTRUE);           /* Enable all interrupt in Interrupt Controller 1, so we can check INTC flags */
      AD5940_INTCCfg(AFEINTC_0, AFEINTSRC_DATAFIFOTHRESH, bTRUE);   /* Interrupt Controller 0 will control GP0 to generate interrupt to MCU */
      AD5940_INTCClrFlag(AFEINTSRC_ALLINT);
      /* Step4: Reconfigure GPIO */
      gpio_cfg.FuncSet = GP0_INT|GP2_SYNC;
      gpio_cfg.InputEnSet = AGPIO_Pin2;
      gpio_cfg.OutputEnSet = AGPIO_Pin0|AGPIO_Pin2;
      gpio_cfg.OutVal = 0;
      gpio_cfg.PullEnSet = 0;
      AD5940_AGPIOCfg(&gpio_cfg);
      AD5940_SleepKeyCtrlS(SLPKEY_UNLOCK);  /* Allow AFE to enter sleep mode. */
      return 0;
    }
    
    void AD5940BATStructInit(void)
    {
      AppBATCfg_Type *pBATCfg;
      AppBATGetCfg(&pBATCfg);
      pBATCfg->SeqStartAddr = 0;
      pBATCfg->MaxSeqLen = 512;
      pBATCfg->RcalVal = 50.0;  							/* Value of RCAL on EVAL-AD5941BATZ board is 50mOhm */
      pBATCfg->ACVoltPP = 300.0f;							/* Pk-pk amplitude is 300mV */
      pBATCfg->DCVolt = 1200.0f;							/* Offset voltage of 1.2V*/
      pBATCfg->DftNum = DFTNUM_8192;
      
      pBATCfg->FifoThresh = 2;      					/* 2 results in FIFO, real and imaginary part. */
    	
    	pBATCfg->SinFreq = 200;									/* Sin wave frequency. THis value has no effect if sweep is enabled */
    	
    	pBATCfg->SweepCfg.SweepEn = bTRUE;			/* Set to bTRUE to enable sweep function */
    	pBATCfg->SweepCfg.SweepStart = 1.0f;		/* Start sweep at 1Hz  */
    	pBATCfg->SweepCfg.SweepStop = 50000.0f;	/* Finish sweep at 1000Hz */
    	pBATCfg->SweepCfg.SweepPoints = 50;			/* 100 frequencies in the sweep */
    	pBATCfg->SweepCfg.SweepLog = bTRUE;			/* Set to bTRUE to use LOG scale. Set bFALSE to use linear scale */
    	
    }
    
    void AD5940_Main(void)
    {
      uint32_t temp;
      AD5940PlatformCfg();
      
      AD5940BATStructInit(); /* Configure your parameters in this function */
      
      AppBATInit(AppBuff, APPBUFF_SIZE);    /* Initialize BAT application. Provide a buffer, which is used to store sequencer commands */
      AppBATCtrl(BATCTRL_MRCAL, 0);     /* Measur RCAL each point in sweep */
    	AppBATCtrl(BATCTRL_START, 0); 
      while(1)
      {
        /* Check if interrupt flag which will be set when interrupt occurred. */
        if(AD5940_GetMCUIntFlag())
        {
    				AD5940_ClrMCUIntFlag(); 				/* Clear this flag */
    				temp = APPBUFF_SIZE;
    				AppBATISR(AppBuff, &temp); 			/* Deal with it and provide a buffer to store data we got */
    				AD5940_Delay10us(100000);
    				BATShowResult(AppBuff, temp);		/* Print measurement results over UART */		
    				AD5940_SEQMmrTrig(SEQID_0);  		/* Trigger next measurement ussing MMR write*/      
       }
      }
    }

    #ifndef _BAT_IMPEDANCE_H_
    #define _BAT_IMPEDANCE_H_
    #include "ad5940.h"
    #include "stdio.h"
    #include "string.h"
    #include "math.h"
    
    #define PRECHARGE_WAIT_MS   4000    //precharge time in ms.
    
    #define PRECHARGE_CH1       1
    #define PRECHARGE_CH2       2
    #define PRECHARGE_CH3       3
    
    #define PRECHARGE_RCAL      PRECHARGE_CH1
    #define PRECHARGE_BAT       PRECHARGE_CH2
    #define PRECHARGE_AMP       PRECHARGE_CH3
    /* 
      Note: this example will use SEQID_0 as measurement sequence, and use SEQID_1 as init sequence. 
      SEQID_3 is used for calibration.
    */
    
    #define STATE_IDLE        0   /**< Initial state. */
    #define STATE_RCAL        1   /**< Measure Rcal response voltage. */
    #define STATE_BATTERY     2   /**< Measure battery response voltage. */
    typedef struct
    {
    /* Common configurations for all kinds of Application. */
      uint32_t state;               /* 0: Init, 1: measure Rcal, 2: Measure Battery. */
      BoolFlag bParaChanged;        /* Indicate to generate sequence again. It's auto cleared by AppBATInit */
      BoolFlag bDoCal;              /* Need to do calibration. */
      uint32_t SeqStartAddr;        /* Initialaztion sequence start address in SRAM of AD5940  */
      uint32_t MaxSeqLen;           /* Limit the maximum sequence.   */
      uint32_t SeqStartAddrCal;     /* Measurement sequence start address in SRAM of AD5940 */
      uint32_t MaxSeqLenCal;
    /* Application related parameters */ 
      float SysClkFreq;             /* The real frequency of system clock */
      float WuptClkFreq;            /* The clock frequency of Wakeup Timer in Hz. Typically it's 32kHz. Leave it here in case we calibrate clock in software method */
      float AdcClkFreq;             /* The real frequency of ADC clock */
      uint32_t FifoThresh;           /* FIFO threshold. Should be N*4 */   
      float BatODR;                 /* in Hz. ODR decides the period of WakeupTimer who will trigger sequencer periodically. DFT number and sample frequency decides the maxim ODR. */
      int32_t NumOfData;            /* By default it's '-1'. If you want the engine stops after get NumofData, then set the value here. Otherwise, set it to '-1' which means never stop. */
      uint32_t PwrMod;              /* Control Chip power mode(LP/HP) */
      float ACVoltPP;               /* Final AC excitation voltage on pin AIN1 in mV peak to peak unit. */
      float DCVolt;                 /* The DC bias voltage on AIN1 pin. Unit is mV. */
      float RcalVal;                /* Rcal value in mOhm */
      float SinFreq;                /* Frequency of excitation signal */
      uint8_t ADCSinc3Osr;          /* SINC3 OSR selection. ADCSINC3OSR_2, ADCSINC3OSR_4 */
      uint8_t ADCSinc2Osr;          /* SINC2 OSR selection. ADCSINC2OSR_22...ADCSINC2OSR_1333 */
      uint32_t DftNum;              /* DFT number */
      uint32_t DftSrc;              /* DFT Source */
      BoolFlag HanWinEn;            /* Enable Hanning window */
      uint32_t SeqWaitAddr[3];    
    /* Sweep Function Control */
      SoftSweepCfg_Type SweepCfg;
    /* Private variables for internal usage */
      float SweepCurrFreq;
      float SweepNextFreq;
      float FreqofData;  
      BoolFlag BATInited;           /* If the program run firstly, generated sequence commands */
      SEQInfo_Type InitSeqInfo;
      SEQInfo_Type MeasureSeqInfo;
      BoolFlag StopRequired;        /* After FIFO is ready, stop the measurement sequence */
      uint32_t FifoDataCount;       /* Count how many times impedance have been measured */
      uint32_t MeasSeqCycleCount;   /* How long the measurement sequence will take */
      float MaxODR;                 /* Max ODR for sampling in this config */
      fImpCar_Type RcalVolt;        /* The measured Rcal resistor(R1) response voltage. */
      float RcalVoltTable[100][2];    
    /* End */
    }AppBATCfg_Type;
    
    #define BATCTRL_START          0
    #define BATCTRL_STOPNOW        1
    #define BATCTRL_STOPSYNC       2
    #define BATCTRL_SHUTDOWN       4   /* Note: shutdown here means turn off everything and put AFE to hibernate mode. The word 'SHUT DOWN' is only used here. */
    #define BATCTRL_MRCAL          5   /* Measure RCAL response voltage */
    #define BATCTRL_GETFREQ				 6
    
    AD5940Err AppBATGetCfg(void *pCfg);
    AD5940Err AppBATInit(uint32_t *pBuffer, uint32_t BufferSize);
    AD5940Err AppBATISR(void *pBuff, uint32_t *pCount);
    AD5940Err AppBATCtrl(int32_t BatCtrl, void *pPara);
    AD5940Err AppBATCheckFreq(float freq);
    AD5940Err AppBATMeasureRCAL(void);
    
    #endif

Children
No Data