timfordlare 发表于 2025-9-30 10:41

单片机样条插值算法

插值算法是一种很常用的数据处理手段,插值包括了最邻近插值、线性插值(单线性和双线性)、样条插值(自然样条、抛物样条),本文以抛物样条和自然样条两种方法进行对比,基于ARM单片机GD32F103进行测试。
测试函数

#include "dsp_test.h"


static arm_spline_instance_f32S;                              //样条插值结构体
static arm_spline_type type=ARM_SPLINE_NATURAL;      //自然样条插值
static float32_tx;                                                //原始数据x
static float32_ty;                                                //原始数据y
static uint32_t n=32;                                                      //原始数据个数
static float32_tcoeffs;                              //稀疏矩阵
static float32_ttempBuffer;                        //内部计算缓冲数组



static float32_txq;
static float32_tpDst;
static uint32_t blockSize=128;

#define num_tab 128/32

void interp_test(u8 mode)
{
      if(mode)
      {
                type=ARM_SPLINE_NATURAL;//自然样条插值
      }
      else
      {
                type=ARM_SPLINE_PARABOLIC_RUNOUT;//抛物样条插值
      }

      u8 i=0;
      for(i=0;i<32;i++)
      {
                x=i*num_tab;
                y=1.f+arm_sin_f32(100.f*PI*i/256.f+PI/3.f);
      }

      for(i=0;i<128;i++)
      {
                xq=i;
      }

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

      printf("*****x********");
      for(i=0;i<32;i++)
      {
                printf("%f",x);
      }
      printf("*****y********");
      for(i=0;i<32;i++)
      {
                printf("%f",y);
      }


      printf("*****x1********");
      for(i=0;i<128;i++)
      {
                printf("%f",xq);
      }

      printf("*****y1********");
      for(i=0;i<128;i++)
      {
                printf("%f",pDst);
      }
}
主函数
/*!
    ile    main.c
    rief   led spark with systick, USART print and key example

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



#include "bitband.h"
#include "led.h"
#include "systick.h"
#include "print.h"
#include "dsp_test.h"

u16 mem_infor={0};
u32 uid={0};


int main(void)
{
    systick_set(96);
      led_init();

      print_config(9600);

      get_mem_infor(&mem_infor,&mem_infor);
      printf("GD32F103VKT6 Flash Size=%dKB,Sram Size=%dKB...",mem_infor,mem_infor);
      get_uid(uid);
      printf("GD32F103VKT6 UID=%d%d%d...",uid,uid,uid);
      printf("抛物样条插值测试.....");
      interp_test(0);
      printf("自然样条插值测试.....");
      interp_test(1);
    while(1)
      {
                led_on();
                delay_ms(1000);
                led_off();
                delay_ms(1000);
    }
}
matlab程序

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

样条插值测试结果可以看出插值后,正弦曲线变得很平滑,两者插值在细节上无明显的区别,,只是最后几个点和趋势上抛物样条插值变缓自然样条插值保持跟原始数据一样
页: [1]
查看完整版本: 单片机样条插值算法