前言
最近在学习数字信号处理的内容,想把在stm32上通过傅立叶快速变换得到的幅频响应数据与在Matlab上直接计算的做比较,所以需要把在stm32上存储着计算结果的那个数组的数据导出来,再加载到Matlab上,下面是具体的操作。
具体实现
1、stm32的部分代码内容
//输入和输出缓冲
#define TEST_LENGTH_SAMPLES 1024
static float testInput_f32[TEST_LENGTH_SAMPLES*2];
static float testOutput_f32[TEST_LENGTH_SAMPLES];
static float testPhase_f32[TEST_LENGTH_SAMPLES];
//调用函数arm_cfft_f32计算幅频和相频
void arm_cfft_f32_app(void)
{
uint16_t i;
for(i=0; i<TEST_LENGTH_SAMPLES; i++)
{
/* 波形是由直流分量,50Hz正弦波组成,波形采样率1024,初始相位60° */
testInput_f32[i*2] = 1 + cos(2*PI*50*i/1024 + PI/3);
testInput_f32[i*2+1] = 0;
}
/* CFFT变换 */
arm_cfft_f32(&arm_cfft_sR_f32_len1024, testInput_f32, 0, 1);
/* 求解模值 */
arm_cmplx_mag_f32(testInput_f32, testOutput_f32, TEST_LENGTH_SAMPLES);
/* 求相频 */
PowerPhaseRadians_f32(testInput_f32, testPhase_f32, TEST_LENGTH_SAMPLES, 0.5f);
}
计算出的结果已经存储到testOutput_f32这个数组里面了,接下来就是要把这个数组里面的数据导出来。
2、以txt文本的格式导出内存中的数据
在Debug模式下输入如下名字导出数据
SAVE D:\data.txt 0x200126B4,0x200136B3
打开D盘,可以看到导出来的txt文档,打开就是一连串懵逼的数字,接下就是要处理这些数字了
3、处理txt文本里的数据
解析Hex格式:
1、把第一行和最后一行删掉
2、把每一行的前8个字符删掉,后2个字符删掉
3、留下中间32个字符,然后每隔8个加一个空格
我一般用 notepad++ 来编辑,操作比较方便,可以一次性对每行的内容进行任意删减和添加,编辑后如下图所示:
把编辑好的 data.txt 放到Matlab的 \Main\bin 目录里,方便直接在代码中打开。
4、Matlab的代码内容
这部分代码内容需要补一下对浮点数概念的理解,例如单精度浮点数它的组成是:1bit符号位 + 8bit阶码 + 23bit尾数,共32bit。
%在STM32计算的数据
fileId = fopen('./data.txt');
data1 = textscan(fileId,'%s');
result = zeros(1,1024);
for i = 1:1024
a = data1{1,1}{i,1};
b = a(1:2);
c = a(3:4);
d = a(5:6);
e = a(7:8);
f = [e,d,c,b];%因为stm32使用小端模式储存数据,对于32位数据aabbccdd,在内存中有低到高储存为ddccbbaa
bin_all = dec2bin(hex2dec(f));
while(length(bin_all)~=32)
bin_all = ['0',bin_all];
end
bin_symbol = bin_all(1); %第1位为符号位
dec_symbol = str2num(bin_symbol);
if(dec_symbol == 0)
dec_symbol = 1;
else
dec_symbol = -1;
end
bin_str = bin_all(2:9); %第2-9为阶码
bin_man = bin_all(10:32); %第10-32为尾数
dec_str = bin2dec(bin_str) - 127; %阶码以移码的形式,需-127
%分两种情况判断(阶码是正数还是负数)
if(dec_str > 0)
bin_man_int = ['1',bin_man(1:dec_str)]; %整数部分
bin_man_dec = bin_man(dec_str+1:23); %小数部分
else
bin_man_int = ['0']; %整数部分
zero_str = char(zeros(1,abs(dec_str)));
for j = 1:abs(dec_str)
zero_str(j) = '0';
end
bin_man_dec = [zero_str,'1',bin_man(1:23)]; %小数部分
end
dec_int = bin2dec(bin_man_int); %整数部分转换成10进制
dec_dec = 0;
for j = 1:(23-dec_str) %小数部分转换成10进制
if(bin_man_dec(j) == '1')
dec_dec = dec_dec + 2^(-j);
end
end
result(i) = dec_symbol * (dec_int + dec_dec); %解码好的内容
end
%在matlab计算的数据
Fs = 1024;
N = 1024;
n = 0:N-1;
t = 0:1/Fs:1-1/Fs;
f = n*Fs/N;
x = 1 + cos(2*pi*50*t+pi/3);
y = fft(x,N);
mag = abs(y);
subplot(2,1,1);
plot(f,mag);
title('matlab计算 fft幅频响应');
xlabel('频率/Hz');
ylabel('幅度');
subplot(2,1,2);
plot(f,result);
title('stm32计算 fft幅频响应');
xlabel('频率/Hz');
ylabel('幅度');
5、运行的结果
可以看到在stm32上面使用官方的dsp库计算出来的结果跟在Matlab上计算的结果大致一样。