-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathmain.c
134 lines (126 loc) · 3.96 KB
/
main.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
#include "stm32f10x.h"
#include "Serial.h"
#include "Delay.h"
#include "stdio.h"
#include "AD.h"
#include "stm32_dsp.h"
#include "math.h"
#include "oled.h"
/*通过修改AD.h里的NPT为256或1024,可指定FFT的点数*/
uint32_t lBufOutArray[NPT]; /* FFT 运算的输出数组 */
uint8_t OLED_DisplayBuf[129] = {0x40}; // OLED显示缓冲区,第一个字节是0x40,表示寄存器地址,后面128个字节是数据
char code(int x)
{
return (char)(0xFF << (8 - x));
}
// 定时器1初始化,1s中断一次
void Timer1_Init(void)
{
NVIC_InitTypeDef NVIC_InitStructure;
NVIC_InitStructure.NVIC_IRQChannel = TIM1_UP_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x01;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x01;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1, ENABLE);
TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
TIM_TimeBaseInitStructure.TIM_Period = 10000 - 1;
TIM_TimeBaseInitStructure.TIM_Prescaler = 7200 - 1;
TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1;
TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInitStructure.TIM_RepetitionCounter = 0;
TIM_TimeBaseInit(TIM1, &TIM_TimeBaseInitStructure);
TIM_ITConfig(TIM1, TIM_IT_Update, ENABLE);
TIM_Cmd(TIM1, ENABLE);
}
int fpsCount = 0,fps = 0;
// 定时器1中断服务函数,用于计算帧率
void TIM1_UP_IRQHandler(void)
{
if (TIM_GetITStatus(TIM1, TIM_IT_Update) != RESET)
{
fps = fpsCount;
fpsCount = 0;
printf("FPS: %d\r\n", fps);
TIM_ClearITPendingBit(TIM1, TIM_IT_Update);
}
}
int main(void)
{
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE);
GPIO_InitTypeDef GPIO_Struct;
GPIO_Struct.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_Struct.GPIO_Pin = GPIO_Pin_13;
GPIO_Struct.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOC, &GPIO_Struct); //点亮PC13,表示程序开始运行
SerialBegin(); //初始化串口
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);
I2C_DMA_Transmit_InitConfig(129, (uint32_t)OLED_DisplayBuf); //初始化DMA
I2C_Configuration(); //初始化I2C
OLED_Init(); //初始化OLED
OLED_Fill(0x00); //清屏
ADC_DMA_Init(); //初始化ADC的DMA中断
AD_Init(); //初始化ADC
Timer1_Init(); //初始化定时器1
TIM3_init(1632, 0); // 44.1kHz ADC sample rate, 72M / 1633
while (1)
{
if (getTrigger())
{
#if NPT == 256
cr4_fft_256_stm32(lBufOutArray, getAD_Value_buf(), NPT);
#elif NPT == 1024
cr4_fft_1024_stm32(lBufOutArray, getAD_Value_buf(), NPT);
#endif
resetTrigger();
int i, j;
int16_t real, imag;
int magnitude[64];
// 正常i可以取到NPT/2,但是这里只取到64是因为OLED的只有128列,两列合并一列,所以只取到64
// i 对应的频率为 i * 44100 / NPT Hz
for (i = 1; i < 64; i++)
{
real = (lBufOutArray[i] << 16) >> 16;
imag = (lBufOutArray[i] >> 16);
magnitude[i] = ((int)sqrt(real * real + imag * imag) >> 3) + 2; //+2是为了让OLED垫高一点,只右移3是因为高频不太明显,正常情况下应该右移5
// 下面注释掉的才是正确的FFT幅值计算方法
// float mag;
// if (i == 0)
// mag = sqrt(real * real + imag * imag);
// else
// mag = sqrt(real * real + imag * imag) * 2;
}
real = (lBufOutArray[0] << 16) >> 16;
imag = (lBufOutArray[0] >> 16);
magnitude[0] = (int)sqrt(real * real + imag * imag) >> 6; //4096/64=64,匹配OLDE的高度
// OLED显示,这里是耗时最多的,FFT计算本身很快
for (j = 7; j != 0; --j)
{
OLED_SetPos(0, j);
char data;
for (i = 0; i < 63; i++)
{
if (magnitude[i] > 0)
{
if (magnitude[i] > 8)
{
magnitude[i] -= 8;
data = 0xFF;
}
else
{
data = code(magnitude[i]);
magnitude[i] = 0;
}
}else{
data = 0x00;
}
OLED_DisplayBuf[2*i+1] = data;
OLED_DisplayBuf[2*i+2] = data;
}
OLED_WriteData_DMA(OLED_DisplayBuf, 129);
}
fpsCount++;
}
}
}