基于infineonPSOC62开发板的-信号处理前端虚拟示波器-工具集

一、前言


本项目基于英飞凌PSoC 6 RTT开发板实现了信号处理前端-一个信号处理的工具集。

包括虚拟示波器,音频采集分析,谐波分析,周期幅值相位分析,数字滤波,极值检测,可上位机可视化和命令行人机交互,可以方便继续扩展相关功能,继续丰富工具集。

视频: https://www.bilibili.com/video/BV1PM4y147v1/

代码仓库: https://gitee.com/qinyunti/infineon-psoc62.git


二、移植DSP算法库


2.1添加代码

git clone https://github.com/ARM-software/CMSIS_5.git

CMSIS_5\CMSIS\DSP下是相关文件,Source下是源码

将DSP文件夹复制到自己的工程目录中,只保留

Include,PrivateInclude,Source三个文件夹

Source下的每个子文件夹都是一类算法,里面的每个c都对应一个计算函数,并且有一个总文件包括其中所有的单个.c,比如BasicMathFunctions.c中

删除这些总的.c,避免编译重复

删除以下文件和所有的非.c和.h文件

1BasicMathFunctions:BasicMathFunctions.c,BasicMathFunctionsF16.c
2BayesFunctions:BayesFunctions.c,BayesFunctionsF16.c
3CommonTables:CommonTables.c,CommonTablesF16.c
4ComplexMathFunctions:ComplexMathFunctions.c,ComplexMathFunctionsF16.c
5ControllerFunctions:ControllerFunctions.c
6DistanceFunctions:DistanceFunctions.c,DistanceFunctionsF16.c
7FastMathFunctions:FastMathFunctions.c,FastMathFunctionsF16.c
8FilteringFunctions:FilteringFunctions.c,FilteringFunctionsF16.c
9InterpolationFunctions:InterpolationFunctions.c,InterpolationFunctionsF16.c
10MatrixFunctions:MatrixFunctions.c,MatrixFunctionsF16.c
11QuaternionMathFunctions:QuaternionMathFunctions.c
12StatisticsFunctions:StatisticsFunctions.c,StatisticsFunctionsF16.c
13SupportFunctions:SupportFunctions.c,SupportFunctionsF16.c
14SVMFunctions:SVMFunctions.c,SVMFunctionsF16.c
15TransformFunctions:TransformFunctions.c,TransformFunctionsF16.c,arm_bitreversal2.S


工程设置添加相关头文件包含路径

2.2测试

复制CMSIS_5\CMSIS\DSP\Examples\ARM\arm_fft_bin_example下的arm_fft_bin_data.c和arm_fft_bin_example_f32.c到自己的工程目录

arm_fft_bin_example_f32.c下的

int32_t main(void)改为int32_t ffttest_main(void)

并添加#define SEMIHOSTING以使能printf打印,我们已经重定向实现了printf打印到串口。

由于 arm_cfft_f32(&varInstCfftF32, testInput_f32_10khz, ifftFlag, doBitReverse);会修改testInput_f32_10khz的内容,所以添加一个缓存,以便能重复测试

1float32_t testtmp_f32_10khz[2048];
2  /* Process the data through the CFFT/CIFFT module */
3  memcpy(testtmp_f32_10khz,testInput_f32_10khz,sizeof(testInput_f32_10khz));
4  arm_cfft_f32(&varInstCfftF32, testtmp_f32_10khz, ifftFlag, doBitReverse);
5  /* Process the data through the Complex Magnitude Module for
6  calculating the magnitude at each bin */

7  arm_cmplx_mag_f32(testtmp_f32_10khz, testOutput, fftSize);

在自己的main函数中申明并调用

int32_t ffttest_main(void)

ffttest_main()

编译运行可以看到串口打印SUCCESS说明测试OK。

将输入输出数据打印

1 printf("SUCCESS\n");
2    for(int i=0; i 3    {
4        if(i2
)
5        {
6            printf("/*%f,%f*/\r\n", testInput_f32_10khz[i],testOutput[i]);
7        }
8        else
9        {
10            printf("/*%f,%f*/\r\n", testInput_f32_10khz[i],0.0);
11        }
12    }

使用serialstudio可视化显示,可以看到计算结果FFT频率明显的峰值


三、音频采集


3.1原理图

从原理图看到有6路模拟输入,分别对应

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

使用的是MAX4466的MIC,接到ADC0,如下图所示

3.2配置模拟采集引脚

3.3代码

Adc.c

1#include "cy_pdl.h"
2#include "cyhal.h"
3#include "cybsp.h"
4#include "cy_retarget_io.h"
5#define VPLUS_CHANNEL_0  (P10_0)
6/* Conversion factor */
7#define MICRO_TO_MILLI_CONV_RATIO        (1000u)
8/* Acquistion time in nanosecond */
9#define ACQUISITION_TIME_NS              (116680u)
10/* ADC Scan delay in millisecond */
11#define ADC_SCAN_DELAY_MS                (200u)
12/*******************************************************************************
13*       Enumerated Types
14*******************************************************************************/

15/* ADC Channel constants*/
16enum ADC_CHANNELS
17{
18  CHANNEL_0 = 0,
19  NUM_CHANNELS
20} adc_channel;
21/*******************************************************************************
22* Global Variables
23*******************************************************************************/

24/* ADC Object */
25cyhal_adc_t adc_obj;
26/* ADC Channel 0 Object */
27cyhal_adc_channel_t adc_chan_0_obj;
28/* Default ADC configuration */
29const cyhal_adc_config_t adc_config = {
30        .continuous_scanning=false// Continuous Scanning is disabled
31        .average_count=1,           // Average count disabled
32        .vref=CYHAL_ADC_REF_VDDA,   // VREF for Single ended channel set to VDDA
33        .vneg=CYHAL_ADC_VNEG_VSSA,  // VNEG for Single ended channel set to VSSA
34        .resolution = 12u,          // 12-bit resolution
35        .ext_vref = NC,             // No connection
36        .bypass_pin = NC };       // No connection
37/* Asynchronous read complete flag, used in Event Handler */
38static bool async_read_complete = true;
39#define NUM_SCAN                    (1000)
40#define NUM_CHANNELS                (1)
41/* Variable to store results from multiple channels during asynchronous read*/
42int32_t result_arr[NUM_CHANNELS * NUM_SCAN] = {0};
43static void adc_event_handler(void* arg, cyhal_adc_event_t event)
44
{
45    if(0u != (event & CYHAL_ADC_ASYNC_READ_COMPLETE))
46    {
47        /* Set async read complete flag to true */
48        async_read_complete = true;
49    }
50}
51int adc_init(void)
52
{
53    /* Variable to capture return value of functions */
54    cy_rslt_t result;
55    /* Initialize ADC. The ADC block which can connect to the channel 0 input pin is selected */
56    result = cyhal_adc_init(&adc_obj, VPLUS_CHANNEL_0, NULL);
57    if(result != CY_RSLT_SUCCESS)
58    {
59        printf("ADC initialization failed. Error: %ld\n", (long unsigned int)result);
60        CY_ASSERT(0);
61    }
62    /* ADC channel configuration */
63    const cyhal_adc_channel_config_t channel_config = {
64            .enable_averaging = false,  // Disable averaging for channel
65            .min_acquisition_ns = ACQUISITION_TIME_NS, // Minimum acquisition time set to 1us
66            .enabled = true };          // Sample this channel when ADC performs a scan
67    /* Initialize a channel 0 and configure it to scan the channel 0 input pin in single ended mode. */
68    result  = cyhal_adc_channel_init_diff(&adc_chan_0_obj, &adc_obj, VPLUS_CHANNEL_0,
69                                          CYHAL_ADC_VNEG, &channel_config);
70    if(result != CY_RSLT_SUCCESS)
71    {
72        printf("ADC first channel initialization failed. Error: %ld\n", (long unsigned int)result);
73        CY_ASSERT(0);
74    }
75    /* Register a callback to handle asynchronous read completion */
76     cyhal_adc_register_callback(&adc_obj, &adc_event_handler, result_arr);
77     /* Subscribe to the async read complete event to process the results */
78     cyhal_adc_enable_event(&adc_obj, CYHAL_ADC_ASYNC_READ_COMPLETE, CYHAL_ISR_PRIORITY_DEFAULT, true);
79     printf("ADC is configured in multichannel configuration.\r\n\n");
80     printf("Channel 0 is configured in single ended mode, connected to the \r\n");
81     printf("channel 0 input pin. Provide input voltage at the channel 0 input pin \r\n");
82     return 0;
83}
84int adc_samp(void)
85
{
86    /* Variable to capture return value of functions */
87    cy_rslt_t result;
88    /* Variable to store ADC conversion result from channel 0 */
89    int32_t adc_result_0 = 0;
90        /* Clear async read complete flag */
91        async_read_complete = false;
92        /* Initiate an asynchronous read operation. The event handler will be called
93         * when it is complete. */

94        memset(result_arr,0,sizeof(result_arr));
95        cyhal_gpio_write_internal(CYBSP_USER_LED,true);
96        result = cyhal_adc_read_async_uv(&adc_obj, NUM_SCAN, result_arr);
97        if(result != CY_RSLT_SUCCESS)
98        {
99            printf("ADC async read failed. Error: %ld\n", (long unsigned int)result);
100            CY_ASSERT(0);
101        }
102        while(async_read_complete == false);
103        cyhal_gpio_write_internal(CYBSP_USER_LED,false);
104        /*
105         * Read data from result list, input voltage in the result list is in
106         * microvolts. Convert it millivolts and print input voltage
107         *
108         */

109        for(int i=0; i110        {
111            adc_result_0 = result_arr[i] / MICRO_TO_MILLI_CONV_RATIO;
112            printf("/*%4ld*/\r\n", (long int)adc_result_0);
113        }
114    return 0;
115}

Adc.h

1#ifndef ADC_H
2#define ADC_H
3int adc_init(void);
4int adc_samp(void);
5#endif

Main.c调用

adc_init();

adc_samp();

3.4时钟源

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

默认是按照8M配置

3.5采样时间

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

1int adc_samp(void)
2
{
3    /* Variable to capture return value of functions */
4    cy_rslt_t result;
5    /* Variable to store ADC conversion result from channel 0 */
6    int32_t adc_result_0 = 0;
7        /* Clear async read complete flag */
8        async_read_complete = false;
9        /* Initiate an asynchronous read operation. The event handler will be called
10         * when it is complete. */

11        memset(result_arr,0,sizeof(result_arr));
12        cyhal_gpio_write_internal(CYBSP_USER_LED,true);
13        result = cyhal_adc_read_async_uv(&adc_obj, NUM_SCAN, result_arr);
14        if(result != CY_RSLT_SUCCESS)
15        {
16            printf("ADC async read failed. Error: %ld\n", (long unsigned int)result);
17            CY_ASSERT(0);
18        }
19        while(async_read_complete == false);
20        cyhal_gpio_write_internal(CYBSP_USER_LED,false);
21        /*
22         * Read data from result list, input voltage in the result list is in
23         * microvolts. Convert it millivolts and print input voltage
24         *
25         */

26        for(int i=0; i27        {
28            adc_result_0 = result_arr[i] / MICRO_TO_MILLI_CONV_RATIO;
29            printf("/*%4ld*/\r\n", (long int)adc_result_0);
30        }
31    return 0;
32}

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

#define ACQUISITION_TIME_NS (2000u)

10.28mS

#define ACQUISITION_TIME_NS (1000u)

9.32mS

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

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

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

3.6 采样值正确性

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

3.7音频采集

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

1int adc_samp(void)
2
{
3    /* Variable to capture return value of functions */
4    cy_rslt_t result;
5    /* Variable to store ADC conversion result from channel 0 */
6    int32_t adc_result_0 = 0;
7        /* Clear async read complete flag */
8        async_read_complete = false;
9        /* Initiate an asynchronous read operation. The event handler will be called
10         * when it is complete. */

11        memset(result_arr,0,sizeof(result_arr));
12        cyhal_gpio_write_internal(CYBSP_USER_LED,true);
13        result = cyhal_adc_read_async_uv(&adc_obj, NUM_SCAN, result_arr);
14        if(result != CY_RSLT_SUCCESS)
15        {
16            printf("ADC async read failed. Error: %ld\n", (long unsigned int)result);
17            CY_ASSERT(0);
18        }
19        while(async_read_complete == false);
20        cyhal_gpio_write_internal(CYBSP_USER_LED,false);
21        /*
22         * Read data from result list, input voltage in the result list is in
23         * microvolts. Convert it millivolts and print input voltage
24         *
25         */

26        for(int i=0; i27        {
28            adc_result_0 = result_arr[i] / MICRO_TO_MILLI_CONV_RATIO;
29            printf("/*%4ld*/\r\n", (long int)adc_result_0);
30        }
31    return 0;
32}


四、信号处理前端


4.1 电能质量,谐波分析

4.1.1添加命令行

在电能检测应用中,电能质量一项分析即谐波分析,谐波分量大,说明电能质量不好,

基于本板信号处理前端也实现了该功能。

shell_fun.h

1void FftFun(void* param);

shell_fun.c

1include "fft.h"

shell_cmd_list中添加一行

1 { (const uint8_t*)"fft",         FftFun,           "fft"},                 /*打印帮助信息*/

添加命令执行函数

1void FftFun(void* param)
2
{
3    fft_main();
4}


4.1.2添加实现

Fft.c

1#include "arm_math.h"
2#include "arm_const_structs.h"
3#include 
4#define TEST_LENGTH_SAMPLES 2048
5extern float32_t testInput_f32_10khz[TEST_LENGTH_SAMPLES];
6static float32_t testOutput[TEST_LENGTH_SAMPLES/2];
7static uint32_t fftSize = 1024;
8static uint32_t ifftFlag = 0;
9static uint32_t doBitReverse = 1;
10static arm_cfft_instance_f32 varInstCfftF32;
11static int testIndex = 0;
12static float testtmp_f32_10khz[2048];
13static int32_t adcbuffer[2048];
14int32_t fft_main(void)
15{
16  arm_status status;
17  float32_t maxValue;
18  status = ARM_MATH_SUCCESS;
19  status=arm_cfft_init_f32(&varInstCfftF32,fftSize);
20  //memcpy(testtmp_f32_10khz,testInput_f32_10khz,sizeof(testInput_f32_10khz));
21  adc_samp(adcbuffer,2048);
22  for(int i=0; i<2048;i ++)
23  {
24      testtmp_f32_10khz[i] = (float)adcbuffer[i];
25  }
26  arm_cfft_f32(&varInstCfftF32, testtmp_f32_10khz, ifftFlag, doBitReverse);
27  arm_cmplx_mag_f32(testtmp_f32_10khz, testOutput, fftSize);
28  /* Calculates maxValue and returns corresponding BIN value */
29  arm_max_f32(testOutput, fftSize, &maxValue, &testIndex);
30  int32_t out = 0;
31  for(int i=0; i32  {
33      if(i>TEST_LENGTH_SAMPLES/2)
34      {
35          out = testOutput[i-TEST_LENGTH_SAMPLES/2]/1024;
36      }
37      else
38      {
39          out = testOutput[i]/1024;
40      }
41      printf("/*%ld,%ld*/\r\n", adcbuffer[i],out);
42  }
43}
44 /** \endlink */

Fft.h

1#ifndef FFT_H
2#define FFT_H
3int fft_main(void);
4#endif

测试

4.2 周期(频率),幅值,相位分析

4.2.1 原理

FFT变换结果,幅值最大的横坐标对应信号频率,纵坐标对应幅度。幅值最大的为out[m]=val;则信号频率f0=(Fs/N)m ,信号幅值Vpp=val/(N/2)。N为FFT的点数,Fs为采样频率。相位Pha=atan2(a, b)弧度制,其中ab是输出虚数结果的实部和虚部。

4.2.2添加命令行

shell_fun.h

1void FrqFun(void* param);

shell_fun.c

include "frq.h"

shell_cmd_list中添加一行

1{ (const uint8_t*)"frt",         FrqFun,           "frq"},

添加命令执行函数

1void FrqFun(void* param)
2
{
3    Frq_main();
4}

4.2.3实现代码

Frq.c

1#include "arm_math.h"
2#include "arm_const_structs.h"
3#include 
4#define TEST_LENGTH_SAMPLES 2048
5#define FS 10000
6extern float32_t testInput_f32_10khz[TEST_LENGTH_SAMPLES];
7static float32_t testOutput[TEST_LENGTH_SAMPLES/2];
8static uint32_t fftSize = 1024;
9static uint32_t ifftFlag = 0;
10static uint32_t doBitReverse = 1;
11static arm_cfft_instance_f32 varInstCfftF32;
12static int testIndex = 0;
13static float testtmp_f32_10khz[2048];
14static int32_t adcbuffer[2048];
15int32_t frq_main(void)
16{
17  arm_status status;
18  float32_t maxValue;
19  status = ARM_MATH_SUCCESS;
20  status=arm_cfft_init_f32(&varInstCfftF32,fftSize);
21  //memcpy(testtmp_f32_10khz,testInput_f32_10khz,sizeof(testInput_f32_10khz));
22  adc_samp(adcbuffer,2048);
23  for(int i=0; i<2048;i ++)
24 {
25      testtmp_f32_10khz[i] = (float)adcbuffer[i];
26  }
27  arm_cfft_f32(&varInstCfftF32, testtmp_f32_10khz, ifftFlag, doBitReverse);
28  arm_cmplx_mag_f32(testtmp_f32_10khz, testOutput, fftSize);
29  /* Calculates maxValue and returns corresponding BIN value */
30  arm_max_f32(testOutput, fftSize, &maxValue, &testIndex);
31  float freq = (FS/TEST_LENGTH_SAMPLES)*testIndex;
32  float vpp = maxValue/(TEST_LENGTH_SAMPLES/2);
33  float pha = atan2(testOutput[2*testIndex],testOutput[2*testIndex+1]);
34  printf("freq=%f,vpp=%f,pha=%f\r\n",freq,vpp,pha);
35}
36 /** \endlink */

Frq.h

1#ifndef FRQ_H
2#define FRQ_H
3int frq_main(void);
4#endif

4.2.4测试

输入frq开始测试印如下

实时采集测试

此时采集的是音频背景声,噪声很小,所以频率为0

4.3数字滤波信号前端

4.3.1原理

CMSIS-DSP提供直接I型IIR库支持Q7,Q15,Q31和浮点四种数据类型。其中Q15和Q31提供了快速版本。

直接I型IIR滤波器是基于二阶Biquad级联的方式来实现的。每个Biquad由一个二阶的滤波器组成:

y[n] = b0 x[n] + b1 x[n-1] + b2 x[n-2] + a1 y[n-1] + a2 * y[n-2]

直接I型算法每个阶段需要5个系数和4个状态变量。

matlab使用上面的公式实现,在使用fdatool工具箱生成的a系数需要取反才能用于直接I型IIR滤波器的函数中。

高阶IIR滤波器的实现是采用二阶Biquad级联的方式来实现的。其中参数numStages就是用来做指定二阶Biquad的个数。比如8阶IIR滤波器就可以采用numStages=4个二阶Biquad来实现。

如果要实现9阶IIR滤波器就需要将numStages=5,这时就需要其中一个Biquad配置成一阶滤波器(也就是b2=0,a2=0)。

4.3.2添加命令行

shell_fun.h

void IirFun(void* param);

shell_fun.c

1include "iir.h"

shell_cmd_list中添加一行

1  { (const uint8_t*)"iir",         IirFun,           “iir"},

添加命令执行函数

1void IirFun(void* param)
2
{
3    Iir_main();
4}

4.3.3实现代码

Iir.c

1#include "arm_math.h"
2#include "arm_const_structs.h"
3#include 
4#define TEST_LENGTH_SAMPLES 2048
5#define FS 10000
6extern float32_t testInput_f32_10khz[TEST_LENGTH_SAMPLES];
7static float32_t testOutput[TEST_LENGTH_SAMPLES];
8static uint32_t fftSize = 1024;
9static uint32_t ifftFlag = 0;
10static uint32_t doBitReverse = 1;
11static arm_cfft_instance_f32 varInstCfftF32;
12static int testIndex = 0;
13static float testtmp_f32_10khz[2048];
14static int32_t adcbuffer[2048];
15#define numStages  2                /* 2阶IIR滤波的个数 */
16#define BLOCK_SIZE           128    /* 调用一次arm_biquad_cascade_df1_f32处理的采样点个数 */
17uint32_t blockSize = BLOCK_SIZE;
18uint32_t numBlocks = TEST_LENGTH_SAMPLES/BLOCK_SIZE;      /* 需要调用arm_biquad_cascade_df1_f32的次数 */
19static float32_t IIRStateF32[4*numStages];                      /* 状态缓存 */
20/* 巴特沃斯低通滤波器系数 80Hz*/
21const float32_t IIRCoeffs32LP[5*numStages] = {
22    1.0f,  2.0f,  1.0f,  1.479798894397216679763573665695730596781f,
23-0.688676953053861784503908438637154176831f,
24    1.0f,  2.0f,  1.0f,  1.212812092620218384908525877108331769705f,
25-0.384004162286553540894828984164632856846f
26};
27int32_t iir_main(void)
28{
29    uint32_t i;
30    arm_biquad_casd_df1_inst_f32 S;
31    float32_t ScaleValue;
32    float32_t  *inputF32, *outputF32;
33    /* 初始化输入输出缓存指针 */
34    //memcpy(testtmp_f32_10khz,testInput_f32_10khz,sizeof(testInput_f32_10khz));
35#if 1
36    adc_samp(adcbuffer,2048);
37    for(int i=0; i<2048;i ++)
38   {
39        testtmp_f32_10khz[i] = (float)adcbuffer[i];
40    }
41#endif
42    inputF32 = testtmp_f32_10khz;
43    outputF32 = testOutput;
44    /* 初始化 */
45    arm_biquad_cascade_df1_init_f32(&S, numStages, (float32_t *)&IIRCoeffs32LP[0],
46(float32_t *)&IIRStateF32[0]);
47    /* 实现IIR滤波,这里每次处理1个点 */
48    for(i=0; i < numBlocks; i++)
49    {
50        arm_biquad_cascade_df1_f32(&S, inputF32 + (i * blockSize),  outputF32 + (i * blockSize),
51  blockSize);
52    }
53    /*放缩系数 */
54    ScaleValue = 0.012f0.42f;
55    /* 打印滤波后结果 */
56    for(i=0; i57    {
58        printf("/*%f, %f*/\r\n", testtmp_f32_10khz[i], testOutput[i]*ScaleValue);
59    }
60}
61 /** \endlink */

Iir.h

1#ifndef IIR_H
2#define IIR_H
3int iir_main(void);
4#endif

4.3.4测试

输入iir回车,查看波形

见视频

以下可以看到滤波导致了滞后,黄色线有滞后

以下是实时采集滤波

4.4 极大值检测

在电力等行业,分析电压极值,是一项重要的参数分析,可以分析电压的波动;示波器中也有自动测量极值的功能更。本板作为信号处理前端也实现了该功能。

4.4.1 算法

算法来源于论文 https://www.mdpi.com/1999-4893/5/4/588/htm

核心代码如下

1void ampd(int32_t* data, int32_t len)
2{
3    int row_sum;
4    for(int k=1; k<len/2+1; k++)
5    {
6        row_sum = 0;
7        for(int i=k; i<len-k; i++)
8        {
9            if((data[i] > data[i - k]) && (data[i] > data[i + k]))
10            {
11                row_sum -= 1;
12            }
13        }
14        arr_rowsum[k-1] = row_sum;
15    }
16    int min_index = argmin(arr_rowsum,len/2+1);
17     max_window_length = min_index;
18    for(int k=1; k1
; k++)
19    {
20        for(int i=k; i<len - k; i++)
21        {
22            if((data[i] > data[i - k]) && (data[i] > data[i + k]))
23            {
24                p_data[i] += 1;
25            }
26        }
27    }
28    for(int k=0; k<len; k++)
29    {
30        if(p_data[k] == max_window_length)
31        {
32            /* 极大值 */
33        }
34    }
35}

4.4.2 添加命令行

1  { (const uint8_t*)"max",         MaxFun,           "max"},                 /*打印帮助信息*/
2void MaxFun(void* param)
3
{
4    max_test();
5}
6void MaxFun(void* param);

测试代码如下,串口命令行输入命令max,开始采集ADC值,并计算极值,打印到PC串口通过seraistudio可视化显示

1int max_test(void)
2
{
3    for(int i=0; i<10; i++)
4    {
5        memset(p_data,0,sizeof(p_data));
6        //adc_samp(sim_data_buffer,1000);
7        sim_data();
8        ampd(sim_data_buffer, sizeof(sim_data_buffer)/sizeof(sim_data_buffer[0]));
9        for(int k=0; k<sizeof(sim_data_buffer)/sizeof(sim_data_buffer[0]); k++)
10        {
11            if(p_data[k] == max_window_length)
12            {
13                /* 极大值 */
14                printf("/*%ld,%ld*/\r\n",sim_data_buffer[k],sim_data_buffer[k]);
15            }
16            else
17            {
18                printf("/*%ld,%d*/\r\n",sim_data_buffer[k],0);
19            }
20            cyhal_system_delay_ms(10);
21        }
22    }
23    return 0;
24}

4.4.3 测试

效果如下IN是原始数据,MAX是检测到的极大值,如果检测极小值将原始数据取反即可。

检测语音,效果如下


五、总结


得益于开发板出色的处理性能,和外设性能,以及官方可视化的代码配置工具,可以方便的搭建开发环境,实现外设采集信号比如ADC,移植DSP库,实现各种算法。本Demo实现了谐波分析,周期幅值相位分析,数字滤波,极大值检测等功能,是一个小的工具集,还可以继续扩展,设计了人机交互命令行,方便实用和测试,具备一定实用价值。


———————End——————




👇 点击阅读原文进入官网

RTThread物联网操作系统 帮助您了解RT-Thread相关的资讯.
评论
  • 艾迈斯欧司朗全新“样片申请”小程序,逾160种LED、传感器、多芯片组合等产品样片一触即达。轻松3步完成申请,境内免费包邮到家!本期热荐性能显著提升的OSLON® Optimal,GF CSSRML.24ams OSRAM 基于最新芯片技术推出全新LED产品OSLON® Optimal系列,实现了显著的性能升级。该系列提供五种不同颜色的光源选项,包括Hyper Red(660 nm,PDN)、Red(640 nm)、Deep Blue(450 nm,PDN)、Far Red(730 nm)及Ho
    艾迈斯欧司朗 2024-11-29 16:55 163浏览
  • 在电子技术快速发展的今天,KLV15002光耦固态继电器以高性能和强可靠性完美解决行业需求。该光继电器旨在提供无与伦比的电气隔离和无缝切换,是现代系统的终极选择。无论是在电信、工业自动化还是测试环境中,KLV15002光耦合器固态继电器都完美融合了效率和耐用性,可满足当今苛刻的应用需求。为什么选择KLV15002光耦合器固态继电器?不妥协的电压隔离从本质上讲,KLV15002优先考虑安全性。输入到输出隔离达到3750Vrms(后缀为V的型号为5000Vrms),确保即使在高压情况下,敏感的低功耗
    克里雅半导体科技 2024-11-29 16:15 119浏览
  • RDDI-DAP错误通常与调试接口相关,特别是在使用CMSIS-DAP协议进行嵌入式系统开发时。以下是一些可能的原因和解决方法: 1. 硬件连接问题:     检查调试器(如ST-Link)与目标板之间的连接是否牢固。     确保所有必要的引脚都已正确连接,没有松动或短路。 2. 电源问题:     确保目标板和调试器都有足够的电源供应。     检查电源电压是否符合目标板的规格要求。 3. 固件问题: &n
    丙丁先生 2024-12-01 17:37 59浏览
  • 戴上XR眼镜去“追龙”是种什么体验?2024年11月30日,由上海自然博物馆(上海科技馆分馆)与三湘印象联合出品、三湘印象旗下观印象艺术发展有限公司(下简称“观印象”)承制的《又见恐龙》XR嘉年华在上海自然博物馆重磅开幕。该体验项目将于12月1日正式对公众开放,持续至2025年3月30日。双向奔赴,恐龙IP撞上元宇宙不久前,上海市经济和信息化委员会等部门联合印发了《上海市超高清视听产业发展行动方案》,特别提到“支持博物馆、主题乐园等场所推动超高清视听技术应用,丰富线下文旅消费体验”。作为上海自然
    电子与消费 2024-11-30 22:03 76浏览
  • 《高速PCB设计经验规则应用实践》+PCB绘制学习与验证读书首先看目录,我感兴趣的是这一节;作者在书中列举了一条经典规则,然后进行详细分析,通过公式推导图表列举说明了传统的这一规则是受到电容加工特点影响的,在使用了MLCC陶瓷电容后这一条规则已经不再实用了。图书还列举了高速PCB设计需要的专业工具和仿真软件,当然由于篇幅所限,只是介绍了一点点设计步骤;我最感兴趣的部分还是元件布局的经验规则,在这里列举如下:在这里,演示一下,我根据书本知识进行电机驱动的布局:这也算知行合一吧。对于布局书中有一句:
    wuyu2009 2024-11-30 20:30 91浏览
  • 光伏逆变器是一种高效的能量转换设备,它能够将光伏太阳能板(PV)产生的不稳定的直流电压转换成与市电频率同步的交流电。这种转换后的电能不仅可以回馈至商用输电网络,还能供独立电网系统使用。光伏逆变器在商业光伏储能电站和家庭独立储能系统等应用领域中得到了广泛的应用。光耦合器,以其高速信号传输、出色的共模抑制比以及单向信号传输和光电隔离的特性,在光伏逆变器中扮演着至关重要的角色。它确保了系统的安全隔离、干扰的有效隔离以及通信信号的精准传输。光耦合器的使用不仅提高了系统的稳定性和安全性,而且由于其低功耗的
    晶台光耦 2024-12-02 10:40 70浏览
  • 最近几年,新能源汽车愈发受到消费者的青睐,其销量也是一路走高。据中汽协公布的数据显示,2024年10月,新能源汽车产销分别完成146.3万辆和143万辆,同比分别增长48%和49.6%。而结合各家新能源车企所公布的销量数据来看,比亚迪再度夺得了销冠宝座,其10月新能源汽车销量达到了502657辆,同比增长66.53%。众所周知,比亚迪是新能源汽车领域的重要参与者,其一举一动向来为外界所关注。日前,比亚迪汽车旗下品牌方程豹汽车推出了新车方程豹豹8,该款车型一上市就迅速吸引了消费者的目光,成为SUV
    刘旷 2024-12-02 09:32 69浏览
  • By Toradex胡珊逢简介嵌入式领域的部分应用对安全、可靠、实时性有切实的需求,在诸多实现该需求的方案中,QNX 是经行业验证的选择。在 QNX SDP 8.0 上 BlackBerry 推出了 QNX Everywhere 项目,个人用户可以出于非商业目的免费使用 QNX 操作系统。得益于 Toradex 和 QNX 的良好合作伙伴关系,用户能够在 Apalis iMX8QM 和 Verdin iMX8MP 模块上轻松测试和评估 QNX 8 系统。下面将基于 Apalis iMX8QM 介
    hai.qin_651820742 2024-11-29 15:29 151浏览
  • 学习学习笔记&记录学习学习笔记&记录学习学习笔记&记录学习学习笔记&记录学习学习笔记&记录学习笔记&记录学习习笔记&记学习学习笔记&记录学习学习笔记&记录学习习笔记&记录学习学习笔记&记录学习学习笔记记录学习学习笔记&记录学习学习笔记&记录学习学习笔记&记录学习学习笔记&记录学习学习笔记&记录学习习笔记&记录学习学习笔记&记录学习学习笔记&记录学习学习笔记&记录学习学习笔记&记录学习学习笔记&记录学习学习笔记&记录学习学习笔记&学习学习笔记&记录学习学习笔记&记录学习学习笔记&记录学习学习笔记&
    youyeye 2024-11-30 14:30 65浏览
  • 光耦合器作为关键技术组件,在确保安全性、可靠性和效率方面发挥着不可或缺的作用。无论是混合动力和电动汽车(HEV),还是军事和航空航天系统,它们都以卓越的性能支持高要求的应用环境,成为现代复杂系统中的隐形功臣。在迈向更环保技术和先进系统的过程中,光耦合器的重要性愈加凸显。1.混合动力和电动汽车中的光耦合器电池管理:保护动力源在电动汽车中,电池管理系统(BMS)是最佳充电、放电和性能监控背后的大脑。光耦合器在这里充当守门人,将高压电池组与敏感的低压电路隔离开来。这不仅可以防止潜在的损坏,还可以提高乘
    腾恩科技-彭工 2024-11-29 16:12 119浏览
  • 国产光耦合器因其在电子系统中的重要作用而受到认可,可提供可靠的电气隔离并保护敏感电路免受高压干扰。然而,随着行业向5G和高频数据传输等高速应用迈进,对其性能和寿命的担忧已成为焦点。本文深入探讨了国产光耦合器在高频环境中面临的挑战,并探索了克服这些限制的创新方法。高频性能:一个持续关注的问题信号传输中的挑战国产光耦合器传统上利用LED和光电晶体管进行信号隔离。虽然这些组件对于标准应用有效,但在高频下面临挑战。随着工作频率的增加,信号延迟和数据保真度降低很常见,限制了它们在电信和高速计算等领域的有效
    腾恩科技-彭工 2024-11-29 16:11 106浏览
  • 国产光耦合器正以其创新性和多样性引领行业发展。凭借强大的研发能力,国内制造商推出了适应汽车、电信等领域独特需求的专业化光耦合器,为各行业的技术进步提供了重要支持。本文将重点探讨国产光耦合器的技术创新与产品多样性,以及它们在推动产业升级中的重要作用。国产光耦合器创新的作用满足现代需求的创新模式新设计正在满足不断变化的市场需求。例如,高速光耦合器满足了电信和数据处理系统中快速信号传输的需求。同时,栅极驱动光耦合器支持电动汽车(EV)和工业电机驱动器等大功率应用中的精确高效控制。先进材料和设计将碳化硅
    克里雅半导体科技 2024-11-29 16:18 163浏览
我要评论
0
点击右上角,分享到朋友圈 我知道啦
请使用浏览器分享功能 我知道啦