182 lines
5.6 KiB
C
182 lines
5.6 KiB
C
/*!
|
|
*****************************************************************************
|
|
@file: AD5940Main.c
|
|
@author: Neo Xu
|
|
@brief: Standard 4-wire or 2-wire impedance measurement example.
|
|
-----------------------------------------------------------------------------
|
|
|
|
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"
|
|
|
|
/**
|
|
User could configure following parameters
|
|
**/
|
|
|
|
#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 =
|
|
4; // AppIMPCfg.FifoThresh; /* DFT result. One pair for RCAL,
|
|
// another for Rz. One DFT result have real part and imaginary part */
|
|
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 = 100.0;
|
|
pImpedanceCfg->SinFreq = 60000.0;
|
|
pImpedanceCfg->FifoThresh = 4;
|
|
|
|
/* Set switch matrix to onboard(EVAL-AD5940ELECZ) dummy sensor. */
|
|
/* Note the RCAL0 resistor is 10kOhm. */
|
|
/* MODIFIED: Using AIN2/AIN3 for voltage sense as per user setup (CE0, SE0,
|
|
* AIN2, AIN3) */
|
|
pImpedanceCfg->DswitchSel = SWD_CE0;
|
|
pImpedanceCfg->PswitchSel = SWP_AIN2;
|
|
pImpedanceCfg->NswitchSel = SWN_AIN3;
|
|
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_1K;
|
|
|
|
/* Disable Hardware Sweep */
|
|
pImpedanceCfg->SweepCfg.SweepEn = bFALSE;
|
|
}
|
|
|
|
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. */
|
|
|
|
AppIMPCfg_Type *pImpedanceCfg;
|
|
AppIMPGetCfg(&pImpedanceCfg);
|
|
|
|
printf("\n--- EIS Configuration ---\n");
|
|
printf("RcalVal: %.2f Ohm\n", pImpedanceCfg->RcalVal);
|
|
printf("BiasVolt: %.2f mV\n", pImpedanceCfg->BiasVolt);
|
|
printf("HstiaRtiaSel: 0x%02X\n", pImpedanceCfg->HstiaRtiaSel);
|
|
printf("AC Volts PP: %.2f mV\n", pImpedanceCfg->DacVoltPP);
|
|
printf("-------------------------\n\n");
|
|
|
|
/* Calculate Sweep Points */
|
|
float start_freq = 100.0f;
|
|
float stop_freq = 100000.0f;
|
|
int num_points = 101;
|
|
// float log_step = pow(stop_freq / start_freq, 1.0 / (num_points - 1));
|
|
float log_step = 1.0715193f; // 1000^(1/100)
|
|
float curr_freq = start_freq;
|
|
|
|
printf("Starting Software Sweep: %.2f Hz to %.2f Hz, %d points\n", start_freq,
|
|
stop_freq, num_points);
|
|
|
|
for (int i = 0; i < num_points; i++) {
|
|
uint32_t temp;
|
|
/* Update Frequency */
|
|
pImpedanceCfg->SinFreq = curr_freq;
|
|
|
|
/* Re-Initialize App to apply new frequency (this regenerates sequences) */
|
|
AppIMPInit(AppBuff, APPBUFF_SIZE);
|
|
|
|
/* Calibrate RTIA at this frequency */
|
|
AppIMPRtiaCal();
|
|
|
|
/* Measure Impedance */
|
|
AppIMPCtrl(IMPCTRL_START, 0);
|
|
|
|
/* Wait for result */
|
|
while (1) {
|
|
if (AD5940_GetMCUIntFlag()) {
|
|
AD5940_ClrMCUIntFlag();
|
|
temp = APPBUFF_SIZE;
|
|
AppIMPISR(AppBuff, &temp);
|
|
ImpedanceShowResult(AppBuff, temp);
|
|
break; // Done with this point
|
|
}
|
|
}
|
|
|
|
/* Next Frequency */
|
|
curr_freq *= log_step;
|
|
}
|
|
printf("Sweep Completed.\n");
|
|
while (1)
|
|
; // Stop
|
|
}
|