STM32CubeIDE STM32F03C6T6开发板 模拟数据生成 FFT傅里叶运算

开发环境:WIN10

开发软件:STM32CubeIDE

使用硬件:STM32F03C6T6开发板

准备TTF软件:是 GCC版本的。

1.新建项目:TTF_Simulate_data_f103c6

       打开STM32CubeIDE-->文件-->新建-->STM32 project

选择器件: 搜索103c6,选择STM32F03A,-->下一步

--- 输入项目名称,点击“完成”,自动进入STM32CubeMX界面

 二,coudMX设置:

 1.项目使用单片机资源:

(1)外部时钟72MH 、

(2)TIM3 

(3)USART1

(4)PC13

---  外部时钟72MH

RCC设置:

 ---  HCLK(MHz) 位置输入 72  ,回车,点击OK, 自动完成设置。

---  TIM3 设置

---  USART1设置:

--- 中断设置:打开TIM3,USART中断

 ---PC13设置:

--- 保存,确认

至此,项目初始化完成。

三,导入FFT软件,选择文件系统导入,浏览到FFT软件所在文件夹

 --- stm32_dsp.h,table_fft.h 导入 Inc 文件夹

 --- cr4_fft_256_stm32.s,cr4_fft_1024_stm32.s 导入Src 文件夹

  

 也可以分别直接复制,粘贴到 IncSrc 这两个文件夹内。

四、添加自己的程序到main.c  找到绿色代码对应位置,复制范围内的代码到自己的main.c。

添加头文件声明

/* USER CODE END Header */

/* Includes ------------------------------------------------------------------*/

#include "main.h"

/* Private includes ----------------------------------------------------------*/

/* USER CODE BEGIN Includes */

#include "stdio.h"

#include "math.h"

#include "stm32_dsp.h"

#include "table_fft.h"

/* USER CODE END Includes */

添加变量声明:

/* Private variables ---------------------------------------------------------*/

TIM_HandleTypeDef htim3;

UART_HandleTypeDef huart1;

/* USER CODE BEGIN PV */

//串口printf重定向

#ifdef __GNUC__

/* With GCC/RAISONANCE, small printf (option LD Linker->Libraries->Small printf

set to 'Yes') calls __io_putchar() */

#define PUTCHAR_PROTOTYPE int __io_putchar(int ch)

#else

#define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)

#endif /* __GNUC__ */

/**

* @brief Retargets the C library printf function to the USART.

* @param None

* @retval None

*/

PUTCHAR_PROTOTYPE {

/* Place your implementation of fputc here */

/* e.g. write a character to the EVAL_COM1 and Loop until the end of transmission */

HAL_UART_Transmit(&huart1, (uint8_t*) &ch, 1, 0xFFFF);

return ch;

}

int display_on = 1;

char frequency_domain_value = 0;

char frequency_domain = 1;

char simulate_data = 2;

//串口输出使用

#define FQV frequency_domain_value //频谱

//串口绘图使用

#define FQD frequency_domain //频谱

#define SMD simulate_data //仿真数据

#define SPT 256 //Sample points 采样点

long simulate_data_array[SPT]; //模拟数据数组simulate_data_array

long FFT_out_array[SPT / 2];     //FFT运算结果

long Frequency_amplitude_array[SPT / 2];  //频谱 FFT运算结果转换

float PI2 = 6.28318530717959;

uint32_t SPF = 10240; //采样率

/* USER CODE END PV */

添加函数声明:

/* Private function prototypes -----------------------------------------------*/

void SystemClock_Config(void);

static void MX_GPIO_Init(void);

static void MX_TIM3_Init(void);

static void MX_USART1_UART_Init(void);

/* USER CODE BEGIN PFP */

void simulate_data_generation(void); //Generate analog sampling data 生成模拟采样数据

void FFT_256(void);

void get_Frequency_amplitude(void); Frequency amplitude 频率幅度

//打印绘图

char print_drawing(char str); //频谱值

/* USER CODE END PFP */

 主程序初始化 :复位后只执行一次

/* USER CODE BEGIN 2 */

HAL_TIM_Base_Start_IT(&htim3);      //启动定时器3

simulate_data_generation(); //仿真数据生成 //Generate analog sampling data 生成模拟采样数据

FFT_256(); //

get_Frequency_amplitude(); Frequency amplitude 频率幅度

//打印绘图

print_drawing(FQV); //频谱值

/* USER CODE END 2 */

主程序循环

/* USER CODE END WHILE */

/* USER CODE BEGIN 3 */

if (display_on == 1) {

HAL_GPIO_TogglePin(GPIOC, GPIO_PIN_13);   //LED灯状态反转

//打印绘图

print_drawing(FQD); //频谱 

//打印绘图

//需要看频谱,将注释掉下一行代码

// print_drawing(SMD); //仿真数据

display_on = 0;

}

//----------------

}

/* USER CODE END 3 */

添加自己的函数:

//仿真数据生成 SPT是采样点:256,SPF是采样频率:10.240KHz

/* USER CODE BEGIN 4 */

//生成FFT需要的仿真数据

void simulate_data_generation(void) {

unsigned short i;

float Signal;

for (i = 0; i < SPT; i++) {

Signal = 100 * sin(PI2 * i * 60.0 / SPF)    //频率60

+ 100 * sin(PI2 * i * 1280.0 / SPF)      //频率1280

+ 100 * sin(PI2 * i * 5000.0 / SPF);     //频率5000

simulate_data_array[i] = ((signed short) Signal) << 16;

}

}

//FFT

void FFT_256() {

cr4_fft_256_stm32(FFT_out_array, simulate_data_array, SPT);

}

//频谱

void get_Frequency_amplitude() {

signed short lX, lY;

float X, Y, Mag;

for (uint16_t i = 0; i < SPT / 2; i++) {

lX = (FFT_out_array[i] << 16) >> 16;

lY = (FFT_out_array[i] >> 16);

X = SPT * ((float) lX) / 32768;

Y = SPT * ((float) lY) / 32768;

Mag = sqrt(X * X + Y * Y) / SPT;

if (i == 0)

Frequency_amplitude_array[i] = (unsigned long) (Mag * 32768);

else

Frequency_amplitude_array[i] = (unsigned long) (Mag * 65536);

}

}

//打印绘图

char print_drawing(char str) {

for (int i = 0; i < SPT / 2; i++) {

switch (str) {

case 0: //FQV串口输出使用 频谱

printf("i = %d", i); //\r\n

printf(" F = %ld", ((SPF / 256) * i)); //175\r\n

printf(" V = %ld\r\n", Frequency_amplitude_array[i]); //\r\n

break;

//串口绘图使用

case 1: //FQD频谱

printf("%ld\r\n", Frequency_amplitude_array[i]); //

break;

case 2: //SMD仿真数据

printf("%ld\r\n", simulate_data_array[i]); //

break;

}

printf("\r\n");

}

return 0;

}

/* USER CODE END 4 */

中断设置:打开 stm32f1xx_it.c 找到对应位置

添加变量:

/* Private variables ---------------------------------------------------------*/

/* USER CODE BEGIN PV */

extern int display_on;

/* USER CODE END PV */

定时器3

void TIM3_IRQHandler(void) {

/* USER CODE BEGIN TIM3_IRQn 0 */

/* USER CODE END TIM3_IRQn 0 */

HAL_TIM_IRQHandler(&htim3);

/* USER CODE BEGIN TIM3_IRQn 1 */

display_on = 1;

/* USER CODE END TIM3_IRQn 1 */

}

 程序部分结束。

构建项目成功

下载程序:

STM32F03C6T6开发板 运行:

代码:print_drawing(FQV); //频谱值

//FQV串口输出  打印结果:i = 系列 与FFT采样点有关,F = 频率,V = 频率对应的值。

FFT采样点,采样率确定后,频谱的频率就固定下来了,去看SPF = 10240; //采样率,函数 simulate_data_generation(void) 中的生成频率,60Hz,1280Hz,5000Hz。

10240(采样率)  / 256(采样点) = 40  ,很明显生成频率60Hz不在40的整数倍上,看不到60Hz的峰值点,但是邻居频率点幅值是递减的;1280Hz,5000Hz能看到峰值。

i = 0   F = 0   V = 17

i = 1   F = 40   V = 70

i = 2   F = 80   V = 60

i = 3   F = 120   V = 24

i = 4   F = 160   V = 13

i = 5   F = 200   V = 11

i = 6   F = 240   V = 10

i = 7   F = 280   V = 8

i = 8   F = 320   V = 8

i = 9   F = 360   V = 8

i = 10   F = 400   V = 10

i = 11   F = 440   V = 10

i = 12   F = 480   V = 8

i = 13   F = 520   V = 7

i = 14   F = 560   V = 10

i = 15   F = 600   V = 10

i = 16   F = 640   V = 7

i = 17   F = 680   V = 4

i = 18   F = 720   V = 2

i = 19   F = 760   V = 6

i = 20   F = 800   V = 2

i = 21   F = 840   V = 6

i = 22   F = 880   V = 6

i = 23   F = 920   V = 6

i = 24   F = 960   V = 6

i = 25   F = 1000   V = 6

i = 26   F = 1040   V = 2

i = 27   F = 1080   V = 6

i = 28   F = 1120   V = 4

i = 29   F = 1160   V = 4

i = 30   F = 1200   V = 6

i = 31   F = 1240   V = 2

i = 32   F = 1280   V = 96

i = 33   F = 1320   V = 4

i = 34   F = 1360   V = 4

i = 35   F = 1400   V = 6

i = 36   F = 1440   V = 4

i = 37   F = 1480   V = 6

i = 38   F = 1520   V = 4

i = 39   F = 1560   V = 4

i = 40   F = 1600   V = 4

i = 41   F = 1640   V = 4

i = 42   F = 1680   V = 6

i = 43   F = 1720   V = 6

i = 44   F = 1760   V = 4

i = 45   F = 1800   V = 6

i = 46   F = 1840   V = 6

i = 47   F = 1880   V = 6

i = 48   F = 1920   V = 2

i = 49   F = 1960   V = 2

i = 50   F = 2000   V = 2

i = 51   F = 2040   V = 2

i = 52   F = 2080   V = 2

i = 53   F = 2120   V = 2

i = 54   F = 2160   V = 2

i = 55   F = 2200   V = 2

i = 56   F = 2240   V = 4

i = 57   F = 2280   V = 4

i = 58   F = 2320   V = 5

i = 59   F = 2360   V = 4

i = 60   F = 2400   V = 2

i = 61   F = 2440   V = 4

i = 62   F = 2480   V = 2

i = 63   F = 2520   V = 2

i = 64   F = 2560   V = 0

i = 65   F = 2600   V = 0

i = 66   F = 2640   V = 2

i = 67   F = 2680   V = 2

i = 68   F = 2720   V = 2

i = 69   F = 2760   V = 2

i = 70   F = 2800   V = 2

i = 71   F = 2840   V = 0

i = 72   F = 2880   V = 2

i = 73   F = 2920   V = 2

i = 74   F = 2960   V = 2

i = 75   F = 3000   V = 4

i = 76   F = 3040   V = 0

i = 77   F = 3080   V = 2

i = 78   F = 3120   V = 4

i = 79   F = 3160   V = 2

i = 80   F = 3200   V = 2

i = 81   F = 3240   V = 4

i = 82   F = 3280   V = 2

i = 83   F = 3320   V = 4

i = 84   F = 3360   V = 0

i = 85   F = 3400   V = 2

i = 86   F = 3440   V = 4

i = 87   F = 3480   V = 2

i = 88   F = 3520   V = 2

i = 89   F = 3560   V = 4

i = 90   F = 3600   V = 4

i = 91   F = 3640   V = 2

i = 92   F = 3680   V = 2

i = 93   F = 3720   V = 4

i = 94   F = 3760   V = 4

i = 95   F = 3800   V = 2

i = 96   F = 3840   V = 2

i = 97   F = 3880   V = 4

i = 98   F = 3920   V = 4

i = 99   F = 3960   V = 4

i = 100   F = 4000   V = 0

i = 101   F = 4040   V = 4

i = 102   F = 4080   V = 2

i = 103   F = 4120   V = 0

i = 104   F = 4160   V = 2

i = 105   F = 4200   V = 4

i = 106   F = 4240   V = 4

i = 107   F = 4280   V = 2

i = 108   F = 4320   V = 0

i = 109   F = 4360   V = 4

i = 110   F = 4400   V = 4

i = 111   F = 4440   V = 4

i = 112   F = 4480   V = 2

i = 113   F = 4520   V = 2

i = 114   F = 4560   V = 2

i = 115   F = 4600   V = 2

i = 116   F = 4640   V = 2

i = 117   F = 4680   V = 2

i = 118   F = 4720   V = 0

i = 119   F = 4760   V = 2

i = 120   F = 4800   V = 2

i = 121   F = 4840   V = 2

i = 122   F = 4880   V = 4

i = 123   F = 4920   V = 2

i = 124   F = 4960   V = 0

i = 125   F = 5000   V = 96

i = 126   F = 5040   V = 2

i = 127   F = 5080   V = 0

函数 get_Frequency_amplitude() 转换的数据,打印绘图结果:

代码:print_drawing(FQD); //频谱

函数 simulate_data_generation(void) 生成的数据,打印绘图结果:

代码:print_drawing(SMD); //仿真数据

不同采样率,不同生成频率:

参考链接:

【玩转单片机系列002】 如何使用STM32提供的DSP库进行FFT - 知乎 (zhihu.com)

串口 printf 重定向参考:

STM32CubeIDE 利用自带HAL库 串口收发_stm32cube实现串口接收数据_zateper的博客-CSDN博客

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值