kehuadong

FFT处理

#include <math.h>

// PS: 采集的最高频率为10k,所以采集频率是20k, 然后是左右交替采集, 所以定时器触发周期是40k


// ---------------------------------------------------------------------------
typedef struct
{
	// 采集到的数据
	uint16_t m_adc_buffer[256*2];	
	
	// 零值(初始化时默认为2048)
	int m_adc_zero[2];
	
	// ADC最大幅度
	int m_adc_max[2];
	
	// fft输入
	int  m_fft_src[256];
	
	// fft输出
	int  m_fft_dst[256];
	
	// 通过fft输出得到的等级 0~8
	uint8_t m_level[16];
	
	// 最终等级 0~8 (合并两个通道)
	uint8_t m_final_level[16];
	
	// 顶部,用于显示下落效果 0~8
	uint8_t m_level_top[16];
	
	uint8_t m_level_down_cnt[16];
} fft_t;


fft_t g_fft;

// 获取fft输入
// ---------------------------------------------------------------------------
static void fft_get_src(uint8_t channel)
{
	uint16_t pos = channel;
	int min = 65536;
	int max = 0;	
	
	// m_adc_buffer是两个通道交替采集的数据
	while (pos < 512)
	{
		if (g_fft.m_adc_buffer[pos] < min)
		{
			min = g_fft.m_adc_buffer[pos];
		}
		if (g_fft.m_adc_buffer[pos] > max)
		{
			max = g_fft.m_adc_buffer[pos];
		}
		
		g_fft.m_fft_src[pos/2] = g_fft.m_adc_buffer[pos];
		pos += 2;
	}
	
	// 更新零值
	if (max - min < 50)
	{
		g_fft.m_adc_zero[channel] = (max+min)/2;
	}
	
	// 减去零值得到正负值,并移动到高16位
	for (pos = 0; pos < 256; pos++)
	{
		g_fft.m_fft_src[pos] = (g_fft.m_fft_src[pos] - g_fft.m_adc_zero[channel]) << 16;
	}
	
	// 更新ADC最大幅度
	max = max - min;
	if (g_fft.m_adc_max[channel] > max)
	{
		// 20根据实际效果调整
		g_fft.m_adc_max[channel] -= (g_fft.m_adc_max[channel] - max)/20;
	}
	else
	{
		g_fft.m_adc_max[channel] = max;
	}
}

// 获取最大的模
// ---------------------------------------------------------------------------
static int fft_get_max_mag(uint8_t offset, uint8_t size)
{
	int max = 0;
	for (uint8_t i = 0; i < size; i++)
	{
		int16_t real = g_fft.m_fft_dst[offset+i]>>16;
		int16_t img = (g_fft.m_fft_dst[offset+i]<<16)>>16;
		int mag = (int)sqrt(real*real + img*img);
		if (mag > max)
		{
			max = mag;
		}
	}
	return max;
}

// ---------------------------------------------------------------------------
static const uint8_t s_offsets[17] = 
{
	0, 1, 2, 3, 
	5, 8, 11, 14, 
	19, 26, 34, 42, 
	50, 65, 80, 100, 
	128
};

// 获取level
// ---------------------------------------------------------------------------
static void fft_get_level(uint8_t channel)
{
	int max_adc = g_fft.m_adc_max[channel];
	
	cr4_fft_256_stm32((void*)g_fft.m_fft_dst, (void*)g_fft.m_fft_src, 256);	
		
	for (uint8_t i = 0; i < 16; i++)
	{
		// 电压过低
		if (max_adc < 60)
		{
			g_fft.m_level[i] = 0;
		}
		else
		{
			g_fft.m_level[i] = 16*fft_get_max_mag(s_offsets[i], s_offsets[i+1]-s_offsets[i])/max_adc;
		}
		
		if (g_fft.m_level[i] > 8)
		{
			g_fft.m_level[i] = 8;
		}
	}
	
	if (channel == 0)
	{
		for (uint8_t i = 0; i < 16; i++)
		{
			g_fft.m_final_level[i] = g_fft.m_level[i];
		}
	}
	else
	{
		for (uint8_t i = 0; i < 16; i++)
		{
			if (g_fft.m_final_level[i] < g_fft.m_level[i])
			{
				g_fft.m_final_level[i] = g_fft.m_level[i];
			}
		}
	}
}

// 获取level的顶部
// ---------------------------------------------------------------------------
static void fft_get_level_top(void)
{
	for (uint8_t i = 0; i < 16; i++)
	{
		// 上升
		if (g_fft.m_level_top[i] < g_fft.m_final_level[i])
		{
			g_fft.m_level_down_cnt[i] = 0;
			
			g_fft.m_level_top[i] = g_fft.m_final_level[i];			
		}
		// 下降(15代表先停止一段时间,后面匀速下降)
		else if (++g_fft.m_level_down_cnt[i] > 15) 			
		{
			g_fft.m_level_down_cnt[i] = 10;
			
			if (g_fft.m_level_top[i] > 0)
			{
				g_fft.m_level_top[i]--;
			}
		}
	}
}

// 初始化
// ---------------------------------------------------------------------------
void fft_init(void)
{
	g_fft.m_adc_zero[0] = 2048;
	g_fft.m_adc_zero[1] = 2048;
}

// FFT处理(先决条件是先40k定时触发采集完毕adc数据,然后处理,然后刷LED, 可以通过20ms~25ms(50HZ~40HZ刷新率)定时触发下一次的采集)
// ---------------------------------------------------------------------------
void fft_process(void)
{
	fft_get_src(0);
	fft_get_level(0);
	fft_get_src(1);
	fft_get_level(1);
	fft_get_level_top();
}


#if 0
0: 78
1: 156
2: 234
3: 312
4: 390
5: 468
6: 546
7: 624
8: 703
9: 781
10: 859
11: 937
12: 1015
13: 1093
14: 1171
15: 1249
16: 1328
17: 1406
18: 1484
19: 1562
20: 1640
21: 1718
22: 1796
23: 1874
24: 1953
25: 2031
26: 2109
27: 2187
28: 2265
29: 2343
30: 2421
31: 2499
32: 2578
33: 2656
34: 2734
35: 2812
36: 2890
37: 2968
38: 3046
39: 3124
40: 3203
41: 3281
42: 3359
43: 3437
44: 3515
45: 3593
46: 3671
47: 3749
48: 3828
49: 3906
50: 3984
51: 4062
52: 4140
53: 4218
54: 4296
55: 4374
56: 4453
57: 4531
58: 4609
59: 4687
60: 4765
61: 4843
62: 4921
63: 4999
64: 5078
65: 5156
66: 5234
67: 5312
68: 5390
69: 5468
70: 5546
71: 5624
72: 5703
73: 5781
74: 5859
75: 5937
76: 6015
77: 6093
78: 6171
79: 6249
80: 6328
81: 6406
82: 6484
83: 6562
84: 6640
85: 6718
86: 6796
87: 6874
88: 6953
89: 7031
90: 7109
91: 7187
92: 7265
93: 7343
94: 7421
95: 7499
96: 7578
97: 7656
98: 7734
99: 7812
100: 7890
101: 7968
102: 8046
103: 8124
104: 8203
105: 8281
106: 8359
107: 8437
108: 8515
109: 8593
110: 8671
111: 8749
112: 8828
113: 8906
114: 8984
115: 9062
116: 9140
117: 9218
118: 9296
119: 9374
120: 9453
121: 9531
122: 9609
123: 9687
124: 9765
125: 9843
126: 9921
127: 9999
#endif

 

posted on 2024-04-17 11:26  kehuadong  阅读(36)  评论(0)    收藏  举报

导航