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_5CMSISDSPExamplesARMarm_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 "); 2 for(int i=0; i
三.音频采集
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; i
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 ", (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; i
采样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 ", (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; i
四.信号处理前端
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
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
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个状态变量。y[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来实现。如果要实现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
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
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是检测到的极大值,如果检测极小值将原始数据取反即可。
检测语音,效果如下 五.总结
原文: https://club.rt-thread.org/ask/article/889e7c861bc93340.html———————End———————
原文标题:基于 Infineon PSoC™62开发板的信号处理前端虚拟示波器-工具集
文章出处:【微信公众号:RTThread物联网操作系统】欢迎添加关注!文章转载请注明出处。
全部0条评论
快来发表一下你的评论吧 !