今天我想从对知识点的掌握程度来说,重点知识点就是fft。
从之前校赛开始知道fft这个东西,我其实并没有怎么深入了解,当时也是学长在我提交之前过来帮我搞定了,所以我也没有深究这个东西。
(今天晚上和实验室一个小伙伴聊了才知道他当时对这个就了解很深入了,这次培训做22年F题就很熟练,这或许也是我要改变的一个点:要用的知识点给他深究到底,至至少要会用)
然后从昨天重新开始接触到fft,我才重新拾起这个知识点。
其实真的想了想,昨天真的是啥也没干出来,真的一点点都没有为今天打下一点点基础
现在就说说自己对这个知识点的阶段性了解吧,自己觉得这样记录下自己阶段性的行为和想法真的很好很好。
首先就是初始化ADC
void Adc_Init(void)
{
ADC_GPIO_Configuration();
ADC_TIM3_Configuration();
ADC_DMA_Configuration();
ADC_Init_Configuration();
}
这个思想其实大家都有,但是我到现在为止其实还没有完完全全写过上面的这四个:GPIO配置、定时器配置、DMA配置、ADC配置。这里填一个坑,以后补上。(现在就先借鉴代码咯)
串口、延时这些系统函数不要忘记了......
然后就是while(1)中的fft
while(1)
{
if(global.adc_finish_fg)
{
global.adc_finish_fg = true;
FFT_test();
// printf("找到的最大值索引: %u\n", maxMagIndex);
// for (int i = 0; i < SAMPLS_NUM; i++)
// {
// printf("adc值[%d]:%d\n",i, ADC_SourceData[i]);
// }
// 将标志复位为false,等待下一次DMA传输完成触发FFT计算
global.adc_finish_fg = false;
}
}
1.这里的flag位就是用DMA传输结束的中断服务助手来修改的(一次传输结束就进入到这个主循环
这个global是定义的全局变量(方便修改
这里为什么要再写一个true,我也不是很理解。
2.进入到这个FFT_test()中
void FFT_test(void)
{
int i;
Get_FFT_Source_Data(FFT_CHANNEL_1);
cr4_fft_256_stm32(FFT_OutData, FFT_SourceData, SAMPLS_NUM);
GetPowerMag();
// for(i = 0; i < SAMPLS_NUM; i++) {
// printf("FFT_SourceData[%d]: %lu\n", i, FFT_SourceData[i]);
// }
// printf("FFT_Mag values:\n");
// for(i = 0; i < SAMPLS_NUM / 2; i++) {
// printf("FFT_Mag[%d]: %lu\n", i, FFT_Mag[i]);
// }
for(i = 0; i < SAMPLS_NUM / 2; i++)
{
printf("%lu ", FFT_Mag[i]);
}
printf("一次结束!!\r\n");
}
这里一个个函数分析下去,可能还是有不懂的。
a.Get_FFT_Source_Data()
void Get_FFT_Source_Data(EN_FFT_CHANNEL channel_idx)
{
u16 i;
for(i=0; i<SAMPLS_NUM; i++)
{
FFT_SourceData[i] = ((signed short)ADC_SourceData[i]) << 16;
}
}
这个输入参数,我也不知道啥意思
typedef enum {
FFT_CHANNEL_1,
// 其他通道
} EN_FFT_CHANNEL;
#define FFT_CHANNEL_1 0 // 或者其他适当的值
感觉是为了凑这个,或者是为了识别通道(就和ADC多通道一样的?我不是很理解
现在对这个函数的理解就是,将ADC采集到的数值移位16,然后存储在全局变量FFT_SourceData中,这个时候初步用上了采样点SMAPLS_NUM
b.第二个函数:cr4
cr4_fft_256_stm32(FFT_OutData, FFT_SourceData, SAMPLS_NUM);
这个我的理解就是:用stm32的官方函数,将source转化out这个,再次用上采样点
c.GetPowerMag函数
void GetPowerMag(void)
{
signed short lX, lY;
float X, Y, Mag;
unsigned short i;
unsigned long maxMag = 0;
unsigned long secondMaxMag = 0;
unsigned short maxIndex = 0;
unsigned short secondMaxIndex = 0;
for(i = 0; i < SAMPLS_NUM / 2; i++)
{
lX = (FFT_OutData[i] << 16) >> 16;
lY = (FFT_OutData[i] >> 16);
X = SAMPLS_NUM * ((float)lX) / 32768;
Y = SAMPLS_NUM * ((float)lY) / 32768;
Mag = sqrt(X * X + Y * Y) / SAMPLS_NUM;
FFT_Mag[i] = (unsigned long)(Mag * 65536);
if (FFT_Mag[i] > maxMag) {
secondMaxMag = maxMag;
secondMaxIndex = maxIndex;
maxMag = FFT_Mag[i];
maxIndex = i;
} else if (FFT_Mag[i] > secondMaxMag) {
secondMaxMag = FFT_Mag[i];
secondMaxIndex = i;
}
}
// printf("Maximum FFT_Mag value: %lu at index %u\n", maxMag, maxIndex);
printf("波形频率:%u KHz\n", secondMaxIndex);
}
这个就是利用数学知识(复变函数)、信号与系统(傅里叶变化),将时域中的信号转化成频域。
且不论里面的数学知识,我其实没有怎么看最后输出的这个secondMaxIndex是怎么来的,今天晚上一直困在串口调试助手中的2khz,自己也没有深究代码,不知道这个是怎么来的。
这里再填一个坑,我要把这个里面看会。
所以自己现在对这个理解就是,先进行数学计算,然后根据最高峰(不算一开始的直流分量),计算前面的Index,根据自己采样率来计算出波形的频率(这里是采样率是:1k)
d.输出观察
for(i = 0; i < SAMPLS_NUM / 2; i++)
{
printf("%lu ", FFT_Mag[i]);
}
printf("一次结束!!\r\n");
这个是我自己加的,我想用matlab观察这些数据:
(用串口得到数据)
(这里的代码真的很简单:就是a[]+plot(a))
利用前面求频率的思想,得到频率。
写写今天的心得和收获:
1.如果可以的话,最好找到一个能跑出来的代码。
这个对我来说,不是直接抄袭来的方便,而是我感觉自己如果面对一个知识点,自己现阶段的拆解和刨析能力还够不到。
就举自己今天学习fft来说,我如果还是自己再钻研别人的片段代码,我很可能还是对fft这个没有最基础的了解。
2.认认真真静下心看解析和代码
一时回想起来,自己真的没有怎么认真看过这个代码,没有像今天晚上写日志的时候从头到尾分析一遍,这导致了我连这个东西的最基本的执行流程也不知道,作用对象是什么?输出的是什么东西?有什么用?这些全都不知道。
说说解析:
还是要相信前人的智慧和经验的,哪怕以一种记忆的方式去记下来有关解析的文章,然后带着这些去理解代码,我觉得也是好的。
这方面我觉得我非常有待进步,因为现在是有想法,行动付出太少了
3.如果可以的话,找一个信得过的人交流一下
非常感谢陈同学救我一命(不然真的会憋在心中憋死)
我感觉我是信得过他这个人,然后连带着我愿意有问题的时候去和他交流,然后听取他的建议和知识。
晚上结束的时候给的建议也很可以:这些东西,你先知道怎么用,等这次比赛结束了,你可以再深究,锻炼一下自己的能力;想培养这种能力的话,你就挑时间多去看看有深度的解析,认认真真地看下去,这个ADC在今后中也非常重要,我觉得你可以看这个。
我在技术方面很喜欢这样的人。
4.对小的知识点一定要理解透
说实在话,我现在对这个过程只是有了结果,反推过程说得通,但是对于其中的小细节我其实不是很懂。如何根据已知频率,来确定采样周期和采样频率和采样率呢?定时器中的arr和pre我要怎么确定呢?如果我要使用双通道,那我要怎么配置呢?如何理解定时器和采样周期的关系呢?
这些我是真的还不懂。
写在最后后后!!!!
其实我知道今天晚上写的分析更多的是我搞出来结果了,然后对这个过程可以说一下说一下。但是如果今天晚上我没有问陈呢?他没有和我说呢?那我如何在今天白天这种状态中转化过来呢?
状态:
1.小组一个女的,要发sci了,然后白天呆在实验室看论文,啥事也不干。
2.之前好像也没啥成就感的东西,现在还在直接做题目,我真的会吗?
3.实验室中,我一直静不下心来去做一件事情,烦躁、心定不住……(这是一种很主观受客观影响的状态,这个对我来说是最大的问题)
4.很敏感,就是啥东西做不出来的时候很敏感,碰到什么都会过激和过度反应
5.基本上丧失了主观能动性,自己激励这些全都没有,除非是长时间坚持一个念头,然后keepit。
我觉得这些该是我最应该积极去面对的问题,解决了这个主观上的问题,我觉得具体的知识点对我来说不是什么太大的问题(想了想,自己在日常生活中也有……)
说说哪些可以让我好受或者说是自己可以发挥出自己
1.换一个小地方,然后自己戴着耳机啥的,钻研一个东西:看ADC这个小知识点,哪怕就是看完参考资料,没有写出来and理解代码。
2.该中断休息休息,不要长时间给困在一个自己觉得效率很低的状态中,above all。
3.找找那些自己信得过的人交流and倾诉困惑。
4.转变念想
这个我觉得可以改变我一整个暑期培训的效率和过程,具体落实了哪些,我想可以去落实一下。
具体的就是:一切靠自己,这是一个难得的可以检验自己的各方面的时机和机会。