芯科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 蓝牙SOC EFR32BG系列IADC与ADC的区别

Silicon Labs蓝牙SOC EFR32BG系列包括有EFR32BG12/13和EFR32BG21两个子系列,其中EFR32BG12/13采用的是Cortex-M4内核,EFR32BG21采用的是Cortex-M33内核,二者的内核不同,另外,EFR32BG12/13集成有IADC,EFR32BG21集成的是ADC,两个ADC还是有一些区别的,在使用时需要注意一下,本文介绍其区别。

2020-02-21 -  设计经验 代理服务 技术支持 现货查询 批量订货

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

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

2024-05-16 -  技术探讨 代理服务 技术支持 现货查询 批量订货

【成功案例】内置24位ADC的MCU在交流三相电监测上的应用

Silicon labs 推出的C8051F350内置24位ADC,以低廉的价格和优异的ADC转换能力,被用在各种信号检测上。在输出率调制器时钟频率2.4576MHz,抽取比1900,输出字率10Hz的情况下本系统可以达到20位的分辨率,RMS噪声仅为2.3uV,能够很好的完成相间电压监测任务。本文通过真实项目案例推荐C8051F350混合型MCU。

2017-12-27 -  新应用 代理服务 技术支持 现货查询 批量订货

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

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

2024-01-30 -  应用方案 代理服务 技术支持 现货查询 批量订货

【经验】芯科Si4463无线收发芯片使用ADC读取芯片内部温度的方法

Silicon Labs的Si4463无线收发芯片内部有一个温度传感器,我们可以使用ADC来读取芯片内部的温度,本文主要介绍如何使用ADC读取Si4463芯片温度的方法。

2022-11-02 -  设计经验 代理服务 技术支持 现货查询 批量订货

【经验】8位单片机EFM8系列的ADC对参考电压Vref引脚设计要求

Silicon Labs的8位单片机EFM8系列,高精度ADC功能时该芯片的一大特点,为了ADC获得准确的采用值,除了正确操作ADC外设外,还需要正确设计参考电压,结合EFM8芯片的特点,介绍参考电压设计需要注意的事项。

2019-10-29 -  设计经验 代理服务 技术支持 现货查询 批量订货

Emerging Bluetooth LE Use Cases and Applications

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

August 2023  - SILICON LABS  - 数据手册 代理服务 技术支持 现货查询 批量订货

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

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

2018-01-23 -  技术探讨 代理服务 技术支持 现货查询 批量订货

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

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

2019-12-17 -  技术问答

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

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

2023-06-28 -  设计经验 代理服务 技术支持 现货查询 批量订货

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

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

2016-10-25 -  技术问答

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

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

2020-11-18 -  设计经验 代理服务 技术支持 现货查询 批量订货

芯科科技新型xG27无线SoC系列,仅4mm²占位面积,为极小型智能家居设备带来安全且高性能网状网络

Silicon Labs(亦称“芯科科技”)无线产品营销高级经理Mikko Nurmimaki先生近期制作一篇博文介绍新型xG27无线SoC系列如何促进智能家居的设备开发进一步迈向极小型、高安全且高性能,并支持广泛的多协议网状网络技术。

2023-04-05 -  原厂动态 代理服务 技术支持 现货查询 批量订货
展开更多

电子商城

查看更多

品牌:SILICON LABS

品类:Wireless Gecko SoC

价格:¥8.1764

现货: 103,878

品牌:SILICON LABS

品类:Wireless SoC

价格:¥31.7756

现货: 88,300

品牌:SILICON LABS

品类:Wireless SoC

价格:¥35.3989

现货: 87,882

品牌:SILICON LABS

品类:Wireless Gecko SoC

价格:¥10.4994

现货: 59,949

品牌:SILICON LABS

品类:Wireless Gecko SoC

价格:¥19.2326

现货: 2,500

品牌:SILICON LABS

品类:8位MCU

价格:¥4.4595

现货: 26,040

品牌:SILICON LABS

品类:8位MCU

价格:¥9.7560

现货: 16,500

品牌:SILICON LABS

品类:8位MCU

价格:¥7.6187

现货: 11,496

品牌:SILICON LABS

品类:8位MCU

价格:¥12.8215

现货: 9,414

品牌:SILICON LABS

品类:8位MCU

价格:¥21.1835

现货: 9,389

品牌:

品类:

价格:

现货:

品牌:

品类:

价格:

现货:

品牌:

品类:

价格:

现货:

品牌:

品类:

价格:

现货:

品牌:

品类:

价格:

现货:

品牌:

品类:

价格:

现货:

品牌:

品类:

价格:

现货:

品牌:

品类:

价格:

现货:

品牌:

品类:

价格:

现货:

品牌:

品类:

价格:

现货:

现货市场

查看更多

品牌: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

收藏
收藏当前页面