Category: Software
Product Number: AD5940
Software Version: keil5
/******************************************************************************
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 "AD5940.H"
#include <stdio.h>
#include <string.h>
#include <math.h>
#include "Impedance.h"
/* 默认LPDAC分辨率(2.5V内部参考) */
#define DAC12BITVOLT_1LSB (2200.0f/4095) // 12位DAC的1LSB对应的电压值(mV)
#define DAC6BITVOLT_1LSB (DAC12BITVOLT_1LSB*64) // 6位DAC的1LSB对应的电压值(mV)
/*
* 应用程序配置结构体。由用户从模板指定。
* 这些变量在整个应用程序中可用。
* 包括序列生成器的基本配置和应用程序相关参数
*/
AppIMPCfg_Type AppIMPCfg =
{
.bParaChanged = bFALSE,
.SeqStartAddr = 0,
.MaxSeqLen = 0,
.SeqStartAddrCal = 0,
.MaxSeqLenCal = 0,
.ImpODR = 10.0, // 降低输出数据速率,给低频测量足够时间
.NumOfData = -1,
.SysClkFreq = 16000000.0,
.WuptClkFreq = 32000.0,
.AdcClkFreq = 16000000.0,
.RcalVal = 1000.0, // 1000欧姆校准电阻
.DswitchSel = SWD_CE0,
.PswitchSel = SWP_CE0,
.NswitchSel = SWN_SE0LOAD,
.TswitchSel = SWT_SE0LOAD,
.PwrMod = AFEPWR_LP,
.SensorCh0.LptiaRtiaSel = LPTIARTIA_1K, // 1kΩ RTIA
.SensorCh0.LpTiaRf = LPTIARF_1M,
.SensorCh0.LpTiaRl = LPTIARLOAD_100R,
.HstiaRtiaSel = HSTIARTIA_1K,
.ExcitBufGain = EXCITBUFGAIN_2, // 或 EXCITBUFGAIN_0P25
.HsDacGain = HSDACGAIN_1, // 或 HSDACGAIN_0P2
.HsDacUpdateRate = 0x1B,
.DacVoltPP = 500.0, // 500mV峰峰值
.BiasVolt = 0.0f,
.SinFreq = 1000.0, // 默认1kHz
.DftNum = DFTNUM_16384,
.DftSrc = DFTSRC_SINC3,
.HanWinEn = bTRUE,
.AdcPgaGain = ADCPGA_1,
.ADCSinc3Osr = ADCSINC3OSR_4, // 增加过采样率
.ADCSinc2Osr = ADCSINC2OSR_22,
.ADCAvgNum = ADCAVGNUM_16,
// 频率扫描配置:1Hz到6kHz
.SweepCfg.SweepEn = bTRUE,
.SweepCfg.SweepStart = 1.0f,
.SweepCfg.SweepStop = 6000.0f,
.SweepCfg.SweepPoints = 61,
.SweepCfg.SweepLog = bTRUE,
.SweepCfg.SweepIndex = 0,
.FifoThresh = 4,
.IMPInited = bFALSE,
.StopRequired = bFALSE,
};
/**
* 此函数供上层控制器使用,用于更改应用程序参数,特别是用户定义的参数。
* @param pCfg 指向配置结构体指针的指针
* @return 错误代码
*/
int32_t AppIMPGetCfg(void *pCfg)
{
if(pCfg)
{
*(AppIMPCfg_Type**)pCfg = &AppIMPCfg; // 返回配置结构体的地址
return AD5940ERR_OK;
}
return AD5940ERR_PARA; // 参数错误
}
/**
* 阻抗控制函数 - 处理各种阻抗测量控制命令
* @param Command 控制命令
* @param pPara 命令参数
* @return 错误代码
*/
int32_t AppIMPCtrl(uint32_t Command, void *pPara)
{
switch (Command)
{
case IMPCTRL_START: // 开始阻抗测量
{
WUPTCfg_Type wupt_cfg; // 唤醒定时器配置结构体
/* 唤醒AFE(模拟前端) */
if(AD5940_WakeUp(10) > 10) // 通过读寄存器唤醒AFE,最多读10次
return AD5940ERR_WAKEUP; // 唤醒失败
if(AppIMPCfg.IMPInited == bFALSE) // 检查是否已初始化
return AD5940ERR_APPERROR; // 应用错误
/* 配置并启动唤醒定时器 */
wupt_cfg.WuptEn = bTRUE; // 使能唤醒定时器
wupt_cfg.WuptEndSeq = WUPTENDSEQ_A; // 唤醒结束序列
wupt_cfg.WuptOrder[0] = SEQID_0; // 序列ID
wupt_cfg.SeqxSleepTime[SEQID_0] = 4; // 序列睡眠时间
// 计算序列唤醒时间(基于唤醒时钟频率和输出数据速率)
wupt_cfg.SeqxWakeupTime[SEQID_0] = (uint32_t)(AppIMPCfg.WuptClkFreq/AppIMPCfg.ImpODR)-4;
AD5940_WUPTCfg(&wupt_cfg); // 应用唤醒定时器配置
AppIMPCfg.FifoDataCount = 0; // 重置FIFO数据计数
break;
}
case IMPCTRL_STOPNOW: // 立即停止测量
{
if(AD5940_WakeUp(10) > 10) // 唤醒AFE
return AD5940ERR_WAKEUP;
/* 立即停止唤醒定时器 */
AD5940_WUPTCtrl(bFALSE);
AD5940_WUPTCtrl(bFALSE); // 二次确认停止(TODO:确认是否必要)
break;
}
case IMPCTRL_STOPSYNC: // 同步停止(在适当时候停止)
{
AppIMPCfg.StopRequired = bTRUE; // 设置停止请求标志
break;
}
case IMPCTRL_GETFREQ: // 获取当前频率
{
if(pPara == 0) // 检查参数指针
return AD5940ERR_PARA;
if(AppIMPCfg.SweepCfg.SweepEn == bTRUE) // 如果启用扫描
*(float*)pPara = AppIMPCfg.FreqofData; // 返回扫描中的当前频率
else
*(float*)pPara = AppIMPCfg.SinFreq; // 返回固定频率
}
break;
case IMPCTRL_SHUTDOWN: // 关闭系统
{
AppIMPCtrl(IMPCTRL_STOPNOW, 0); // 首先停止正在进行的测量
/* 关闭休眠操作未自动控制的LPloop相关模块 */
AFERefCfg_Type aferef_cfg;
LPLoopCfg_Type lploop_cfg;
memset(&aferef_cfg, 0, sizeof(aferef_cfg)); // 清零参考配置
AD5940_REFCfgS(&aferef_cfg); // 应用参考配置
memset(&lploop_cfg, 0, sizeof(lploop_cfg)); // 清零低功耗环路配置
AD5940_LPLoopCfgS(&lploop_cfg); // 应用低功耗环路配置
AD5940_EnterSleepS(); // 进入休眠模式
}
break;
default:
break;
}
return AD5940ERR_OK; // 成功返回
}
/**
* 获取当前频率
* @return 当前频率值
*/
float AppIMPGetCurrFreq(void)
{
if(AppIMPCfg.SweepCfg.SweepEn == bTRUE) // 扫描模式
return AppIMPCfg.FreqofData; // 返回扫描中的当前频率
else
return AppIMPCfg.SinFreq; // 返回固定频率
}
/**
* 应用程序初始化序列配置生成
* 生成初始化序列,配置AFE的各种参数
* @return 错误代码
*/
static AD5940Err AppIMPSeqCfgGen(void)
{
AD5940Err error = AD5940ERR_OK;
const uint32_t *pSeqCmd; // 序列命令指针
uint32_t SeqLen; // 序列长度
AFERefCfg_Type aferef_cfg; // AFE参考配置
HSLoopCfg_Type HsLoopCfg; // 高速环路配置
LPLoopCfg_Type lploop_cfg; // 低功耗环路配置
DSPCfg_Type dsp_cfg; // DSP配置
float sin_freq; // 正弦波频率
/* 启动序列生成器 */
AD5940_SEQGenCtrl(bTRUE);
/* 初始化所有AFE控制为禁用状态 */
AD5940_AFECtrlS(AFECTRL_ALL, bFALSE);
/* 配置AFE参考电压 */
aferef_cfg.HpBandgapEn = bTRUE; // 使能高功耗带隙
aferef_cfg.Hp1V1BuffEn = bTRUE; // 使能高功耗1.1V缓冲器
aferef_cfg.Hp1V8BuffEn = bTRUE; // 使能高功耗1.8V缓冲器
aferef_cfg.Disc1V1Cap = bFALSE; // 不断开1.1V电容
aferef_cfg.Disc1V8Cap = bFALSE; // 不断开1.8V电容
aferef_cfg.Hp1V8ThemBuff = bFALSE; // 禁用高功耗1.8V热缓冲器
aferef_cfg.Hp1V8Ilimit = bFALSE; // 禁用高功耗1.8V电流限制
aferef_cfg.Lp1V1BuffEn = bFALSE; // 禁用低功耗1.1V缓冲器
aferef_cfg.Lp1V8BuffEn = bFALSE; // 禁用低功耗1.8V缓冲器
aferef_cfg.LpBandgapEn = bTRUE; // 使能低功耗带隙
aferef_cfg.LpRefBufEn = bTRUE; // 使能低功耗参考缓冲器
aferef_cfg.LpRefBoostEn = bFALSE; // 禁用低功耗参考升压
AD5940_REFCfgS(&aferef_cfg); // 应用参考配置
/* 配置低功耗环路 */
lploop_cfg.LpDacCfg.LpdacSel = LPDAC0; // 选择LPDAC0
lploop_cfg.LpDacCfg.LpDacSrc = LPDACSRC_MMR; // DAC源:MMR
lploop_cfg.LpDacCfg.LpDacSW = LPDACSW_VBIAS2LPPA|LPDACSW_VBIAS2PIN|LPDACSW_VZERO2LPTIA|LPDACSW_VZERO2PIN; // DAC开关配置
lploop_cfg.LpDacCfg.LpDacVzeroMux = LPDACVZERO_6BIT; // Vzero多路选择:6位
lploop_cfg.LpDacCfg.LpDacVbiasMux = LPDACVBIAS_12BIT; // Vbias多路选择:12位
lploop_cfg.LpDacCfg.LpDacRef = LPDACREF_2P5; // DAC参考:2.5V
lploop_cfg.LpDacCfg.DataRst = bFALSE; // 不重置数据
lploop_cfg.LpDacCfg.PowerEn = bTRUE; // 使能电源
/* 计算DAC数据值 */
lploop_cfg.LpDacCfg.DacData6Bit = (uint32_t)((AppIMPCfg.SensorCh0.Vzero-200)/DAC6BITVOLT_1LSB); // 6位DAC数据
lploop_cfg.LpDacCfg.DacData12Bit =(int32_t)((AppIMPCfg.SensorCh0.SensorBias)/DAC12BITVOLT_1LSB) + lploop_cfg.LpDacCfg.DacData6Bit*64; // 12位DAC数据
if(lploop_cfg.LpDacCfg.DacData12Bit>lploop_cfg.LpDacCfg.DacData6Bit*64)
lploop_cfg.LpDacCfg.DacData12Bit--; // 调整数据值
/* 配置低功耗放大器 */
lploop_cfg.LpAmpCfg.LpAmpSel = LPAMP0; // 选择LPAMP0
lploop_cfg.LpAmpCfg.LpAmpPwrMod = LPAMPPWR_NORM; // 功率模式:正常
lploop_cfg.LpAmpCfg.LpPaPwrEn = bTRUE; // 使能功率放大器电源
lploop_cfg.LpAmpCfg.LpTiaPwrEn = bTRUE; // 使能TIA电源
lploop_cfg.LpAmpCfg.LpTiaRf = AppIMPCfg.SensorCh0.LpTiaRf; // TIA反馈电阻
lploop_cfg.LpAmpCfg.LpTiaRload = AppIMPCfg.SensorCh0.LpTiaRl; // TIA负载电阻
lploop_cfg.LpAmpCfg.LpTiaRtia = AppIMPCfg.SensorCh0.LptiaRtiaSel; // TIA RTIA选择
lploop_cfg.LpAmpCfg.LpTiaSW = LPTIASW(5)|LPTIASW(2)|LPTIASW(4)|LPTIASW(12)|LPTIASW(13); // TIA开关配置
AD5940_LPLoopCfgS(&lploop_cfg); // 应用低功耗环路配置
/* 配置高速环路 */
HsLoopCfg.HsDacCfg.ExcitBufGain = AppIMPCfg.ExcitBufGain; // 激励缓冲器增益
HsLoopCfg.HsDacCfg.HsDacGain = AppIMPCfg.HsDacGain; // 高速DAC增益
HsLoopCfg.HsDacCfg.HsDacUpdateRate = AppIMPCfg.HsDacUpdateRate; // 高速DAC更新速率
HsLoopCfg.HsTiaCfg.DiodeClose = bFALSE; // 不关闭二极管
HsLoopCfg.HsTiaCfg.HstiaBias = HSTIABIAS_1P1; // 高速TIA偏置:1.1V
HsLoopCfg.HsTiaCfg.HstiaCtia = 31; // 高速TIA电容:31pF + 2pF
HsLoopCfg.HsTiaCfg.HstiaDeRload = HSTIADERLOAD_OPEN; // 高速TIA去耦负载:开路
HsLoopCfg.HsTiaCfg.HstiaDeRtia = HSTIADERTIA_OPEN; // 高速TIA去耦RTIA:开路
HsLoopCfg.HsTiaCfg.HstiaRtiaSel = AppIMPCfg.HstiaRtiaSel; // 高速TIA RTIA选择
HsLoopCfg.SWMatCfg.Dswitch = SWD_OPEN; // D开关:开路
HsLoopCfg.SWMatCfg.Pswitch = SWP_OPEN; // P开关:开路
HsLoopCfg.SWMatCfg.Nswitch = SWN_OPEN; // N开关:开路
HsLoopCfg.SWMatCfg.Tswitch = SWT_OPEN; // T开关:开路
HsLoopCfg.WgCfg.WgType = WGTYPE_SIN; // 波形类型:正弦波
HsLoopCfg.WgCfg.GainCalEn = bTRUE; // 使能增益校准
HsLoopCfg.WgCfg.OffsetCalEn = bTRUE; // 使能偏移校准
/* 设置频率 */
if(AppIMPCfg.SweepCfg.SweepEn == bTRUE) // 如果启用扫描
{
AppIMPCfg.FreqofData = AppIMPCfg.SweepCfg.SweepStart; // 设置数据频率为扫描起始频率
AppIMPCfg.SweepCurrFreq = AppIMPCfg.SweepCfg.SweepStart; // 设置当前扫描频率
AD5940_SweepNext(&AppIMPCfg.SweepCfg, &AppIMPCfg.SweepNextFreq); // 计算下一个频率
sin_freq = AppIMPCfg.SweepCfg.SweepStart; // 1 Hz
}
else // 单频点模式
{
sin_freq = AppIMPCfg.SinFreq; // 使用固定频率
AppIMPCfg.FreqofData = sin_freq; // 设置数据频率
}
/* 配置波形发生器 */
HsLoopCfg.WgCfg.SinCfg.SinFreqWord = AD5940_WGFreqWordCal(sin_freq, AppIMPCfg.SysClkFreq); // 计算频率字
HsLoopCfg.WgCfg.SinCfg.SinAmplitudeWord = (uint32_t)(AppIMPCfg.DacVoltPP/800.0f*2047 + 0.5f); // 计算幅度字
HsLoopCfg.WgCfg.SinCfg.SinOffsetWord = 0; // 偏移字:0
HsLoopCfg.WgCfg.SinCfg.SinPhaseWord = 0; // 相位字:0
AD5940_HSLoopCfgS(&HsLoopCfg); // 应用高速环路配置
/* 配置DSP(数字信号处理) */
dsp_cfg.ADCBaseCfg.ADCMuxN = ADCMUXN_HSTIA_N; // ADC负输入多路选择:高速TIA负端
dsp_cfg.ADCBaseCfg.ADCMuxP = ADCMUXP_HSTIA_P; // ADC正输入多路选择:高速TIA正端
dsp_cfg.ADCBaseCfg.ADCPga = AppIMPCfg.AdcPgaGain; // ADC PGA增益
memset(&dsp_cfg.ADCDigCompCfg, 0, sizeof(dsp_cfg.ADCDigCompCfg)); // 清零ADC数字比较配置
dsp_cfg.ADCFilterCfg.ADCAvgNum = AppIMPCfg.ADCAvgNum; // ADC平均次数
dsp_cfg.ADCFilterCfg.ADCRate = ADCRATE_800KHZ; // ADC速率:800kHz(TODO:此参数决定什么?)
dsp_cfg.ADCFilterCfg.ADCSinc2Osr = AppIMPCfg.ADCSinc2Osr; // ADC SINC2过采样率
dsp_cfg.ADCFilterCfg.ADCSinc3Osr = AppIMPCfg.ADCSinc3Osr; // ADC SINC3过采样率
dsp_cfg.ADCFilterCfg.BpNotch = bTRUE; // 带通陷波
dsp_cfg.ADCFilterCfg.BpSinc3 = bFALSE; // 不使用SINC3带通
dsp_cfg.ADCFilterCfg.Sinc2NotchEnable = bTRUE; // 使能SINC2陷波
dsp_cfg.DftCfg.DftNum = AppIMPCfg.DftNum; // DFT点数
dsp_cfg.DftCfg.DftSrc = AppIMPCfg.DftSrc; // DFT源
dsp_cfg.DftCfg.HanWinEn = AppIMPCfg.HanWinEn; // 汉宁窗使能
memset(&dsp_cfg.StatCfg, 0, sizeof(dsp_cfg.StatCfg)); // 清零统计配置
AD5940_DSPCfgS(&dsp_cfg); // 应用DSP配置
/* 启用所有模块。在休眠模式下它们会自动关闭以节省功耗 */
if(AppIMPCfg.BiasVolt == 0.0f) // 如果偏置电压为0
AD5940_AFECtrlS(AFECTRL_HSTIAPWR|AFECTRL_INAMPPWR|AFECTRL_EXTBUFPWR|\
AFECTRL_WG|AFECTRL_DACREFPWR|AFECTRL_HSDACPWR|\
AFECTRL_SINC2NOTCH, bTRUE); // 启用除DC缓冲器外的所有模块
else // 如果有偏置电压
AD5940_AFECtrlS(AFECTRL_HSTIAPWR|AFECTRL_INAMPPWR|AFECTRL_EXTBUFPWR|\
AFECTRL_WG|AFECTRL_DACREFPWR|AFECTRL_HSDACPWR|\
AFECTRL_SINC2NOTCH|AFECTRL_DCBUFPWR, bTRUE); // 启用所有模块包括DC缓冲器
/* 序列结束 */
AD5940_SEQGenInsert(SEQ_STOP()); // 插入停止命令,因为初始化序列只需要运行一次
/* 获取生成的序列 */
error = AD5940_SEQGenFetchSeq(&pSeqCmd, &SeqLen); // 获取序列命令和长度
AD5940_SEQGenCtrl(bFALSE); // 停止序列生成器
if(error == AD5940ERR_OK) // 如果生成成功
{
/* 保存初始化序列信息 */
AppIMPCfg.InitSeqInfo.SeqId = SEQID_1; // 序列ID
AppIMPCfg.InitSeqInfo.SeqRamAddr = AppIMPCfg.SeqStartAddr; // 序列RAM地址
AppIMPCfg.InitSeqInfo.pSeqCmd = pSeqCmd; // 序列命令指针
AppIMPCfg.InitSeqInfo.SeqLen = SeqLen; // 序列长度
/* 写入命令到SRAM */
AD5940_SEQCmdWrite(AppIMPCfg.InitSeqInfo.SeqRamAddr, pSeqCmd, SeqLen);
}
else
return error; // 返回错误
return AD5940ERR_OK; // 成功返回
}
/**
* 测量序列生成函数
* 生成实际的阻抗测量序列,包括三个测量阶段:
* 1. 传感器+Rload测量
* 2. Rload测量
* 3. RCAL测量
* @return 错误代码
*/
static AD5940Err AppIMPSeqMeasureGen(void)
{
AD5940Err error = AD5940ERR_OK;
const uint32_t *pSeqCmd; // 序列命令指针
uint32_t SeqLen; // 序列长度
uint32_t WaitClks; // 等待时钟数
SWMatrixCfg_Type sw_cfg; // 开关矩阵配置
ClksCalInfo_Type clks_cal; // 时钟计算信息
LPAmpCfg_Type LpAmpCfg; // 低功耗放大器配置
/* 计算获取数据到FIFO所需的时钟数 */
clks_cal.DataType = DATATYPE_DFT; // 数据类型:DFT
clks_cal.DftSrc = AppIMPCfg.DftSrc; // DFT源
clks_cal.DataCount = 1L<<(AppIMPCfg.DftNum+2); // 数据计数:2^(DFTNUMBER+2)
clks_cal.ADCSinc2Osr = AppIMPCfg.ADCSinc2Osr; // ADC SINC2过采样率
clks_cal.ADCSinc3Osr = AppIMPCfg.ADCSinc3Osr; // ADC SINC3过采样率
clks_cal.ADCAvgNum = AppIMPCfg.ADCAvgNum; // ADC平均次数
clks_cal.RatioSys2AdcClk = AppIMPCfg.SysClkFreq/AppIMPCfg.AdcClkFreq; // 系统时钟与ADC时钟比率
AD5940_ClksCalculate(&clks_cal, &WaitClks); // 计算等待时钟数
/* 启动序列生成器 */
AD5940_SEQGenCtrl(bTRUE);
AD5940_SEQGpioCtrlS(AGPIO_Pin2); // 设置GPIO2,清除其他受控制的GPIO
/* 在 AppIMPSeqMeasureGen() 里,替换原来的稳定时间判断 */
if (AppIMPCfg.SweepCurrFreq < 100.0f) {
AD5940_SEQGenInsert(SEQ_WAIT(16 * 100000)); /* ✅ 100 ms 稳定 */
AppIMPCfg.DftNum = DFTNUM_8192; /* ✅ 8192 点 */
AppIMPCfg.ADCSinc2Osr = ADCSINC2OSR_533; /* ✅ 533 倍过采样 */
} else {
AD5940_SEQGenInsert(SEQ_WAIT(16 * 625)); /* 10 ms 高速档 */
AppIMPCfg.DftNum = DFTNUM_16384;
AppIMPCfg.ADCSinc2Osr = ADCSINC2OSR_22;
}
/* 从LPTIA断开SE0以避免RC滤波器放电 */
LpAmpCfg.LpAmpSel = LPAMP0; // 选择LPAMP0
LpAmpCfg.LpAmpPwrMod = LPAMPPWR_NORM; // 功率模式:正常
LpAmpCfg.LpPaPwrEn = bTRUE; // 使能功率放大器电源
LpAmpCfg.LpTiaPwrEn = bTRUE; // 使能TIA电源
LpAmpCfg.LpTiaRf = AppIMPCfg.SensorCh0.LpTiaRf; // TIA反馈电阻
LpAmpCfg.LpTiaRload = AppIMPCfg.SensorCh0.LpTiaRl; // TIA负载电阻
LpAmpCfg.LpTiaRtia = LPTIARTIA_OPEN; // 断开Rtia以避免RC滤波器放电
LpAmpCfg.LpTiaSW = LPTIASW(7)|LPTIASW(4)|LPTIASW(12)|LPTIASW(13); // TIA开关配置
AD5940_LPAMPCfgS(&LpAmpCfg); // 应用低功耗放大器配置
/*** 第一阶段:传感器 + Rload测量 ***/
sw_cfg.Dswitch = AppIMPCfg.DswitchSel; // D开关选择
sw_cfg.Pswitch = AppIMPCfg.PswitchSel; // P开关选择
sw_cfg.Nswitch = AppIMPCfg.NswitchSel; // N开关选择
sw_cfg.Tswitch = SWT_TRTIA|AppIMPCfg.TswitchSel; // T开关选择(包括TIA)
AD5940_SWMatrixCfgS(&sw_cfg); // 应用开关矩阵配置
/* 启用相关模块 */
AD5940_AFECtrlS(AFECTRL_HSTIAPWR|AFECTRL_INAMPPWR|AFECTRL_EXTBUFPWR|\
AFECTRL_WG|AFECTRL_DACREFPWR|AFECTRL_HSDACPWR|\
AFECTRL_SINC2NOTCH, bTRUE);
AD5940_AFECtrlS(AFECTRL_ADCPWR|AFECTRL_SINC2NOTCH, bTRUE); // 启用波形发生器
AD5940_SEQGenInsert(SEQ_WAIT(16*625)); // 等待信号稳定
AD5940_AFECtrlS(AFECTRL_ADCCNV|AFECTRL_DFT, bTRUE); // 开始ADC转换和DFT
AD5940_SEQGenInsert(SEQ_WAIT(WaitClks)); // 等待第一个数据就绪
/* 禁用相关模块 */
AD5940_AFECtrlS(AFECTRL_HSTIAPWR|AFECTRL_INAMPPWR|AFECTRL_EXTBUFPWR|\
AFECTRL_WG|AFECTRL_DACREFPWR|AFECTRL_HSDACPWR|\
AFECTRL_SINC2NOTCH|AFECTRL_DFT|AFECTRL_ADCCNV, bFALSE);
/*** 第二阶段:RLOAD测量 ***/
sw_cfg.Dswitch = SWD_SE0; // D开关:SE0
sw_cfg.Pswitch = SWP_SE0; // P开关:SE0
sw_cfg.Nswitch = SWN_SE0LOAD; // N开关:SE0负载
sw_cfg.Tswitch = SWT_SE0LOAD|SWT_TRTIA; // T开关:SE0负载+TIA
AD5940_SWMatrixCfgS(&sw_cfg); // 应用开关矩阵配置
/* 启用相关模块并执行测量 */
AD5940_AFECtrlS(AFECTRL_HSTIAPWR|AFECTRL_INAMPPWR|AFECTRL_EXTBUFPWR|\
AFECTRL_WG|AFECTRL_DACREFPWR|AFECTRL_HSDACPWR|AFECTRL_SINC2NOTCH, bTRUE);
AD5940_SEQGenInsert(SEQ_WAIT(16*625)); // 等待信号稳定
AD5940_AFECtrlS(AFECTRL_ADCCNV|AFECTRL_DFT, bTRUE); // 开始ADC转换和DFT
AD5940_SEQGenInsert(SEQ_WAIT(WaitClks)); // 等待第一个数据就绪
/* 禁用相关模块 */
AD5940_AFECtrlS(AFECTRL_HSTIAPWR|AFECTRL_INAMPPWR|AFECTRL_EXTBUFPWR|\
AFECTRL_WG|AFECTRL_DACREFPWR|AFECTRL_HSDACPWR|\
AFECTRL_SINC2NOTCH|AFECTRL_ADCCNV, bFALSE);
/*** 第三阶段:RCAL测量 ***/
sw_cfg.Dswitch = SWD_RCAL0; // D开关:RCAL0
sw_cfg.Pswitch = SWP_RCAL0; // P开关:RCAL0
sw_cfg.Nswitch = SWN_RCAL1; // N开关:RCAL1
sw_cfg.Tswitch = SWT_RCAL1|SWT_TRTIA; // T开关:RCAL1+TIA
AD5940_SWMatrixCfgS(&sw_cfg); // 应用开关矩阵配置
/* 重新连接LP环路 */
LpAmpCfg.LpTiaRtia = AppIMPCfg.SensorCh0.LptiaRtiaSel; // 重新连接Rtia
LpAmpCfg.LpTiaSW = LPTIASW(5)|LPTIASW(2)|LPTIASW(8)|LPTIASW(12)|LPTIASW(13); // TIA开关配置
AD5940_LPAMPCfgS(&LpAmpCfg); // 应用低功耗放大器配置
/* 启用相关模块并执行RCAL测量 */
AD5940_AFECtrlS(AFECTRL_HSTIAPWR|AFECTRL_INAMPPWR|AFECTRL_EXTBUFPWR|\
AFECTRL_WG|AFECTRL_DACREFPWR|AFECTRL_HSDACPWR|AFECTRL_SINC2NOTCH, bTRUE);
AD5940_SEQGenInsert(SEQ_WAIT(16*10)); // 等待信号稳定
AD5940_AFECtrlS(AFECTRL_ADCCNV|AFECTRL_DFT/*|AFECTRL_SINC2NOTCH*/, bTRUE); // 开始ADC转换和DFT
AD5940_SEQGenInsert(SEQ_WAIT(WaitClks)); // 等待第一个数据就绪
/* 停止ADC转换和DFT */
AD5940_AFECtrlS(AFECTRL_ADCCNV|AFECTRL_DFT|AFECTRL_WG|AFECTRL_ADCPWR, bFALSE);
/* 禁用所有相关模块 */
AD5940_AFECtrlS(AFECTRL_HSTIAPWR|AFECTRL_INAMPPWR|AFECTRL_EXTBUFPWR|\
AFECTRL_WG|AFECTRL_DACREFPWR|AFECTRL_HSDACPWR|\
AFECTRL_SINC2NOTCH, bFALSE);
/* 清理阶段 */
AD5940_SEQGpioCtrlS(0); // 清除GPIO2
/* 断开所有开关 */
sw_cfg.Dswitch = SWD_OPEN; // D开关:开路
sw_cfg.Pswitch = SWP_OPEN; // P开关:开路
sw_cfg.Nswitch = SWN_OPEN; // N开关:开路
sw_cfg.Tswitch = SWT_OPEN; // T开关:开路
AD5940_SWMatrixCfgS(&sw_cfg); // 应用开关矩阵配置
/* 获取生成的序列 */
error = AD5940_SEQGenFetchSeq(&pSeqCmd, &SeqLen); // 获取序列命令和长度
AD5940_SEQGenCtrl(bFALSE); // 停止序列生成器
if(error == AD5940ERR_OK) // 如果生成成功
{
/* 保存测量序列信息 */
AppIMPCfg.MeasureSeqInfo.SeqId = SEQID_0; // 序列ID
AppIMPCfg.MeasureSeqInfo.SeqRamAddr = AppIMPCfg.InitSeqInfo.SeqRamAddr + AppIMPCfg.InitSeqInfo.SeqLen; // 序列RAM地址
AppIMPCfg.MeasureSeqInfo.pSeqCmd = pSeqCmd; // 序列命令指针
AppIMPCfg.MeasureSeqInfo.SeqLen = SeqLen; // 序列长度
/* 写入命令到SRAM */
AD5940_SEQCmdWrite(AppIMPCfg.MeasureSeqInfo.SeqRamAddr, pSeqCmd, SeqLen);
}
else
return error; // 返回错误
return AD5940ERR_OK; // 成功返回
}
/**
* 应用程序初始化函数
* 可以启用Wupt自动触发序列,或配置其他参数
* @param pBuffer 缓冲区指针
* @param BufferSize 缓冲区大小
* @return 错误代码
*/
int32_t AppIMPInit(uint32_t *pBuffer, uint32_t BufferSize)
{
AD5940Err error = AD5940ERR_OK;
SEQCfg_Type seq_cfg; // 序列器配置
FIFOCfg_Type fifo_cfg; // FIFO配置
/* 唤醒AFE */
if(AD5940_WakeUp(10) > 10) // 通过读寄存器唤醒AFE,最多读10次
return AD5940ERR_WAKEUP; // 唤醒失败
/* 配置序列器并停止它 */
seq_cfg.SeqMemSize = SEQMEMSIZE_2KB; // 2kB SRAM用于序列器,其余用于数据FIFO
seq_cfg.SeqBreakEn = bFALSE; // 禁用序列中断
seq_cfg.SeqIgnoreEn = bTRUE; // 使能序列忽略
seq_cfg.SeqCntCRCClr = bTRUE; // 清除序列计数CRC
seq_cfg.SeqEnable = bFALSE; // 禁用序列器
seq_cfg.SeqWrTimer = 0; // 序列写入定时器
AD5940_SEQCfg(&seq_cfg); // 应用序列器配置
/* 重新配置FIFO */
AD5940_FIFOCtrlS(FIFOSRC_DFT, bFALSE); // 首先禁用FIFO
fifo_cfg.FIFOEn = bTRUE; // 使能FIFO
fifo_cfg.FIFOMode = FIFOMODE_FIFO; // FIFO模式:FIFO
fifo_cfg.FIFOSize = FIFOSIZE_4KB; // FIFO大小:4kB,其余2kB用于序列器
fifo_cfg.FIFOSrc = FIFOSRC_DFT; // FIFO源:DFT
fifo_cfg.FIFOThresh = AppIMPCfg.FifoThresh; // FIFO阈值:DFT结果。一对用于RCAL,另一对用于Rz。一个DFT结果有实部和虚部
AD5940_FIFOCfg(&fifo_cfg); // 应用FIFO配置
AD5940_INTCClrFlag(AFEINTSRC_ALLINT); // 清除所有中断标志
/* 启动序列生成器 */
/* 初始化序列生成器 */
if((AppIMPCfg.IMPInited == bFALSE)||\
(AppIMPCfg.bParaChanged == bTRUE)) // 如果未初始化或参数已改变
{
if(pBuffer == 0) return AD5940ERR_PARA; // 检查缓冲区指针
if(BufferSize == 0) return AD5940ERR_PARA; // 检查缓冲区大小
AD5940_SEQGenInit(pBuffer, BufferSize); // 初始化序列生成器
/* 生成初始化序列 */
error = AppIMPSeqCfgGen(); // 使用MCU或序列器生成应用程序初始化序列
if(error != AD5940ERR_OK) return error;
/* 生成测量序列 */
error = AppIMPSeqMeasureGen();
if(error != AD5940ERR_OK) return error;
AppIMPCfg.bParaChanged = bFALSE; // 清除此标志,因为我们已经实现了新配置
}
/* 初始化序列器 */
AppIMPCfg.InitSeqInfo.WriteSRAM = bFALSE; // 不写入SRAM
AD5940_SEQInfoCfg(&AppIMPCfg.InitSeqInfo); // 配置序列信息
seq_cfg.SeqEnable = bTRUE; // 使能序列器
AD5940_SEQCfg(&seq_cfg); // 应用序列器配置
AD5940_SEQMmrTrig(AppIMPCfg.InitSeqInfo.SeqId); // 触发初始化序列
while(AD5940_INTCTestFlag(AFEINTC_1, AFEINTSRC_ENDSEQ) == bFALSE) // 等待序列结束
/* 测量序列 */
AppIMPCfg.MeasureSeqInfo.WriteSRAM = bFALSE; /* 不写入SRAM */
AD5940_SEQInfoCfg(&AppIMPCfg.MeasureSeqInfo); /* 配置测量序列信息 */
seq_cfg.SeqEnable = bTRUE; /* 使能序列器 */
AD5940_SEQCfg(&seq_cfg); /* 应用序列器配置,等待触发 */
AD5940_ClrMCUIntFlag(); /* 清除之前生成的中断标志 */
AD5940_AFEPwrBW(AppIMPCfg.PwrMod, AFEBW_250KHZ); /* 配置AFE功率和带宽 */
/* ✅ 清 FIFO 旧数据(移到 return 之前) */
AD5940_FIFOCtrlS(FIFOSRC_DFT, bFALSE); /* 禁用FIFO */
AD5940_FIFOCtrlS(FIFOSRC_DFT, bTRUE); /* 重新启用,清空旧数据 */
AppIMPCfg.IMPInited = bTRUE; /* 阻抗应用程序已初始化 */
return AD5940ERR_OK; /* ✅ 最后返回 */
}
/**
* AFE唤醒时修改寄存器
* 在AFE处于活动状态时进行重新配置
* @param pData 数据指针
* @param pDataCount 数据计数指针
* @return 错误代码
*/
int32_t AppIMPRegModify(int32_t * const pData, uint32_t *pDataCount)
{
float freq = AppIMPCfg.SweepCurrFreq;
if (freq < 10.0f) {
AppIMPCfg.DftNum = DFTNUM_8192;
AppIMPCfg.ADCSinc2Osr = ADCSINC2OSR_267;
// 设置稳定时间 100ms
} else if (freq < 100.0f) {
AppIMPCfg.DftNum = DFTNUM_4096;
AppIMPCfg.ADCSinc2Osr = ADCSINC2OSR_178;
// 设置稳定时间 10ms
} else {
AppIMPCfg.DftNum = DFTNUM_16384;
AppIMPCfg.ADCSinc2Osr = ADCSINC2OSR_22;
// 设置稳定时间 0.5ms
}
/* 检查数据数量限制 */
if(AppIMPCfg.NumOfData > 0) // 如果设置了数据数量限制
{
AppIMPCfg.FifoDataCount += *pDataCount/4; // 更新FIFO数据计数
if(AppIMPCfg.FifoDataCount >= AppIMPCfg.NumOfData) // 如果达到数据数量限制
{
AD5940_WUPTCtrl(bFALSE); // 停止唤醒定时器
return AD5940ERR_OK;
}
}
/* 检查停止请求 */
if(AppIMPCfg.StopRequired == bTRUE) // 如果请求停止
{
AD5940_WUPTCtrl(bFALSE); // 停止唤醒定时器
return AD5940ERR_OK;
}
/* 频率扫描处理 */
if(AppIMPCfg.SweepCfg.SweepEn) // 如果需要设置新频率和功率模式
{
AD5940_WGFreqCtrlS(AppIMPCfg.SweepNextFreq, AppIMPCfg.SysClkFreq); // 控制波形发生器频率
}
return AD5940ERR_OK; // 成功返回
}
/**
* 数据处理函数
* 根据数据类型,在返回给控制器之前进行适当的数据预处理
* 实现复杂的阻抗计算算法
* @param pData 数据指针
* @param pDataCount 数据计数指针
* @return 处理状态
*/
int32_t AppIMPDataProcess(int32_t * const pData, uint32_t *pDataCount)
{
uint32_t DataCount = *pDataCount; // 数据总数
uint32_t ImpResCount = DataCount/6; // 阻抗结果数量(每6个数据对应一个阻抗结果)
fImpPol_Type * const pOut = (fImpPol_Type*)pData; // 输出指针(极坐标格式)
iImpCar_Type * pSrcData = (iImpCar_Type*)pData; // 源数据指针(笛卡尔坐标格式)
*pDataCount = 0; // 重置数据计数
DataCount = (DataCount/6)*6; // 我们期望Rz+Rload、Rload和RCAL数据。一个DFT结果在FIFO中有两个数据:实部和虚部
/* 将DFT结果转换为int32_t类型 */
for(uint32_t i=0; i<DataCount; i++)
{
pData[i] &= 0x3ffff; // 保留18位数据(TODO:选项检查ECC)
if(pData[i]&(1L<<17)) // 位17是符号位
{
pData[i] |= 0xfffc0000; // 数据是18位二进制补码,位17是符号位
}
}
/* 处理每个阻抗结果 */
for(uint32_t i=0; i<ImpResCount; i++)
{
// 使用复数运算方法计算阻抗
fImpCar_Type DftRcal, DftRzRload, DftRload, temp1, temp2, res;
fImpCar_Type DftConst1 = {1.0f, 0}; // 常数1+0j
/*
* 硬件对DFT虚部结果添加了'-1'符号。下面修复它。
*/
DftRzRload.Real = pSrcData->Real; // Rz+Rload实部
DftRzRload.Image = -pSrcData->Image; // Rz+Rload虚部(符号修正)
pSrcData++;
DftRload.Real = pSrcData->Real; // Rload实部
DftRload.Image = -pSrcData->Image; // Rload虚部(符号修正)
pSrcData++;
DftRcal.Real = pSrcData->Real; // RCAL实部
DftRcal.Image = -pSrcData->Image; // RCAL虚部(符号修正)
pSrcData++;
/**
* 阻抗计算公式:
* Rz = RloadRz - Rload
* RloadRz = DftRcal/DftRzRload*RCAL;
* Rload = DftRcal/DftRload*RCAL;
* Rz = RloadRz - Rload =
* (1/DftRzRload - 1/DftRload)*DftRcal*RCAL;
* 其中RCAL是RCAL电阻值(欧姆)
*/
temp1 = AD5940_ComplexDivFloat(&DftConst1, &DftRzRload); // 1/DftRzRload
temp2 = AD5940_ComplexDivFloat(&DftConst1, &DftRload); // 1/DftRload
res = AD5940_ComplexSubFloat(&temp1, &temp2); // (1/DftRzRload - 1/DftRload)
res = AD5940_ComplexMulFloat(&res, &DftRcal); // 乘以DftRcal
pOut[i].Magnitude = AD5940_ComplexMag(&res)*AppIMPCfg.RcalVal; // 计算阻抗幅值
pOut[i].Phase = AD5940_ComplexPhase(&res); // 计算阻抗相位
}
*pDataCount = ImpResCount; // 更新数据计数为阻抗结果数量
AppIMPCfg.FreqofData = AppIMPCfg.SweepCurrFreq; // 更新数据频率
/* 计算下一个频率点(如果启用扫描) */
if(AppIMPCfg.SweepCfg.SweepEn == bTRUE)
{
AppIMPCfg.FreqofData = AppIMPCfg.SweepCurrFreq; // 设置当前数据频率
AppIMPCfg.SweepCurrFreq = AppIMPCfg.SweepNextFreq; // 更新当前扫描频率
AD5940_SweepNext(&AppIMPCfg.SweepCfg, &AppIMPCfg.SweepNextFreq); // 计算下一个频率
}
return 0; // 成功返回
}
/**
* 中断服务程序
* 处理数据FIFO阈值中断,读取和处理测量数据
* @param pBuff 缓冲区指针
* @param pCount 计数指针
* @return 执行状态
*/
int32_t AppIMPISR(void *pBuff, uint32_t *pCount)
{
uint32_t BuffCount;
uint32_t FifoCnt;
BuffCount = *pCount; // 获取缓冲区计数
*pCount = 0; // 重置计数
/* 唤醒AFE */
if(AD5940_WakeUp(10) > 10) // 通过读寄存器唤醒AFE,最多读10次
return AD5940ERR_WAKEUP; // 唤醒失败
AD5940_SleepKeyCtrlS(SLPKEY_LOCK); // 禁止AFE进入睡眠模式
/* 检查数据FIFO阈值中断 */
if(AD5940_INTCTestFlag(AFEINTC_0, AFEINTSRC_DATAFIFOTHRESH) == bTRUE)
{
/* 现在FIFO中应该有数据 */
FifoCnt = (AD5940_FIFOGetCnt()/6)*6; // 获取FIFO中的数据计数(6的倍数)
if(FifoCnt > BuffCount) // 如果FIFO数据超过缓冲区容量
{
///@todo 缓冲区有限,需要处理
}
/* 从FIFO读取数据 */
AD5940_FIFORd((uint32_t *)pBuff, FifoCnt);
AD5940_INTCClrFlag(AFEINTSRC_DATAFIFOTHRESH); // 清除中断标志
/* 在AFE处于活动状态时进行重新配置(如果需要) */
AppIMPRegModify(pBuff, &FifoCnt);
//AD5940_EnterSleepS(); // 手动将AFE返回休眠模式(此操作仅在先前寄存器值为ACTIVE时生效)
AD5940_SleepKeyCtrlS(SLPKEY_UNLOCK); // 允许AFE进入睡眠模式
/* 处理数据 */
AppIMPDataProcess((int32_t*)pBuff,&FifoCnt);
*pCount = FifoCnt; // 更新计数
return 0; // 成功返回
}
return 0; // 成功返回
}
前面这个是Impedance.c的代码
/******************************************************************************
Copyright (c) 2017-2019 Analog Devices, Inc. All Rights Reserved.
*****************************************************************************/
#include "Impedance.h"
#include "AD5940.H"
#include <stdio.h>
#include <stdint.h>
extern float AppIMPGetCurrFreq(void);
#define APPBUFF_SIZE 512
uint32_t AppBuff[APPBUFF_SIZE];
/* 显示阻抗结果 */
int32_t ImpedanceShowResult(uint32_t *pData, uint32_t DataCount)
{
float freq = AppIMPGetCurrFreq(); /* ✅ 当前频率(非固定) */
fImpPol_Type *pImp = (fImpPol_Type*)pData;
printf("Freq:%.2f Hz, RzMag:%.2f Ohm, RzPhase:%.4f rad, MagnitudeError:%.2f%%\n",
freq,
pImp[0].Magnitude,
pImp[0].Phase,
(pImp[0].Magnitude - 1000.0f) / 10.0f); /* 以1000 Ω为基准的误差 */
return 0;
}
/* 平台配置 */
static int32_t AD5940PlatformCfg(void)
{
CLKCfg_Type clk_cfg;
AD5940_Initialize();
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);
AD5940_INTCCfg(AFEINTC_1, AFEINTSRC_ALLINT, bTRUE);
AD5940_INTCCfg(AFEINTC_0, AFEINTSRC_DATAFIFOTHRESH, bTRUE);
AD5940_INTCClrFlag(AFEINTSRC_ALLINT);
AD5940_SleepKeyCtrlS(SLPKEY_UNLOCK);
return 0;
}
/**
* @brief AD5940阻抗结构体初始化
*/
void AD5940ImpedanceStructInit(void)
{
AppIMPCfg_Type *pImpedanceCfg;
AppIMPGetCfg(&pImpedanceCfg);
/* 基本序列配置 */
pImpedanceCfg->SeqStartAddr = 0;
pImpedanceCfg->MaxSeqLen = 512;
/* 测量参数配置 */
pImpedanceCfg->RcalVal = 200.0f; /* ✅ 修正:板载 RCAL = 200 Ω */
pImpedanceCfg->SinFreq = 1000.0f; /* 仅单频模式有效 */
pImpedanceCfg->FifoThresh = 6;
pImpedanceCfg->ImpODR = 1;
/* 频率扫描 1 Hz – 6 kHz */
pImpedanceCfg->SweepCfg.SweepEn = bTRUE;
/* 在 AD5940ImpedanceStructInit() 里 */
pImpedanceCfg->SweepCfg.SweepStart = 1.0f; /* ✅ 1 Hz */
pImpedanceCfg->SweepCfg.SweepIndex = 0; /* ✅ 强制从第0点开始 */
pImpedanceCfg->SweepCfg.SweepStop = 6000.0f;
pImpedanceCfg->SweepCfg.SweepPoints = 61;
pImpedanceCfg->SweepCfg.SweepLog = bTRUE;
/* 传感器通道 */
pImpedanceCfg->SensorCh0.LpTiaRf = LPTIARF_1M;
pImpedanceCfg->SensorCh0.LpTiaRl = LPTIARLOAD_1K6; /* 1.6 kΩ 负载 */
pImpedanceCfg->SensorCh0.LptiaRtiaSel = LPTIARTIA_1K; /* 1 kΩ RTIA */
pImpedanceCfg->SensorCh0.Vzero = 1100;
pImpedanceCfg->SensorCh0.SensorBias = 0;
/* 开关矩阵 */
pImpedanceCfg->DswitchSel = SWD_CE0;
pImpedanceCfg->PswitchSel = SWP_RE0;
pImpedanceCfg->NswitchSel = SWN_SE0LOAD;
pImpedanceCfg->TswitchSel = SWT_SE0LOAD;
/* 高速 TIA */
pImpedanceCfg->HstiaRtiaSel = HSTIARTIA_1K;
/* 激励 */
pImpedanceCfg->DacVoltPP = 100.0f; /* 100 mV 峰峰值 */
/* 功率模式 */
pImpedanceCfg->PwrMod = AFEPWR_LP;
/* 信号链 */
pImpedanceCfg->DftNum = DFTNUM_16384;
pImpedanceCfg->DftSrc = DFTSRC_SINC3;
pImpedanceCfg->ADCSinc3Osr = ADCSINC3OSR_4;
pImpedanceCfg->HanWinEn = bTRUE;
/* 强制重生成序列 */
pImpedanceCfg->bParaChanged = bTRUE; /* ✅ 关键 */
}
/* 主函数 */
void AD5940_Main(void)
{
AD5940PlatformCfg(); /* 平台初始化 */
AD5940ImpedanceStructInit(); /* 参数初始化 */
/* 清 FIFO 旧数据 */
AD5940_FIFOCtrlS(FIFOSRC_DFT, bFALSE);
AD5940_FIFOCtrlS(FIFOSRC_DFT, bTRUE);
AppIMPInit(AppBuff, APPBUFF_SIZE); /* 生成序列 */
AppIMPCtrl(IMPCTRL_START, 0); /* 启动测量 */
while(1)
{
if(AD5940_GetMCUIntFlag())
{
AD5940_ClrMCUIntFlag();
uint32_t cnt = APPBUFF_SIZE;
AppIMPISR(AppBuff, &cnt);
if(cnt) ImpedanceShowResult(AppBuff, cnt);
}
}
}
前面这个是AD5940Main.c的代码/******************************************************************************
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 <stdio.h>
#include "ad5940.h"
#include "ADuCM355.h"
#include "ClkLib.h"
#include "UrtLib.h"
#include "DioLib.h"
//Define this parameter for readings on CH0 only, otherwise readings will be taken on CH0 and CH1
//#define CH0_ONLY
void UartInit(void);
void ClockInit(void);
int main(void)
{
void AD5940_Main(void);
//AfeWdtGo(false); // Disable Watchdog for debug purposes
pADI_AFEWDT->WDTCON &=(~BITM_AFEWDT_WDTCON_EN);
ClockInit();
UartInit();
AD5940_MCUResourceInit(0); /* Inialize all peripherals etc. used for AD5940/AFE. */
AD5940_Main();
}
void ClockInit(void)
{
DigClkSel(DIGCLK_SOURCE_HFOSC);
ClkDivCfg(1,1); //时钟分频配置:HCLK(系统时钟)= PCLK(外设时钟)= 26MHz
}
// Initialize UART for 230400-8-N-1
void UartInit(void)
{
DioCfgPin(pADI_GPIO0,PIN10|PIN11,1); // Setup P0.10, P0.11 as UART pin
UrtCfg(pADI_UART0,256000,
(BITM_UART_COMLCR_WLS|3),0); // Configure UART for 57600 baud rate
UrtFifoCfg(pADI_UART0, RX_FIFO_1BYTE, // Configure the UART FIFOs for 8 bytes deep
BITM_UART_COMFCR_FIFOEN);
UrtFifoClr(pADI_UART0, BITM_UART_COMFCR_RFCLR// Clear the Rx/TX FIFOs
|BITM_UART_COMFCR_TFCLR);
}
前面这个是main.c的代码。我在官方M355_ECSns_EIS的例程上进行修改,将官方的稳定60KHz进行单点扫描,改为1Hz到6000Hz进行对数扫描。我用三电极系统进行测量,工作电极和参比电极夹在电阻一侧,对电极夹在电阻另一侧,目前在1Hz到21Hz区间段频率下无法精准测量1000欧姆阻值,误差偏大,如图所示
蓝色标注部分为误差偏大部分。这部分为我的硬件原理图
PDF。请求各路大神帮忙解决1Hz到6000Hz区间段测阻抗误差偏大的问题。