2320|2

504

帖子

4

TA的资源

纯净的硅(高级)

楼主
 

【RTT&英飞凌PSoC6评估板(带触摸)】ADC测试与音频采集 [复制链接]

本帖最后由 qinyunti 于 2023-6-24 10:39 编辑

f54c020b5b79171138481b8508dd67aa

 

前言

本篇进行ADC的测试以及音频的采集。

 

原理图

有6路模拟输入,分别对应

P10.0~P10.5,  VREF为模拟参考电压。

 

 

 

 

ADC模块介绍

参考《Infineon-PSoC_6_MCU_CY8C6xx8_CY8C6xxA_Architecture_Technical_Reference_Manual_(TRM)-AdditionalTechnicalInformation-v08_00-EN.pdf》的Section E: Analog Subsystem

 

特征

AREF 产生电压参考

由一个带隙参考电路产生的1.2 V电压参考(VREFBG)

来自SRSS块的0.8 V参考

来自外部引脚的外部参考

AREF 产生电流参考

零温度系数IZTAT生成器产生1µA电流。

从SRSS的250 nA参考电流放大4倍得到1µA电流。

 

  1. 一个12位逐次逼近寄存器,1-Msps 模数转换器(SAR ADC)。
  2. 十六个可单独配置的逻辑通道,可以扫描十一个唯一的输入通道。每个通道都具有以下功能:

来自八个专用引脚的输入(八个单端模式或四个差分输入)或内部信号(AMUXBUS或温度传感器)

每个通道可以选择四个可编程采集时间中的一个来设置采集时间

支持单端和差分

支持平均和累加

结果双缓存

  1. 结果可左对齐,右对齐,16位符号扩展
  2. 软件,其他外设,引脚触发,单次和连续模式
  3. 支持2、4、8、16、32、64、128和256个样本(2的幂)的一阶累加
  4. 参考电压

VDDA和VDDA/2

内部1.2V

外部参考

  1. 中断

扫描结束

饱和或者超量程

结果溢出

碰撞检测

 

 

采集时间

最少需要18个CLK

 

 

时钟

来源于SRSS必须为1.8MHz~18MHz之间

 

时序

 

配置模拟采集引脚

 

 

 

代码

Adc.c

#include "cy_pdl.h"

#include "cyhal.h"

#include "cybsp.h"

#include "cy_retarget_io.h"

 

#define VPLUS_CHANNEL_0  (P10_0)

/* Conversion factor */

#define MICRO_TO_MILLI_CONV_RATIO        (1000u)

 

/* Acquistion time in nanosecond */

#define ACQUISITION_TIME_NS              (116680u)

 

/* ADC Scan delay in millisecond */

#define ADC_SCAN_DELAY_MS                (200u)

 

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

*       Enumerated Types

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

/* ADC Channel constants*/

enum ADC_CHANNELS

{

  CHANNEL_0 = 0,

  NUM_CHANNELS

} adc_channel;

 

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

* Global Variables

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

/* ADC Object */

cyhal_adc_t adc_obj;

 

/* ADC Channel 0 Object */

cyhal_adc_channel_t adc_chan_0_obj;

 

/* Default ADC configuration */

const cyhal_adc_config_t adc_config = {

        .continuous_scanning=false, // Continuous Scanning is disabled

        .average_count=1,           // Average count disabled

        .vref=CYHAL_ADC_REF_VDDA,   // VREF for Single ended channel set to VDDA

        .vneg=CYHAL_ADC_VNEG_VSSA,  // VNEG for Single ended channel set to VSSA

        .resolution = 12u,          // 12-bit resolution

        .ext_vref = NC,             // No connection

        .bypass_pin = NC };       // No connection

 

/* Asynchronous read complete flag, used in Event Handler */

static bool async_read_complete = true;

#define NUM_SCAN                    (1000)

#define NUM_CHANNELS                (1)

/* Variable to store results from multiple channels during asynchronous read*/

int32_t result_arr[NUM_CHANNELS * NUM_SCAN] = {0};

 

static void adc_event_handler(void* arg, cyhal_adc_event_t event)

{

    if(0u != (event & CYHAL_ADC_ASYNC_READ_COMPLETE))

    {

        /* Set async read complete flag to true */

        async_read_complete = true;

    }

}

 

int adc_init(void)

{

    /* Variable to capture return value of functions */

    cy_rslt_t result;

 

    /* Initialize ADC. The ADC block which can connect to the channel 0 input pin is selected */

    result = cyhal_adc_init(&adc_obj, VPLUS_CHANNEL_0, NULL);

    if(result != CY_RSLT_SUCCESS)

    {

        printf("ADC initialization failed. Error: %ld\n", (long unsigned int)result);

        CY_ASSERT(0);

    }

 

    /* ADC channel configuration */

    const cyhal_adc_channel_config_t channel_config = {

            .enable_averaging = false,  // Disable averaging for channel

            .min_acquisition_ns = ACQUISITION_TIME_NS, // Minimum acquisition time set to 1us

            .enabled = true };          // Sample this channel when ADC performs a scan

 

    /* Initialize a channel 0 and configure it to scan the channel 0 input pin in single ended mode. */

    result  = cyhal_adc_channel_init_diff(&adc_chan_0_obj, &adc_obj, VPLUS_CHANNEL_0,

                                          CYHAL_ADC_VNEG, &channel_config);

    if(result != CY_RSLT_SUCCESS)

    {

        printf("ADC first channel initialization failed. Error: %ld\n", (long unsigned int)result);

        CY_ASSERT(0);

    }

 

    /* Register a callback to handle asynchronous read completion */

     cyhal_adc_register_callback(&adc_obj, &adc_event_handler, result_arr);

 

     /* Subscribe to the async read complete event to process the results */

     cyhal_adc_enable_event(&adc_obj, CYHAL_ADC_ASYNC_READ_COMPLETE, CYHAL_ISR_PRIORITY_DEFAULT, true);

 

     printf("ADC is configured in multichannel configuration.\r\n\n");

     printf("Channel 0 is configured in single ended mode, connected to the \r\n");

     printf("channel 0 input pin. Provide input voltage at the channel 0 input pin \r\n");

     return 0;

}

 

int adc_samp(void)

{

    /* Variable to capture return value of functions */

    cy_rslt_t result;

 

    /* Variable to store ADC conversion result from channel 0 */

    int32_t adc_result_0 = 0;

 

 

        /* Clear async read complete flag */

        async_read_complete = false;

 

        /* Initiate an asynchronous read operation. The event handler will be called

         * when it is complete. */

        memset(result_arr,0,sizeof(result_arr));

        cyhal_gpio_write_internal(CYBSP_USER_LED,true);

        result = cyhal_adc_read_async_uv(&adc_obj, NUM_SCAN, result_arr);

        if(result != CY_RSLT_SUCCESS)

        {

            printf("ADC async read failed. Error: %ld\n", (long unsigned int)result);

            CY_ASSERT(0);

        }

        while(async_read_complete == false);

        cyhal_gpio_write_internal(CYBSP_USER_LED,false);

        /*

         * Read data from result list, input voltage in the result list is in

         * microvolts. Convert it millivolts and print input voltage

         *

         */

        for(int i=0; i<NUM_SCAN; i++)

        {

            adc_result_0 = result_arr / MICRO_TO_MILLI_CONV_RATIO;

            printf("/*%4ld*/\r\n", (long int)adc_result_0);

        }

 

    return 0;

}

 

 

 

Adc.h

#ifndef ADC_H

#define ADC_H

 

int adc_init(void);

int adc_samp(void);

 

#endif

 

 

Main.c调用

adc_init();

 

adc_samp();

 

 

测试

时钟源

时钟源是100Mhz,12分频=8.33M,满足1.8MHz~18MHz之间的要求

默认是按照8M配置

 

 

采样时间

采样前后翻转LED用示波器测量时间

int adc_samp(void)

{

    /* Variable to capture return value of functions */

    cy_rslt_t result;

 

    /* Variable to store ADC conversion result from channel 0 */

    int32_t adc_result_0 = 0;

 

 

        /* Clear async read complete flag */

        async_read_complete = false;

 

        /* Initiate an asynchronous read operation. The event handler will be called

         * when it is complete. */

        memset(result_arr,0,sizeof(result_arr));

        cyhal_gpio_write_internal(CYBSP_USER_LED,true);

        result = cyhal_adc_read_async_uv(&adc_obj, NUM_SCAN, result_arr);

        if(result != CY_RSLT_SUCCESS)

        {

            printf("ADC async read failed. Error: %ld\n", (long unsigned int)result);

            CY_ASSERT(0);

        }

        while(async_read_complete == false);

        cyhal_gpio_write_internal(CYBSP_USER_LED,false);

        /*

         * Read data from result list, input voltage in the result list is in

         * microvolts. Convert it millivolts and print input voltage

         *

         */

        for(int i=0; i<NUM_SCAN; i++)

        {

            adc_result_0 = result_arr / MICRO_TO_MILLI_CONV_RATIO;

            printf("/*%4ld*/\r\n", (long int)adc_result_0);

        }

 

    return 0;

}

 

采样1000次,分别设置采样时间为2uS和1uS对比。

#define ACQUISITION_TIME_NS              (2000u)

10.28mS

 

#define ACQUISITION_TIME_NS              (1000u)

9.32mS

 

 

10.28-9.32=0.96mS 1000次约1mS1次刚好是1uS。

而1000次除去采样时间其他时间为8.32mS,即一次8.32uS。

 

因为前面设置了时钟为8.33MHz, 从前面时序一节可以看到,除去采样时间,其他转换时间等需要14个CLK,所以需要14/8.33uS=1.7uS. 剩余的8.32-1.7为数据搬运,软件处理等时间。

 

采样值正确性

1.545V和示波器采集为1.54V差不多是正确的,这里没有高精度的万用表就不对测试精度了,只测试了正确性。

 

 

音频采集

一次采集1000次然后串口打印,使用SerialStudio可视化显示

int adc_samp(void)

{

    /* Variable to capture return value of functions */

    cy_rslt_t result;

 

    /* Variable to store ADC conversion result from channel 0 */

    int32_t adc_result_0 = 0;

 

 

        /* Clear async read complete flag */

        async_read_complete = false;

 

        /* Initiate an asynchronous read operation. The event handler will be called

         * when it is complete. */

        memset(result_arr,0,sizeof(result_arr));

        cyhal_gpio_write_internal(CYBSP_USER_LED,true);

        result = cyhal_adc_read_async_uv(&adc_obj, NUM_SCAN, result_arr);

        if(result != CY_RSLT_SUCCESS)

        {

            printf("ADC async read failed. Error: %ld\n", (long unsigned int)result);

            CY_ASSERT(0);

        }

        while(async_read_complete == false);

        cyhal_gpio_write_internal(CYBSP_USER_LED,false);

        /*

         * Read data from result list, input voltage in the result list is in

         * microvolts. Convert it millivolts and print input voltage

         *

         */

        for(int i=0; i<NUM_SCAN; i++)

        {

            adc_result_0 = result_arr / MICRO_TO_MILLI_CONV_RATIO;

            printf("/*%4ld*/\r\n", (long int)adc_result_0);

        }

 

    return 0;

}

 

 

总结

以上实现了ADC的测试,包括采样率,正确性,并进行了音频的采集,为后续语音识别做了准备。

 

此帖出自ARM技术论坛

最新回复

这家伙整得6啊   详情 回复 发表于 2023-9-6 10:15
点赞 关注
 

回复
举报

1705

帖子

0

TA的资源

五彩晶圆(初级)

沙发
 

视频中示波器测的那个地方波形

此帖出自ARM技术论坛
 
 
 

回复

6

帖子

0

TA的资源

一粒金砂(初级)

板凳
 

这家伙整得6啊

此帖出自ARM技术论坛
 
 
 

回复
您需要登录后才可以回帖 登录 | 注册

查找数据手册?

EEWorld Datasheet 技术支持

相关文章 更多>>
关闭
站长推荐上一条 1/8 下一条

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

About Us 关于我们 客户服务 联系方式 器件索引 网站地图 最新更新 手机版

站点相关: 国产芯 安防电子 汽车电子 手机便携 工业控制 家用电子 医疗电子 测试测量 网络通信 物联网

北京市海淀区中关村大街18号B座15层1530室 电话:(010)82350740 邮编:100190

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2025 EEWORLD.com.cn, Inc. All rights reserved
快速回复 返回顶部 返回列表