[应用方案] 单片机样条插值算法

[复制链接]
486|0
timfordlare 发表于 2025-9-30 10:41 | 显示全部楼层 |阅读模式
插值算法是一种很常用的数据处理手段,插值包括了最邻近插值、线性插值(单线性和双线性)、样条插值(自然样条、抛物样条),本文以抛物样条和自然样条两种方法进行对比,基于ARM单片机GD32F103进行测试。
测试函数

  1. #include "dsp_test.h"


  2. static arm_spline_instance_f32  S;                                //样条插值结构体
  3. static arm_spline_type type=ARM_SPLINE_NATURAL;        //自然样条插值
  4. static float32_t  x[32];                                                //原始数据x
  5. static float32_t  y[32];                                                //原始数据y
  6. static uint32_t n=32;                                                        //原始数据个数
  7. static float32_t  coeffs[3*(32-1)];                                //稀疏矩阵
  8. static float32_t  tempBuffer[2*(32-1)];                        //内部计算缓冲数组



  9. static float32_t  xq[128];
  10. static float32_t  pDst[128];
  11. static uint32_t blockSize=128;

  12. #define num_tab 128/32

  13. void interp_test(u8 mode)
  14. {
  15.         if(mode)
  16.         {
  17.                 type=ARM_SPLINE_NATURAL;//自然样条插值
  18.         }
  19.         else
  20.         {
  21.                 type=ARM_SPLINE_PARABOLIC_RUNOUT;//抛物样条插值
  22.         }

  23.         u8 i=0;
  24.         for(i=0;i<32;i++)
  25.         {
  26.                 x[i]=i*num_tab;
  27.                 y[i]=1.f+arm_sin_f32(100.f*PI*i/256.f+PI/3.f);
  28.         }

  29.         for(i=0;i<128;i++)
  30.         {
  31.                 xq[i]=i;
  32.         }

  33.         arm_spline_init_f32(&S,type,x,y,n,coeffs,tempBuffer);
  34.         arm_spline_f32(&S,xq,pDst,blockSize);

  35.         printf("*****x********");
  36.         for(i=0;i<32;i++)
  37.         {
  38.                 printf("%f",x[i]);
  39.         }
  40.         printf("*****y********");
  41.         for(i=0;i<32;i++)
  42.         {
  43.                 printf("%f",y[i]);
  44.         }


  45.         printf("*****x1********");
  46.         for(i=0;i<128;i++)
  47.         {
  48.                 printf("%f",xq[i]);
  49.         }

  50.         printf("*****y1********");
  51.         for(i=0;i<128;i++)
  52.         {
  53.                 printf("%f",pDst[i]);
  54.         }
  55. }

主函数
  1. /*!
  2.     ile    main.c
  3.     rief   led spark with systick, USART print and key example

  4.     ersion 2014-12-26, V1.0.0, firmware for GD32F10x
  5.     ersion 2017-06-20, V2.0.0, firmware for GD32F10x
  6.     ersion 2018-07-31, V2.1.0, firmware for GD32F10x
  7.     ersion 2020-09-30, V2.2.0, firmware for GD32F10x
  8. */



  9. #include "bitband.h"
  10. #include "led.h"
  11. #include "systick.h"
  12. #include "print.h"
  13. #include "dsp_test.h"

  14. u16 mem_infor[2]={0};
  15. u32 uid[3]={0};


  16. int main(void)
  17. {
  18.     systick_set(96);
  19.         led_init();

  20.         print_config(9600);

  21.         get_mem_infor(&mem_infor[0],&mem_infor[1]);
  22.         printf("GD32F103VKT6 Flash Size=%dKB,Sram Size=%dKB...",mem_infor[1],mem_infor[0]);
  23.         get_uid(uid);
  24.         printf("GD32F103VKT6 UID=%d%d%d...",uid[0],uid[1],uid[2]);
  25.         printf("抛物样条插值测试.....");
  26.         interp_test(0);
  27.         printf("自然样条插值测试.....");
  28.         interp_test(1);
  29.     while(1)
  30.         {
  31.                 led_on();
  32.                 delay_ms(1000);
  33.                 led_off();
  34.                 delay_ms(1000);
  35.     }
  36. }

matlab程序

  1. x=data(1:32,1);
  2. y=data(1:32,2);
  3. x1=data(:,3);
  4. y1=data(:,4);
  5. y2=data(:,5);
  6. subplot(311)
  7. plot(x,y),title('原始数据'),xlabel('x'),ylabel('y'),grid;
  8. subplot(312)
  9. plot(x1,y1),title('抛物样条插值结果'),xlabel('x'),ylabel('y'),grid;
  10. subplot(313)
  11. plot(x1,y2),title('自然样条插值结果'),xlabel('x'),ylabel('y'),grid;

测试结果

83a8e53a6afb0a90d4db40c27a5bf2f1e0fe2708.jpg@1122w_840h.webp
样条插值测试结果
可以看出插值后,正弦曲线变得很平滑,两者插值在细节上无明显的区别,,只是最后几个点和趋势上抛物样条插值变缓自然样条插值保持跟原始数据一样
您需要登录后才可以回帖 登录 | 注册

本版积分规则

46

主题

1673

帖子

1

粉丝
快速回复 在线客服 返回列表 返回顶部