152 lines
5.0 KiB
C
152 lines
5.0 KiB
C
/*!
|
|
*****************************************************************************
|
|
@file: AD5940Main.c
|
|
@author: Neo Xu
|
|
@brief: Electrochemical impedance spectroscopy based on example AD5940_Impedance
|
|
This project is optomized for 3-lead electrochemical sensors that typically have
|
|
an impedance <200ohm. For optimum performance RCAL should be close to
|
|
impedance of the sensor.
|
|
-----------------------------------------------------------------------------
|
|
|
|
Copyright (c) 2017-2019 Analog Devices, Inc. All Rights Reserved.
|
|
|
|
This software is proprietary to Analog Devices, Inc. and its licensors.
|
|
By using this software you agree to the terms of the associated
|
|
Analog Devices Software License Agreement.
|
|
|
|
*****************************************************************************/
|
|
#include "Impedance.h"
|
|
|
|
#define APPBUFF_SIZE 512
|
|
uint32_t AppBuff[APPBUFF_SIZE];
|
|
|
|
int32_t ImpedanceShowResult(uint32_t *pData, uint32_t DataCount)
|
|
{
|
|
float freq;
|
|
|
|
fImpPol_Type *pImp = (fImpPol_Type*)pData;
|
|
AppIMPCtrl(IMPCTRL_GETFREQ, &freq);
|
|
|
|
printf("Freq:%.2f ", freq);
|
|
/*Process data*/
|
|
for(int i=0;i<DataCount;i++)
|
|
{
|
|
printf("RzMag: %f Ohm , RzPhase: %f \n",pImp[i].Magnitude,pImp[i].Phase*180/MATH_PI);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
static int32_t AD5940PlatformCfg(void)
|
|
{
|
|
CLKCfg_Type clk_cfg;
|
|
FIFOCfg_Type fifo_cfg;
|
|
AGPIOCfg_Type gpio_cfg;
|
|
|
|
/* Use hardware reset */
|
|
AD5940_HWReset();
|
|
AD5940_Initialize();
|
|
/* Platform configuration */
|
|
/* Step1. Configure clock */
|
|
clk_cfg.ADCClkDiv = ADCCLKDIV_1;
|
|
clk_cfg.ADCCLkSrc = ADCCLKSRC_HFOSC;
|
|
clk_cfg.SysClkDiv = SYSCLKDIV_1;
|
|
clk_cfg.SysClkSrc = SYSCLKSRC_HFOSC;
|
|
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 = 6;
|
|
AD5940_FIFOCfg(&fifo_cfg);
|
|
fifo_cfg.FIFOEn = bTRUE;
|
|
AD5940_FIFOCfg(&fifo_cfg);
|
|
|
|
/* Step3. Interrupt controller */
|
|
AD5940_INTCCfg(AFEINTC_1, AFEINTSRC_ALLINT, bTRUE); /* Enable all interrupt in INTC1, so we can check INTC flags */
|
|
AD5940_INTCClrFlag(AFEINTSRC_ALLINT);
|
|
AD5940_INTCCfg(AFEINTC_0, AFEINTSRC_DATAFIFOTHRESH, bTRUE);
|
|
AD5940_INTCClrFlag(AFEINTSRC_ALLINT);
|
|
/* Step4: Reconfigure GPIO */
|
|
gpio_cfg.FuncSet = GP0_INT|GP1_SLEEP|GP2_SYNC;
|
|
gpio_cfg.InputEnSet = 0;
|
|
gpio_cfg.OutputEnSet = AGPIO_Pin0|AGPIO_Pin1|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 AD5940ImpedanceStructInit(void)
|
|
{
|
|
AppIMPCfg_Type *pImpedanceCfg;
|
|
|
|
AppIMPGetCfg(&pImpedanceCfg);
|
|
/* Step1: configure initialization sequence Info */
|
|
pImpedanceCfg->SeqStartAddr = 0;
|
|
pImpedanceCfg->MaxSeqLen = 512; /* @todo add checker in function */
|
|
|
|
pImpedanceCfg->RcalVal = 200.0;
|
|
pImpedanceCfg->FifoThresh = 6;
|
|
pImpedanceCfg->SinFreq = 1000.0;
|
|
|
|
/* Configure Excitation Waveform
|
|
*
|
|
* Output waveform = DacVoltPP * ExcitBufGain * HsDacGain
|
|
*
|
|
* = 300 * 0.25 * 0.2 = 15mV pk-pk
|
|
*
|
|
*/
|
|
pImpedanceCfg->DacVoltPP = 300; /* Maximum value is 600mV*/
|
|
pImpedanceCfg->ExcitBufGain = EXCITBUFGAIN_0P25;
|
|
pImpedanceCfg->HsDacGain = HSDACGAIN_0P2;
|
|
|
|
/* Set switch matrix to onboard(EVAL-AD5940ELECZ) gas sensor. */
|
|
pImpedanceCfg->DswitchSel = SWD_CE0;
|
|
pImpedanceCfg->PswitchSel = SWP_RE0;
|
|
pImpedanceCfg->NswitchSel = SWN_SE0LOAD;
|
|
pImpedanceCfg->TswitchSel = SWT_SE0LOAD;
|
|
/* The dummy sensor is as low as 5kOhm. We need to make sure RTIA is small enough that HSTIA won't be saturated. */
|
|
pImpedanceCfg->HstiaRtiaSel = HSTIARTIA_200;
|
|
pImpedanceCfg->BiasVolt = 0.0;
|
|
/* Configure the sweep function. */
|
|
pImpedanceCfg->SweepCfg.SweepEn = bFALSE;
|
|
pImpedanceCfg->SweepCfg.SweepStart = 100.0f; /* Start from 1kHz */
|
|
pImpedanceCfg->SweepCfg.SweepStop = 100e3f; /* Stop at 100kHz */
|
|
pImpedanceCfg->SweepCfg.SweepPoints = 101; /* Points is 101 */
|
|
pImpedanceCfg->SweepCfg.SweepLog = bTRUE;
|
|
/* Configure Power Mode. Use HP mode if frequency is higher than 80kHz. */
|
|
pImpedanceCfg->PwrMod = AFEPWR_LP;
|
|
/* Configure filters if necessary */
|
|
pImpedanceCfg->ADCSinc3Osr = ADCSINC3OSR_4; /* Sample rate is 800kSPS/2 = 400kSPS */
|
|
pImpedanceCfg->DftNum = DFTNUM_16384;
|
|
pImpedanceCfg->DftSrc = DFTSRC_SINC3;
|
|
}
|
|
|
|
void AD5940_Main(void)
|
|
{
|
|
uint32_t temp;
|
|
AD5940PlatformCfg();
|
|
AD5940ImpedanceStructInit();
|
|
|
|
AppIMPInit(AppBuff, APPBUFF_SIZE); /* Initialize IMP application. Provide a buffer, which is used to store sequencer commands */
|
|
AppIMPCtrl(IMPCTRL_START, 0); /* Control IMP measurement to start. Second parameter has no meaning with this command. */
|
|
|
|
while(1)
|
|
{
|
|
if(AD5940_GetMCUIntFlag())
|
|
{
|
|
AD5940_ClrMCUIntFlag();
|
|
temp = APPBUFF_SIZE;
|
|
AppIMPISR(AppBuff, &temp);
|
|
ImpedanceShowResult(AppBuff, temp);
|
|
}
|
|
}
|
|
}
|
|
|