芯科ADC采集使用tailgating实现周期扫描与随机单次采样而不影响周期扫描采样时序的方法

2023-12-22 世强
adc,BG22,XG22,XG21 adc,BG22,XG22,XG21 adc,BG22,XG22,XG21 adc,BG22,XG22,XG21

我们在使用adc采样的时候有时候会遇到这样的场景,只用一个ADC,有一个需要周期采样的数据,并且时序要求比较高,比如心电数据这种时序要求高的采样对象,并且想多采样多个其他数据比如板子上的其他温度,气压,电压数据等这类对时序无要求的数据,正常我们的解决方案有两种:


1)将这类数据放到adc扫描列表中,而当产品对功耗非常敏感时,将这类较长时间才采样一次的数据放置到扫描列表里每次都参加扫描,将会导致功耗浪费在许多不需要的采集中,这是功耗敏感型应用所无法接受的

2)判断下扫描周期时间,避开adc周期采样时间,避免影响到adc周期扫描采样,但是这样也会导致功耗上升并且实现方法较为复杂


而在芯科的adc参考手册中,你可以看到这样一种方法,它可以实现不影响周期采样的时序的情况下,随机穿插一个单次采样,并且相对只有周期扫描的功耗上升微乎其微,这种方法叫tailgating,意思就是在adc采集时增加一个队列,将采集的命令都放在队列中,在随机来的采样命令中放置队列尾部,在每次周期采样时间实现队列中的命令,以下为原理:



实现的方法很简单,只需要将scan和single的adc采样方式,一起进行初始化,将scan ADC的命令放在定时器的周期中断中实现周期scan采样,然后在任意时候使用单次采样都会在下一次scan命令采集完进行单次采样命令。


下面是以定时中断扫描,按键触发单次采样并以串口输出结果为例的代码示例:


1、初始化ADC

void initIADC(void)

{

 app_log("Init adc_tailgating\r\n");

 // Declare initialization structures

 IADC_Init_t init = IADC_INIT_DEFAULT;

 IADC_AllConfigs_t initAllConfigs = IADC_ALLCONFIGS_DEFAULT;

 IADC_InitScan_t initScan = IADC_INITSCAN_DEFAULT;

 /*******************************************************************/

 IADC_InitSingle_t initSingle = IADC_INITSINGLE_DEFAULT;

 IADC_SingleInput_t initSingleInput = IADC_SINGLEINPUT_DEFAULT;

 /*******************************************************************/

 // Scan table structure

 IADC_ScanTable_t scanTable = IADC_SCANTABLE_DEFAULT;


 CMU_ClockEnable(cmuClock_IADC0, true);

 /*******************************************************************/

 app_log("ready to IADC_reset\r\n");

 IADC_reset(IADC0);

 app_log("IADC_reset done \r\n");

 /*******************************************************************/

 // Use the FSRC0 as the IADC clock so it can run in EM2

 CMU_ClockSelectSet(cmuClock_IADCCLK, cmuSelect_FSRCO);


 // Set the prescaler needed for the intended IADC clock frequency

 init.srcClkPrescale = IADC_calcSrcClkPrescale(IADC0, CLK_SRC_ADC_FREQ, 0);


 // Shutdown between conversions to reduce current

 init.warmup = iadcWarmupNormal;

 initSingle.singleTailgate = tailgating_switch;

 /*

  * Configuration 0 is used by both scan and single conversions by

  * default.  Use internal bandgap as the reference and specify the

  * reference voltage in mV.

  *

  * Resolution is not configurable directly but is based on the

  * selected oversampling ratio (osrHighSpeed), which defaults to

  * 2x and generates 12-bit results.

  */


 initAllConfigs.configs[0].reference = iadcCfgReferenceInt1V2;

 initAllConfigs.configs[0].vRef = 1210;

 initAllConfigs.configs[0].osrHighSpeed = iadcCfgOsrHighSpeed2x;

 initAllConfigs.configs[0].analogGain = iadcCfgAnalogGain0P5x;


 /*

  * CLK_SRC_ADC is prescaled to derive the intended CLK_ADC frequency.

  *

  * Based on the default 2x oversampling rate (OSRHS)...

  *

  * conversion time = ((4 * OSRHS) + 2) / fCLK_ADC

  *

  * ...which, results in a maximum sampling rate of 833 ksps with the

  * 2-clock input multiplexer switching time is included.

  */

 initAllConfigs.configs[0].adcClkPrescale = IADC_calcAdcClkPrescale(IADC0,

                                                                    CLK_ADC_FREQ,

                                                                    0,

                                                                    iadcCfgModeNormal,

                                                                    init.srcClkPrescale);


 /*

  * Set the SCANFIFODVL flag when there are 4 entries in the scan

  * FIFO.

  *

  * Tag FIFO entries with scan table entry IDs.

  *

  * Allow a scan conversion sequence to start as soon as there is a

  * trigger event.

  */

 initScan.dataValidLevel = iadcFifoCfgDvl4;

 initScan.showId = true;

 initScan.start = true;


 /*

  * Configure entries in scan table.  CH0 is single-ended from

  * input 0; CH1 is single-ended from input 1.

  */

 scanTable.entries[0].posInput = IADC_INPUT_0_PORT_PIN;

 scanTable.entries[0].negInput = iadcNegInputGnd;

 scanTable.entries[0].includeInScan = true;


 scanTable.entries[1].posInput = IADC_INPUT_1_PORT_PIN;

 scanTable.entries[1].negInput = iadcNegInputGnd;

 scanTable.entries[1].includeInScan = true;


 scanTable.entries[2].posInput = iadcPosInputAvdd;      // Add AVDD to scan for demonstration purposes

 scanTable.entries[2].negInput = iadcNegInputGnd | 1;   // When measuring a supply, PINNEG must be odd (1, 3, 5,...)

 scanTable.entries[2].includeInScan = true;


 scanTable.entries[3].posInput = iadcPosInputVddio;     // Add VDDIO to scan for demonstration purposes

 scanTable.entries[3].negInput = iadcNegInputGnd | 1;   // When measuring a supply, PINNEG must be odd (1, 3, 5,...)

 scanTable.entries[3].includeInScan = true;


 scanTable.entries[4].posInput = iadcPosInputVss;       // Add VSS to scan for demonstration purposes

 scanTable.entries[4].negInput = iadcNegInputGnd | 1;   // When measuring a supply, PINNEG must be odd (1, 3, 5,...)

 scanTable.entries[4].includeInScan = false;            // FIFO is only 4 entries deep


 scanTable.entries[5].posInput = iadcPosInputVssaux;    // Add VSSAUX (same as VSS) to scan for demonstration purposes

 scanTable.entries[5].negInput = iadcNegInputGnd | 1;   // When measuring a supply, PINNEG must be odd (1, 3, 5,...)

 scanTable.entries[5].includeInScan = false;


 scanTable.entries[6].posInput = iadcPosInputDvdd;      // Add DVDD to scan for demonstration purposes

 scanTable.entries[6].negInput = iadcNegInputGnd | 1;   // When measuring a supply, PINNEG must be odd (1, 3, 5,...)

 scanTable.entries[6].includeInScan = false;


 scanTable.entries[7].posInput = iadcPosInputDecouple;  // Add DECOUPLE to scan for demonstration purposes

 scanTable.entries[7].negInput = iadcNegInputGnd | 1;   // When measuring a supply, PINNEG must be odd (1, 3, 5,...)

 scanTable.entries[7].includeInScan = false;


 // Initialize IADC

 IADC_init(IADC0, &init, &initAllConfigs);


 // Initialize scan

 IADC_initScan(IADC0, &initScan, &scanTable);


 /*******************************************************************/

 // Initialize Single

 IADC_initSingle(IADC0, &initSingle, &initSingleInput);

 /*******************************************************************/


 // Allocate the analog bus for IADC0 inputs

 GPIO->IADC_INPUT_0_BUS |= IADC_INPUT_0_BUSALLOC;

 GPIO->IADC_INPUT_1_BUS |= IADC_INPUT_1_BUSALLOC;


 // Clear any previous interrupt flags

 IADC_clearInt(IADC0, _IADC_IF_MASK);


 // Enable scan interrupts

 IADC_enableInt(IADC0, IADC_IEN_SCANTABLEDONE);


 // Enable single done interrupts

  IADC_enableInt(IADC0, IADC_IEN_SINGLEDONE);


 // Enable IADC interrupts

 NVIC_ClearPendingIRQ(IADC_IRQn);

 NVIC_EnableIRQ(IADC_IRQn);

}

2、初始化定时器,1秒定时

/**************************************************************************//**

* @brief LETIMER initialization

*****************************************************************************/

void initLETIMER(void)

{

 CMU_LFXOInit_TypeDef lfxoInit = CMU_LFXOINIT_DEFAULT;

 LETIMER_Init_TypeDef letimerInit = LETIMER_INIT_DEFAULT;


 // Initialize the LFXO and use it as the EM23GRPACLK source

 CMU_LFXOInit(&lfxoInit);

 CMU_ClockSelectSet(cmuClock_EM23GRPACLK, cmuSelect_LFXO);


 CMU_ClockEnable(cmuClock_LETIMER0, true);


 // Calculate the top value (frequency) based on clock source

 uint32_t topValue = CMU_ClockFreqGet(cmuClock_LETIMER0) / LETIMER_FREQ;


 // Reload top on underflow, pulse output, and run in free mode

 letimerInit.comp0Top = true;

 letimerInit.topValue = topValue;

 letimerInit.ufoa0 = letimerUFOAPulse;

 letimerInit.repMode = letimerRepeatFree;


 // Initialize LETIMER

 LETIMER_Init(LETIMER0, &letimerInit);


 // Clear any previous interrupt flags

 LETIMER_IntClear(LETIMER0, _LETIMER_IF_MASK);


 // Enable underflow interrupts

 LETIMER_IntEnable(LETIMER0, LETIMER_IEN_UF);


 // Enable LETIMER interrupts

 NVIC_ClearPendingIRQ(LETIMER0_IRQn);

 NVIC_EnableIRQ(LETIMER0_IRQn);

 app_log("LETIMER0 init done\r\n");

}

3、定时器中断

/**************************************************************************//**

* @brief  LETIMER IRQ Handler

*****************************************************************************/

void LETIMER0_IRQHandler(void)

{

 uint32_t flags = LETIMER_IntGet(LETIMER0);


 // Trigger an IADC scan conversion

 IADC_command(IADC0, iadcCmdStartScan);


 app_log("LETIMER0 timeout\r\n");


 // Clear LETIMER interrupt flags

 LETIMER_IntClear(LETIMER0, flags);

}


4、采样中断

/**************************************************************************//**

* @brief  IADC interrupt handler

*****************************************************************************/

void IADC_IRQHandler(void)

{

 IADC_Result_t result = {0, 0};



 // While the FIFO count is non-zero...

 while (IADC_getScanFifoCnt(IADC0))

 {

   // Pull a scan result from the FIFO

   result = IADC_pullScanFifoResult(IADC0);


   /*

    * Calculate the voltage converted as follows:

    *

    * For single-ended conversions, the result can range from 0 to

    * +Vref, i.e., for Vref = VBGR = 1.21V, and with analog gain = 0.5,

    * 0xFFF represents the full scale value of 2.42V.

    */

   scanResult[result.id] = result.data * 2.42 / 0xFFF;

   /*

    * Scan results 2 - 6 are for external supply voltages, which are

    * presented to the IADC divided by 4 for conversion.  Back this

    * out to get the correct result in volts.  Note that DECOUPLE,

    * scan table entry 7 in this example, is an internal supply (the

    * output of the core supply regulator) and is connected directly

    * to the IADC without a divide-by-4 stage.

    */

   if ((result.id > 1) && (result.id < 7)) {

     scanResult[result.id] *= 4;

   }

   app_log("scanResult[%d] : %lf\r\n",result.id,scanResult[result.id]);

 }


   while (IADC_getSingleFifoCnt(IADC0))

   {


     sample = IADC_pullSingleFifoResult(IADC0);


     singleResult = sample.data * 2.42 / 0xFFF;


     app_log("singleResult : %lf\r\n",singleResult);

   }

 // Alternate between the first and second set of scan table entries.

 if (result.id == 3) {

   IADC_setScanMask(IADC0, 0x0070);

 }

 else {

   IADC_setScanMask(IADC0, 0x000F);

 }


 /*

  * Clear the scan table complete interrupt.  Reading FIFO results

  * does not do this automatically.

  */

 IADC_clearInt(IADC0, IADC_IF_SCANTABLEDONE);

 IADC_clearInt(IADC0, IADC_IF_SINGLEDONE);


}


5、按键中断

void sl_button_on_change(const sl_button_t *handle)

{

 (void)handle;

 IADC_command(IADC0, iadcCmdStartSingle);

}



授权代理商:世强先进(深圳)科技股份有限公司
技术资料,数据手册,3D模型库,原理图,PCB封装文件,选型指南来源平台:世强硬创平台www.sekorm.com
现货商城,价格查询,交期查询,订货,现货采购,在线购买,样品申请渠道:世强硬创平台电子商城www.sekorm.com/supply/
概念,方案,设计,选型,BOM优化,FAE技术支持,样品,加工定制,测试,量产供应服务提供:世强硬创平台www.sekorm.com
集成电路,电子元件,电子材料,电气自动化,电机,仪器全品类供应:世强硬创平台www.sekorm.com
  • +1 赞 0
  • 收藏
  • 评论 0

本文由SpiderMan提供,版权归世强硬创平台所有,非经授权,任何媒体、网站或个人不得转载,授权转载时须注明“来源:世强硬创平台”。

评论

   |   

提交评论

全部评论(0

暂无评论

相关推荐

【经验】EFR32BG22系列蓝牙SOC电池电压与VDD供电电压检测ADC的方法

EFR32BG22作为低功耗蓝牙SOC方案,经常应用于电池供电的方案中,一般采用内部的ADC作为采集通道,内部的输入源作为输入接口,来测试VDD供电电压。本文将讲解电池电压与VDD供电电压检测ADC的方法。

设计经验    发布时间 : 2020-11-28

【经验】蓝牙SoC EFR32BG22的高精度ADC配置步骤与注意事项

Silicon Labs的EFR32BG22系列蓝牙SoC内部集成高精度ADC功能,采用内部1.21V作为Vref,ADC真实有效位数可达13.5bit,使用外部1.25V基准源作为Vref,精度可达14.3bit。本文介绍ADC配置相关步骤以及注意项目。

设计经验    发布时间 : 2020-11-04

【经验】如何解决Silicon Labs EFR32B22在开启一次ADC转换后,功耗变高的问题?

在使用芯科科技EFR32BG22蓝牙SoC开发低功耗应用时,可能会使用到ADC这个外设,但在ADC转换后,会出现芯片在休眠时功耗比较高的情况。本文将介绍如何解决EFR32B22在开启一次ADC转换后,功耗变高的问题?

设计经验    发布时间 : 2023-06-28

解决物联网应用的网络安全性议题

随着物联网应用的普及,物联网设备已经逐渐出现在我们的日常生活之中,但这些产品也成为了恶意份子攻击的目标,如何确保物联网设备的安全性,成为产品开发过程中必须要关注的议题。本文将为您介绍物联网应用所面对的网络攻击问题,以及由Silicon Labs所推出的相关解决方案的功能与特性。

技术探讨    发布时间 : 2024-05-16

高性价比Silicon labs EFM8单片机,STM8完美备选方案

Silicon Labs EFM8BB系列8位单片机采用流水线式CIP-51内核,70%指令的执行时间为1-2个时钟周期,与标准的8051指令集完全兼容,外设资源、性能指标及设计灵活性都具有自身独特的优势。

新产品    发布时间 : 2018-02-08

【技术】EFM8LB单片机之14位高精度ADC模数转换器,900Ksps采样率

Silicon Labs推出的EFM8LB系列8位单片机, 操作频率最高为72MHz, 3mm × 3mm的QFN封装,集成14位ADC模数转换器和4路12位DAC数模转换输出。

技术探讨    发布时间 : 2018-01-23

芯科科技推出包含一整套业界前沿先进安全功能的Secure Vault,解决物联网应用的网络安全

Silicon Labs推出的Secure Vault包含一整套业界前沿的先进安全功能,可解决不断升级的物联网威胁,极大降低物联网生态系统安全漏洞风险,降低因仿冒导致的知识产权或收入损失的影响,将可提升物联网设备的安全性。

应用方案    发布时间 : 2024-01-30

最高精度的ADC采样的单片机,能够达到多少位?

Silicon Labs 8位MCU C8051F350集成的ADC可以达到24位。还有芯海科技的8位MCU CSU8RP1186/CSU18MB86等集成的ADC也可以达到24位、芯海的BLE SOC CST34M96集成的ADC也是24位的。

技术问答    发布时间 : 2019-12-17

C8051F91x-C8051F90x Single/Dual Battery, 0.9–3.6 V, 16–8 kB, SmaRTClock, 12/10-Bit ADC MCU

型号- C8051F902-D-GU,C8051F90X,C8051F901-D-GDI,C8051F911-D-GDI,C8051F91X,C8051F902-D-GM,C8051F902-D-GDI,C8051F912-D-GDI,C8051F912-D-GM,C8051F901-D-GM,C8051F911-D-GU,C8051F912-D-GU,C8051F901-D-GU,C8051F911-D-GM

数据手册  -  SILICON LABS  - Rev. 1.4  - 2022/3/22 PDF 英文 下载 查看更多版本

我使用的是芯片EFR32MG1P232F256GM48,创建的是BLE工程,使能了UART,IIC,SPI,ADC,其他的都是普通IO口, 在进入EM2后,电流在170-300ua跳动,请问下在em2时应该怎么设置使功耗最低,外围硬件除外。看门狗和rtcc默认是没使能的吧,像UART,IIC,SPI,ADC这些在进入em2时要不要设置?

1、Silicon Labs 蓝牙BLE低功耗测试,可以参考:【经验】EFR32BG系列蓝牙SoC之低功耗测试操作指导在这个测试指导里面,使用到的参考工程,都是没有开启这些外设的,可以先测试一下。2、开启外设之后,需要考虑进入EM2模式后,为了实现最低功耗,这些外设需要关闭,尤其是ADC模块需要关闭,同时考虑这些外设所使用的GPIO外围电路,是否有放电的回路,如果有的话,也需要配置GPIO的方向,输入输出,上拉等配置。3、建议单个外设模块单独添加,并测试进入EM2后的功耗情况,以便查找功耗问题。

技术问答    发布时间 : 2020-06-08

需要遥控器钥匙方案,了解到无线单片机产品Si4010是不带ADC功能,是否有带有ADC功能的类似无线芯片?

新款无线MCU Si106x/8x就符合,属于主推无线单片机,既有发射模块,也有AD模块。

技术问答    发布时间 : 2016-10-25

Emerging Bluetooth LE Use Cases and Applications

型号- RS9116W,XG27,XGM210P,XG24,XGM220P,RS9116,XGM240P,XG22,XG21,XGM220S,XGM240S,XGM27

数据手册  -  SILICON LABS  - August 2023 PDF 英文 下载

【经验】蓝牙SoC EFR32BG22的差分ADC配置注意事项

Silicon Labs的蓝牙SoC EFR32BG22在使用内部的VREF=1.2V的时候,ADC的实际有效bit为13.5,对除了需要蓝牙功能、还对模拟信号输入有要求的方案具有非常大优势。使用差分输入的方式,可以提高ADC的精度,有效避开干扰。本文主要介绍差分ADC的配置注意事项。

设计经验    发布时间 : 2020-11-18

对于8位单片机EFM8LB10,在使用ADC功能时,如何计算ADC详细的转换时间以及速率?

根据EFM8LB1 Datasheet,ADC转换总所需时间为:Total ConverSion Time=RPT×(ADTK+NUMBITS+1)×T(SARCLK)+(T(ADCCLK)×4);where RPT is the number of converSions represented by the ADRPT field and ADCCLK is the clock selected for the ADC;在高速模式下,以最快的SARCLK为18MHz 计算,跟踪时间至少需230ns( =T(SARCLK)x4),若RPT为累计一个样本,ADCCLK为系统时钟72MHz,那么ADC的转换速率约为:14 Bit Mode:1/[230ns+(14+1)/18MHz+4/72MHz]=0.9Mbps;12 Bit Mode:1/[230ns+(12+1)/18MHz+4/72MHz]=1Mbps;10 Bit Mode:1/[230ns+(10+1)/18MHz+4/72MHz]=1.1Mbps。

技术问答    发布时间 : 2017-05-05

C8051F930-G1DI Tested Single/Dual Battery, 0.9–3.6 V, 64 kB Flash, SmaRTClock, 10-Bit ADC MCU Die in Wafer Form

型号- C8051F930-G-GDI,C8051F930-G1DI,C8051F93X,C8051F930G,C8051F930-G-G1DI,C8051F92X,C8051F930-GDI

数据手册  -  SILICON LABS  - Rev. 1.4  - 3/23 PDF 英文 下载

展开更多

电子商城

查看更多

品牌:SILICON LABS

品类:Wireless Gecko SoC

价格:¥8.1764

现货: 104,128

品牌:SILICON LABS

品类:Wireless SoC

价格:¥31.7756

现货: 88,300

品牌:SILICON LABS

品类:Wireless SoC

价格:¥35.3989

现货: 80,632

品牌:SILICON LABS

品类:Wireless Gecko SoC

价格:¥10.4994

现货: 61,779

品牌:SILICON LABS

品类:Wireless Gecko SoC

价格:¥19.2326

现货: 2,500

品牌:SILICON LABS

品类:8位MCU

价格:¥4.4595

现货: 27,240

品牌:SILICON LABS

品类:8位MCU

价格:¥9.7560

现货: 16,500

品牌:SILICON LABS

品类:8位MCU

价格:¥7.6187

现货: 11,496

品牌:SILICON LABS

品类:8位MCU

价格:¥21.1835

现货: 9,889

品牌:SILICON LABS

品类:8位MCU

价格:¥12.8215

现货: 9,414

品牌:

品类:

价格:

现货:

品牌:

品类:

价格:

现货:

品牌:

品类:

价格:

现货:

品牌:

品类:

价格:

现货:

品牌:

品类:

价格:

现货:

品牌:

品类:

价格:

现货:

品牌:

品类:

价格:

现货:

品牌:

品类:

价格:

现货:

品牌:

品类:

价格:

现货:

品牌:

品类:

价格:

现货:

现货市场

查看更多

品牌:SILICON LABS

品类:Wireless SoC

价格:¥15.1400

现货:1,455

品牌:国民技术

品类:微控制器

价格:¥18.7261

现货:25,138

品牌:TI

品类:模数转换芯片ADC

价格:¥3.8700

现货:13,251

品牌:中科芯

品类:32位微控制器

价格:¥8.5000

现货:10,000

品牌:华科鸿溟

品类:I²C接口数字温度传感器

价格:¥1.2250

现货:10,000

品牌:上海贝岭

品类:免校准计量芯片

价格:¥2.5000

现货:10,000

品牌:中科芯

品类:32位微控制器

价格:¥5.0000

现货:10,000

品牌:中微半导体

品类:MCU

价格:¥2.5200

现货:4,378

品牌:汇顶科技

品类:高精度多功能交互传感器

价格:¥2.3556

现货:2,987

品牌:TI

品类:MCU

价格:¥124.3000

现货:2,872

品牌:

品类:

价格:

现货:

品牌:

品类:

价格:

现货:

品牌:

品类:

价格:

现货:

品牌:

品类:

价格:

现货:

品牌:

品类:

价格:

现货:

品牌:

品类:

价格:

现货:

品牌:

品类:

价格:

现货:

品牌:

品类:

价格:

现货:

品牌:

品类:

价格:

现货:

品牌:

品类:

价格:

现货:

查看更多

授权代理品牌:接插件及结构件

查看更多

授权代理品牌:部件、组件及配件

查看更多

授权代理品牌:电源及模块

查看更多

授权代理品牌:电子材料

查看更多

授权代理品牌:仪器仪表及测试配组件

查看更多

授权代理品牌:电工工具及材料

查看更多

授权代理品牌:机械电子元件

查看更多

授权代理品牌:加工与定制

世强和原厂的技术专家将在一个工作日内解答,帮助您快速完成研发及采购。
我要提问

954668/400-830-1766(工作日 9:00-18:00)

service@sekorm.com

研发客服
商务客服
服务热线

联系我们

954668/400-830-1766(工作日 9:00-18:00)

service@sekorm.com

投诉与建议

E-mail:claim@sekorm.com

商务合作

E-mail:contact@sekorm.com

收藏
收藏当前页面