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

描述

一、前言
本项目基于英飞凌PSoC6 RT-Thread开发板实现了信号处理前端-一个信号处理的工具集。包括虚拟示波器,音频采集分析,谐波分析,周期幅值相位分析,数字滤波,极值检测,可上位机可视化和命令行人机交互,可以方便继续扩展相关功能,继续丰富工具集。RT-Thread视频: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.gitCMSIS_5CMSISDSP下是相关文件,Source下是源码RT-Thread将DSP文件夹复制到自己的工程目录中,只保留Include,PrivateInclude,Source三个文件夹RT-ThreadRT-ThreadSource下的每个子文件夹都是一类算法,里面的每个c都对应一个计算函数,并且有一个总文件包括其中所有的单个.c,比如BasicMathFunctions.c中RT-Thread删除这些总的.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 RT-Thread工程设置添加相关头文件包含路径
		 2.2测试复制CMSIS_5CMSISDSPExamplesARMarm_fft_bin_example下的arm_fft_bin_data.carm_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 ");  2    for(int i=0; i 3    {  4        if(i2)  5        {  6            printf("/*%f,%f*/ ", testInput_f32_10khz[i],testOutput[i]);  7        }  8        else  9        { 10            printf("/*%f,%f*/ ", testInput_f32_10khz[i],0.0); 11        } 12    } 使用serialstudio可视化显示,可以看到计算结果FFT频率明显的峰值

		RT-Thread

		
			 三.音频采集
3.1原理图从原理图看到有6路模拟输入,分别对应P10.0~P10.5, VREF为模拟参考电压。RT-ThreadRT-Thread使用的是MAX4466的MIC,接到ADC0,如下图所示RT-ThreadRT-ThreadRT-Thread  3.2配置模拟采集引脚 RT-Thread  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 ", (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 ", (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. ");  80     printf("Channel 0 is configured in single ended mode, connected to the  ");  81     printf("channel 0 input pin. Provide input voltage at the channel 0 input pin  ");  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 ", (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*/ ", (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配置

		RT-Thread

		RT-Thread
			 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 ", (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*/ ", (long int)adc_result_0); 30        } 31    return 0; 32}

		采样1000次,分别设置采样时间为2uS和1uS对比。#define ACQUISITION_TIME_NS (2000u)10.28mS

		RT-Thread#define ACQUISITION_TIME_NS (1000u)9.32mS

		RT-Thread10.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差不多是正确的,这里没有高精度的万用表就不对测试精度了,只测试了正确性。RT-Thread

		RT-Thread

		
			 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 ", (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*/ ", (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*/ ", adcbuffer[i],out); 42  } 43} 44 /** endlink */Fft.h

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

		测试

		RT-Thread

		
			 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.cinclude "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 ",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开始测试印如下RT-Thread实时采集测试此时采集的是音频背景声,噪声很小,所以频率为0

		RT-Thread

		
			 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个状态变量。RT-Thready[n] = b0 x[n] + b1 x[n-1] + b2 x[n-2] - a1 y[n-1] - a2 * y[n-2]matlab使用上面的公式实现,在使用fdatool工具箱生成的a系数需要取反才能用于直接I型IIR滤波器的函数中。高阶IIR滤波器的实现是采用二阶Biquad级联的方式来实现的。其中参数numStages就是用来做指定二阶Biquad的个数。比如8阶IIR滤波器就可以采用numStages=4个二阶Biquad来实现。RT-Thread如果要实现9阶IIR滤波器就需要将numStages=5,这时就需要其中一个Biquad配置成一阶滤波器(也就是b2=0,a2=0)。
			 4.3.2添加命令行shell_fun.hvoid 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*/ ", 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回车,查看波形见视频以下可以看到滤波导致了滞后,黄色线有滞后

		RT-Thread

		RT-Thread以下是实时采集滤波RT-Thread4.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; k2+1; k++)  5    {  6        row_sum = 0;  7        for(int i=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; i21        { 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; k29    { 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*/ ",sim_data_buffer[k],sim_data_buffer[k]); 15            } 16            else 17            { 18                printf("/*%ld,%d*/ ",sim_data_buffer[k],0); 19            } 20            cyhal_system_delay_ms(10); 21        } 22    } 23    return 0; 24}

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

		RT-ThreadRT-Thread检测语音,效果如下RT-ThreadRT-ThreadRT-Thread
		 五.总结
得益于开发板出色的处理性能,和外设性能,以及官方可视化的代码配置工具,可以方便的搭建开发环境,实现外设采集信号比如ADC,移植DSP库,实现各种算法。本Demo实现了谐波分析,周期幅值相位分析,数字滤波,极大值检测等功能,是一个小的工具集,还可以继续扩展,设计了人机交互命令行,方便实用和测试,具备一定实用价值。
原文: https://club.rt-thread.org/ask/article/889e7c861bc93340.html
 ———————End——————    
 点击阅读原文进入官网


原文标题:基于 Infineon PSoC™62开发板的信号处理前端虚拟示波器-工具集

文章出处:【微信公众号:RTThread物联网操作系统】欢迎添加关注!文章转载请注明出处。


打开APP阅读更多精彩内容
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉

全部0条评论

快来发表一下你的评论吧 !

×
20
完善资料,
赚取积分