[RISC-V MCU 创新应用比赛] 可用于CH32V103R8T6的快速傅里叶FFT变换库

[复制链接]
 楼主| catnull 发表于 2021-8-30 18:47 | 显示全部楼层 |阅读模式
本帖最后由 catnull 于 2021-8-30 18:55 编辑

一、引言
很幸运申请到了南京沁恒自主设计的RISC-V内核CH32V103R8T6。它有72Mhz的系统主频,SRAM有20KB, FLASH有64KB也是够用了。开发板很精致,也设置了Arduino的接口,方便使用一些Arduino接口板开发板。上面自带了一个WCH-LINK 下载仿真器,可以很方便的进行程序的调试。片上丰富的资源,可以展开DSP的实验,特别是离散傅里叶变换的实验。这种数字信号处理的应用相当广泛,例如一些市面上的调音器,还有心率识别,等等,都可以使用傅里叶变化对时域信号进行处理,之后变成频域信号。

二、思路简介
网络上已经有了STM32官方的快速傅里叶变换的库了,相关的应用也开展了不少。但是咱们的CH32V103行不行?直接移植过来,因为涉及到底层的运算优化,非我的能力所能达到。但是作为实验的题目,先解决零到壹的问题。从无到有来解决最好了。
后面找到一本数字信号的书,名字叫做《实用数字信号处理——从原理到应用》, Digital Signal Processing A Practical Guide for Engineers and Scientists , 是一个美国人写的, Steven W. Smith。由北航的两位老师翻译成中文。认真读了一番,因为之前数学上恶补了关于傅里叶变换的知识,啃下了物理系的《数学物理方法》中的复变函数论,所以读起来还算有所收获。
参考里面的BASIC程序,我移植为C语言。先在QT上调试了一番,后面移植到了开发板上,算是达到能用的水平。
但是特别提醒一点,需要打开MountainRiver山河编译器里面的一些编译选项,才能支持数学库里面的正弦余弦运算,以及浮点数的模拟运算的功能(RISC-IMAC是没有实现浮点指令集的,浮点运算需要模拟为整数进行)。

打钩用于一些浮点数的输入输出,方便调试。
浮点的选项.png

下图中的m 编译时时 gcc会加上 -lm,会调用数学库。没有加的或无法计算正余弦函数。
数学库.png

3、快速傅里叶变换FFT库文件中的代码

具体的代码如下:
头文件: cr2_fft.h
  1. /******************
  2. *
  3. * Fast Fourier Transformer
  4. *
  5. * Author : 张远东  莆田  seighbang@126.com
  6. *
  7. *
  8. ********************/

  9. #ifndef CR2_FFT_H
  10. #define CR2_FFT_H


  11. #define PI 3.14159265
  12. #define FFT_N  1024

  13. typedef struct complex
  14. {
  15.     float real ;
  16.     float imag ;
  17. } complex;


  18. int fft(complex* x);
  19. int ifft(complex* x );

  20. #endif // CR2_FFT_H
库文件: cr2_fft.c
  1. #include "cr2_fft.h"
  2. #include <math.h>

  3. int fft(complex* x)
  4. {
  5.     int i =0;
  6.     int ip = 0;
  7.     int j = 0;
  8.     int jm1 = 0;
  9.     int k = 0;
  10.     int l = 0;
  11.     int le = 0;
  12.     int le2 = 0;
  13.     int nm1 = FFT_N-1;
  14.     int nd2 = FFT_N/2;
  15.     int m = (int)(log(FFT_N)/log(2));
  16.     complex t = {.real = 0.0, .imag = 0.0};
  17.     complex u = {.real = 1.0, .imag = 0.0};
  18.     complex s = {.real =0.0, .imag = 0.0};
  19.     /*bit reversal sorting of x_in*/

  20.     j = nd2;
  21.     for(i = 1; i < nm1; i ++)
  22.     {
  23.         if(i < j)   // while the i < j , transverse x[i],x[j],
  24.         {
  25.             t=x[i];
  26.             x[i] = x[j];
  27.             x[j] = t;
  28.         }
  29. //Rather mechod to bit reverse arrangement
  30.         k = nd2;
  31.         while(k <= j)
  32.         {
  33.             j = j - k;        //set the big end bit to 0
  34.             k = k/2;          //the next bit , from up bit k to next bit k/2...
  35.         }
  36.         j = j + k;            //set the big end bit to 1, as k > j
  37.     }

  38.     /******************************************************
  39.      *
  40.      * DFT routine
  41.      *
  42.     *******************************************************/
  43.     for(l =1 ; l <= m; l ++)
  44.     {
  45.         le = (int)(1<<l);
  46.         le2 = le/2;
  47.         u.real = 1.0;
  48.         u.imag = 0.0;
  49.         s.real = cos(PI/le2);
  50.         s.imag = -sin(PI/le2);

  51.         for(j = 1 ; j <= le2; j++)  //for each sub DFT
  52.         {
  53.             jm1 = j -1;
  54.             for(i = jm1; i <= nm1; i = i + le)   //loop for each Butterfly
  55.             {
  56.                 ip = i + le2;
  57.                 t.real = x[ip].real * u.real - x[ip].imag * u.imag;
  58.                 t.imag = x[ip].real * u.imag + x[ip].imag * u.real;
  59.                 x[ip].real = x[i].real - t.real;
  60.                 x[ip].imag = x[i].imag - t.imag;
  61.                 x[i].real = x[i].real + t.real;
  62.                 x[i].imag = x[i].imag + t.imag;

  63.             }

  64.             t.real = u.real;
  65.             u.real = t.real * s.real - u.imag * s.imag;
  66.             u.imag = t.real * s.imag + u.imag * s.real;

  67.         }
  68.     }

  69.     return 0;
  70. }

  71. /********************************************************************************
  72. *
  73. * INVERSE FAST FOURIER TRANSFORM FUNCTION
  74. *
  75. ********************************************************************************/
  76. int ifft(complex * x)
  77. {
  78.     int i = 0;
  79.     int k = 0;
  80.     int n = FFT_N ;
  81.     int nm1 = FFT_N - 1;

  82.     //change the sign of imag part of x[]
  83.     for( k = 0; k < n; k++)
  84.     {
  85.         x[k].imag = -x[k].imag;
  86.     }

  87.     //forward FFT
  88.     fft(x);

  89.     for(i = 0 ; i< n; i++)   //divide the time domain by N and  change the sign of x[].imag.
  90.     {
  91.         x[i].real = x[i].real/n;
  92.         x[i].imag = -x[i].imag/n;
  93.     }

  94.     return 0;
  95. }


4.  测试样例: SCANNER_FTT_2021_08_30.zip (852.31 KB, 下载次数: 35)


5. 测试的效果:

测试图片.png

6.致谢: 感谢南京沁恒公司对我的厚爱,和沁恒的缘分很长,2014年做Arduino的板子,使用的是CH340G,之前也申请过CH32F103的开发板,沁恒也是支持。这次的比赛我也很幸运得到了开发板的物质支持。向沁恒的工程师们致敬!谢谢!
   
GSDDDD 发表于 2021-8-30 21:56 | 显示全部楼层
这个运算速度怎么?要几个mS
 楼主| catnull 发表于 2021-8-30 23:47 | 显示全部楼层
GSDDDD 发表于 2021-8-30 21:56
这个运算速度怎么?要几个mS

测试的是4096个点的。这个库严格讲仅仅是实现了FFT算法,并没有进行优化,偏向原理的学习。但是对于一般的使用应该是可以的。运行的时间我没有测试。使用计时器计时,我还需要学习。
coody 发表于 2021-8-31 17:13 | 显示全部楼层
catnull 发表于 2021-8-30 23:47
测试的是4096个点的。这个库严格讲仅仅是实现了FFT算法,并没有进行优化,偏向原理的学习。但是对于一般 ...

运行时间,用一个IO指示即可。FFT,MCU都可以计算,关键是速度。
kkzz 发表于 2021-9-1 15:49 | 显示全部楼层
计算的速度是多少?   
hudi008 发表于 2021-9-1 16:00 | 显示全部楼层
这个是官网的库函数吗?     
lzmm 发表于 2021-9-1 16:01 | 显示全部楼层
支持一下。        
minzisc 发表于 2021-9-1 16:01 | 显示全部楼层
这个是最近才申请的吗     
selongli 发表于 2021-9-1 16:02 | 显示全部楼层
fft的计算很浪费资源。   
fentianyou 发表于 2021-9-1 16:02 | 显示全部楼层
快速傅里叶和离散傅里叶一样吗   
xiaoyaodz 发表于 2021-9-1 16:03 | 显示全部楼层
72Mhz的计算量真是一般呢   
febgxu 发表于 2021-9-1 16:03 | 显示全部楼层
做个数据解析吧。   
sdlls 发表于 2021-9-1 16:04 | 显示全部楼层
能把matlab的代码转换过来吗
pixhw 发表于 2021-9-1 16:04 | 显示全部楼层
QT有显示吗
selongli 发表于 2021-9-1 16:05 | 显示全部楼层
这个芯片有硬件计算吗   
minzisc 发表于 2021-9-1 16:05 | 显示全部楼层
内部的ram够不够计算呢   
fentianyou 发表于 2021-9-1 16:05 | 显示全部楼层
代码实现是一致的吗   
lzmm 发表于 2021-9-1 16:05 | 显示全部楼层
ch32v103最快好像是80Mhz的频率。   
xiaoyaodz 发表于 2021-9-1 16:05 | 显示全部楼层
ch32v307可以到180Mhz的主频。   
hudi008 发表于 2021-9-1 16:05 | 显示全部楼层
怎么使用lib的函数呢      
您需要登录后才可以回帖 登录 | 注册

本版积分规则

6

主题

40

帖子

1

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

6

主题

40

帖子

1

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