打印
[范例教程]

FFT-LED算法led频谱显示

[复制链接]
2273|63
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
cashrwood|  楼主 | 2023-10-25 13:00 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式


#include<intrins.h>

/********************************************************************/
#define SAMPLE_NUM 128
#define LOG 6
#define TIME 2048           //中断
#define FFT_OUT_MIN 0
#define FFT_OUT_MAX        7      
#define OFF L1=L2=L3=L4=L5=L6=L7=L8=L9=L10=L11=L12=L13=L14=L15=L16=L17=L18=L19=L20=L21=L22=L23=L24=1;
#define ADC_POWER   0x80            //ADC power control bit
#define ADC_FLAG    0x10            //ADC complete flag
#define ADC_START   0x08            //ADC start control bit
//#define ADC_SPEEDLL 0x00            //420 clocks
//#define ADC_SPEEDL  0x20            //280 clocks
#define ADC_SPEEDH  0x40            //140 clocks
//#define ADC_SPEEDHH 0x60            //70 clocks

/********************************************************************/
//采样存储序列表
unsigned char code BRTable[SAMPLE_NUM] ={0, 64, 32, 96, 16, 80, 48, 112,
8, 72, 40, 104, 24, 88, 56, 120,
4, 68, 36, 100, 20, 84, 52, 116,
12, 76, 44, 108, 28, 92, 60, 124,
2, 66, 34, 98, 18, 82, 50, 114,
10, 74, 42, 106, 26, 90, 58, 122,
6, 70, 38, 102, 22, 86, 54, 118,
14, 78, 46, 110, 30, 94, 62, 126,
1, 65, 33, 97, 17, 81, 49, 113,
9, 73, 41, 105, 25, 89, 57, 121,
5, 69, 37, 101, 21, 85, 53, 117,
13, 77, 45, 109, 29, 93, 61, 125,
3, 67, 35, 99, 19, 83, 51, 115,
11, 75, 43, 107, 27, 91, 59, 123,
7, 71, 39, 103, 23, 87, 55, 119,
15, 79, 47, 111, 31, 95, 63, 127};
char code sin_tabb[SAMPLE_NUM] = {0, 6, 12, 18, 24, 30, 36, 42, 48, 54, 59, 65, 70, 75, 80, 85, 89, 94, 98, 102,

105, 108, 112, 114, 117, 119, 121, 123, 124, 125, 126, 126, 126, 126, 126, 125, 124, 123, 121, 119, 117, 114, 112,

108, 105, 102, 98, 94, 89, 85, 80, 75, 70, 65, 59, 54, 48, 42, 36, 30, 24, 18, 12, 6, 0, -6, -12, -18, -24, -30,

-36, -42, -48, -54, -59, -65, -70, -75, -80, -85, -89, -94, -98, -102, -105, -108, -112, -114, -117, -119, -121,

-123, -124, -125, -126, -126, -126, -126, -126, -125, -124, -123, -121, -119, -117, -114, -112, -108, -105, -102,

-98, -94, -89, -85, -80, -75, -70, -65, -59, -54, -48, -42, -36, -30, -24, -18, -12, -6};                        
char code cos_tabb[SAMPLE_NUM] = {127, 126, 126, 125, 124, 123, 121, 119, 117, 114, 112, 108, 105, 102, 98, 94,

89, 85, 80, 75, 70, 65, 59, 54, 48, 42, 36, 30, 24, 18, 12, 6, 0, -6, -12, -18, -24, -30, -36, -42, -48, -54, -59,

-65, -70, -75, -80, -85, -89, -94, -98, -102, -105, -108, -112, -114, -117, -119, -121, -123, -124, -125, -126, -

126, -126, -126, -126, -125, -124, -123, -121, -119, -117, -114, -112, -108, -105, -102, -98, -94, -89, -85, -80,

-75, -70, -65, -59, -54, -48, -42, -36, -30, -24, -18, -12, -6, 0, 6, 12, 18, 24, 30, 36, 42, 48, 54, 59, 65, 70,

75, 80, 85, 89, 94, 98, 102, 105, 108, 112, 114, 117, 119, 121, 123, 124, 125, 126, 126};
xdata unsigned char result[128];
xdata unsigned char temp[128];
xdata unsigned char num[128];
unsigned char anum,timernum,timernum2,lednum3,Ltime,t;//用于分离
unsigned char lednum[]={0x01,0x03,0x07,0x0f,0x1f,0x3f,0x7f,0xff};//0-7的显示数组  P2组控制
int xdata FftReal[SAMPLE_NUM];
int xdata FftImage[SAMPLE_NUM];

unsigned char code musicdisplay[]={
        0x00,0x00,
        0xFE,0x40,0x30,0x40,0xFE,0x00, // -M-
        0xFC,0x02,0x02,0x02,0xFC,0x00, // -U-
        0x64,0x92,0x92,0x92,0x4C,0x00, // -S-
        0x00,0x82,0xFE,0x82,0x00,0x00, // -I-
        0x7C,0x82,0x82,0x82,0x44,0x00, // -C-
        0x00,0x00,0x00,
        0xFE,0x82,0x82,0x82,0x7C,0x00, // -D-
        0x00,0x82,0xFE,0x82,0x00,0x00, // -I-
        0x64,0x92,0x92,0x92,0x4C,0x00, // -S-
        0xFE,0x90,0x90,0x90,0x60,0x00, // -P-
        0xFE,0x02,0x02,0x02,0x02,0x00, // -L-
        0x3E,0x48,0x88,0x48,0x3E,0x00, // -A-
        0xC0,0x20,0x1E,0x20,0xC0,0x00, // -Y-
        0x00,0x00,0x00,0x00,0x00,0x00,
        0x00,0x00,0x00,0x00,0x00,0x00,
        0x00,0x00,0x00,0x00,0x00,0x00,
        0x00,0x00,0x00,0x00,0x00,0x00,
        0x00,0x00,0x00,0x00,0x00,0x00};
/********************************************************************/
#define LED P2
#define pwm 9

sbit L24=P3^2;
sbit L23=P3^1;
sbit L22=P3^0;
sbit L21=P4^7;
sbit L20=P1^7;
sbit L19=P1^6;
sbit L18=P1^5;
sbit L17=P1^4;
sbit L16=P3^3;
sbit L15=P3^4;
sbit L14=P3^5;
sbit L13=P3^6;
sbit L12=P3^7;
sbit L11=P0^2;
sbit L10=P0^1;
sbit L9=P0^0;
sbit L8=P0^3;
sbit L7=P0^4;
sbit L6=P0^5;
sbit L5=P0^6;
sbit L4=P0^7;
sbit L3=P4^6;
sbit L2=P4^5;
sbit L1=P4^4;
/********************************************************************/
void delay(unsigned char a)
{
        unsigned int i;
        while(--a)
                for(i=0;i<50;i++);                                    
}
/********************************************************************/
void off()
{
        LED = 0x00;
        OFF
//        delay(10-pwm);
}
/********************************************************************/
void display(unsigned char i,unsigned char dat)
{
        P2=dat;
        switch(i)
        {
                case 1:L1=0;break;
                case 2:L2=0;break;
                case 3:L3=0;break;
                case 4:L4=0;break;
                case 5:L5=0;break;
                case 6:L6=0;break;
                case 7:L7=0;break;
                case 8:L8=0;break;
                case 9:L9=0;break;
                case 10:L10=0;break;
                case 11:L11=0;break;
                case 12:L12=0;break;
                case 13:L13=0;break;
                case 14:L14=0;break;
                case 15:L15=0;break;
                case 16:L16=0;break;
                case 17:L17=0;break;
                case 18:L18=0;break;
                case 19:L19=0;break;
                case 20:L20=0;break;
                case 21:L21=0;break;
                case 22:L22=0;break;
                case 23:L23=0;break;
                case 24:L24=0;break;
        }
        delay(pwm);
        off();
}
/********************************************************************/
void show_musicdisplay()
{
        unsigned char a,b,c;
        for(c=0;c<80;c++)
                for(b=12;b>0;b--)
                           for(a=1;a<25;a++)
                                display(a,musicdisplay[a-1+c]);
}
/********************************************************************/            
void FFT_process()                          //下落迟滞
{
        unsigned char i;
        for(i=0;i<24;i++)
        {      
                if(result[i] < temp[i])
                {
                        num[i]++;
                        if(num[i] == 1)
                        {
                                if(temp[0]==0&&temp[1]==0&&temp[2]==0&&temp[3]==0&&temp[4]==0&&temp[5]==0&&temp[6]==0&&temp[7]==0&&temp[8]==0&&temp[9]==0&&temp[10]==0&&temp[11]==0&&temp[12]==0&&temp[13]==0&&temp[14]==0&&temp[15]==0&&temp[16]==0&&temp[17]==0&&temp[18]==0&&temp[19]==0&&temp[20]==0&&temp[21]==0&&temp[22]==0&&temp[23]==0&&temp[24]==0);
                                else
                                {
                                        result[i] = --temp[i];
                                        num[i] = 0;
                                }
                        }
                }
                else
                        num[i] = 0;               
        }
}
/********************************************************************/
void disp()
{
//        unsigned char i,j,buff;
        timernum++;
        if(timernum == 25)
                timernum = 1;
           OFF
        FFT_process();
        /*for(i=0;i<16;i++)
                for(j=i+1;j<16;j++)
                        if(result[j] > result[i])
                        {
                                buff = result[i];
                                result[i] = result[j];
                                result[j] = buff;
                        }*/                                          
        switch(timernum)
        {
                case 1:anum = result[0];L1=0;break;
                case 2:anum = result[1];L2=0;break;
                case 3:anum = result[2];L3=0;break;
                case 4:anum = result[3];L4=0;break;
                case 5:anum = result[4];L5=0;break;
                case 6:anum = result[5];L6=0;break;
                case 7:anum = result[6];L7=0;break;
                case 8:anum = result[7];L8=0;break;
                case 9:anum = result[8];L9=0;break;
                case 10:anum = result[9];L10=0;break;
                case 11:anum = result[10];L11=0;break;
                case 12:anum = result[11];L12=0;break;
                case 13:anum = result[12];L13=0;break;
                case 14:anum = result[13];L14=0;break;
                case 15:anum = result[14];L15=0;break;
                case 16:anum = result[15];L16=0;break;
                case 17:anum = result[16];L17=0;break;
                case 18:anum = result[17];L18=0;break;
                case 19:anum = result[18];L19=0;break;
                case 20:anum = result[19];L20=0;break;
                case 21:anum = result[20];L21=0;break;
                case 22:anum = result[21];L22=0;break;
                case 23:anum = result[22];L23=0;break;
                case 24:anum = result[23];L24=0;break;
        }
        if(anum >= 8)
                anum = FFT_OUT_MAX;
        LED = lednum[anum];
}
/********************************************************************/
void ADC_init()
{
        P1ASF = 0x01;                   //Open 8 channels ADC function
    ADC_RES = 0;                    //Clear previous result
        ADC_RESL= 0;
    ADC_CONTR = ADC_POWER | ADC_SPEEDH;
    delay(5);                       //ADC power-on and delay      
}
/********************************************************************/
float ADC_read()
{
//delay(10);      
    ADC_CONTR = ADC_POWER | ADC_SPEEDH  | ADC_START;
    _nop_();                        //至少要延时4个时钟周期
    _nop_();
    _nop_();
    _nop_();
        _nop_();
    while (!(ADC_CONTR & ADC_FLAG));//Wait complete flag
    ADC_CONTR &= ~ADC_FLAG;         //关闭ADC
    return (ADC_RES*4+ADC_RESL);                 //Return ADC result
}
/********************************************************************/
short sqrt_16(unsigned long M)   
{
    unsigned int N,i;
    unsigned long tmp,ttp;
    if( M == 0 )            
        return 0;   
    N = 0;  
    tmp = (M >> 30);        
    M <<= 2;
    if( tmp > 1 )            
    {
        N++;               
        tmp -= N;
    }   
    for( i=15; i>0; i-- )   
    {
        N <<= 1;                  
        tmp <<= 2;
        tmp += (M >> 30);         
        ttp = N;
        ttp = (ttp<<1)+1;        
        M <<= 2;
        if( tmp >= ttp )   
        {
            tmp -= ttp;
            N ++;
        }      
    }   
    return N;
}
/********************************************************************/
void FFT()
{
    register unsigned char i,bb,j,k,p;
    register short TR,TI,temp;
    unsigned long ulReal,ulImage;                             
        unsigned char max;
                                                                  
    for(i=0;i<SAMPLE_NUM;i++)         
    {
                FftReal[BRTable[i]] = ADC_read();
        FftImage[i] = 0;
    }        

    for(i=1;i<=LOG;i++)                        
    {
        bb=1;
        bb <<= (i-1);                                      
        for(j=0;j<=bb-1;j++)                           
        {
            p=1;
            p <<= (LOG-i);           
            p = p*j;
            for(k=j;k<SAMPLE_NUM;k=k+2*bb)               
            {
                TR=FftReal[k];TI=FftImage[k];temp=FftReal[k+bb];
                FftReal[k]=FftReal[k]+((FftReal[k+bb]*cos_tabb[p])>>7)+((FftImage[k+bb]*sin_tabb[p])>>7);
                FftImage[k]=FftImage[k] - ((FftReal[k+bb]*sin_tabb[p])>>7)+((FftImage[k+bb]*cos_tabb[p])>>7);
                FftReal[k+bb]=TR-((FftReal[k+bb]*cos_tabb[p])>>7)-((FftImage[k+bb]*sin_tabb[p])>>7);
                FftImage[k+bb]=TI+((temp*sin_tabb[p])>>7)-((FftImage[k+bb]*cos_tabb[p])>>7);
               
                FftReal[k] >>= 1;            
                FftImage[k] >>= 1;
                FftReal[k+bb] >>= 1;                 
                FftImage[k+bb] >>= 1;                                                                              
            }  
        }
    }

   for(i=0;i<24;i++)
    {  
        ulReal = FftReal[i+1];
        ulReal *= ulReal;
        ulImage = FftImage[i+1];
        ulImage *= ulImage;      
        result[i] = sqrt_16(ulReal+ulImage);                                                                 
                    
    }
/*        for(i=0;i<17;i++)
    {
                while(result[i] > FFT_OUT_MAX)
                {
                for(i=0;i<17;i++)
             {                        
                        result[i] =result[i] -1;      
                  }
            }
        }         */
        while(result[i] == FFT_OUT_MIN)
                {
                for(i=0;i<24;i++)
             {                        
                        result[i] =result[i] +1;      
                  }
            }
        for(i=0;i<24;i++)
        {
                if(result[i] > FFT_OUT_MAX)
                {
                        result[i] = FFT_OUT_MAX;      
                        if(result[i] > max)
                max = result[i];
                }
        }
        //局部增益        */        /*                       
                /*if(max >= 4)               
                for(i=1;i<24;i++)
                        if(result[i] >= 2)
                                result[i]+=1;          */
                                                                 
}
/********************************************************************/            
void init()
{
        P2M0=0XFF;
        P2M1=0X00;
        P3M0=0XFF;
        P3M1=0X00;
        P1M0=0XFE;
        P1M1=0X01;
        P4SW=0x70;

        ADC_init();
        //AUXR |= 0x80;                //定时器时钟1T模式
        TMOD=0x01;
        TH0=(65535-TIME)/256;
        TL0=(65535-TIME)%256;
    EA=1;
        ET0=1;               
        show_musicdisplay();  
        TR0=1;
}
/********************************************************************/
void main()
{
        init();
    while(1)         
        FFT();
}
/********************************************************************/
void timer0() interrupt 1
{
        unsigned char i;
        t++;
        if(t == 24)
        {
                for(i=0;i<24;i++)
                        temp[i] = result[i];
                t = 0;
        }                                 
        disp();
        TH0=(65535-TIME)/256;      
        TL0=(65535-TIME)%256;
}


使用特权

评论回复
沙发
chenqianqian| | 2023-10-25 19:21 | 只看该作者
在LCD上显示效果如何,有图片吗?

使用特权

评论回复
板凳
xiaoyaodz| | 2023-11-11 15:03 | 只看该作者
在输入信号前需要确定输入信号的带宽和采样率。

使用特权

评论回复
地板
fengm| | 2023-11-11 15:53 | 只看该作者
在进行频谱分析前,需要对采集到的信号进行校准,以消除系统误差和环境因素对频谱分析结果的影响。

使用特权

评论回复
5
averyleigh| | 2023-11-11 16:55 | 只看该作者
可以调整FFT-LED算法的参数,如采样率、滤波器类型、颜色映射等,以实现更好的视觉效果。

使用特权

评论回复
6
houjiakai| | 2023-11-11 17:11 | 只看该作者
FFT的核心思想是将时域信号分离,然后再将这些分离的信号转换到频域,此时示波器将从时域转换成频域,显示的是信号幅值与频率之间的关系。

使用特权

评论回复
7
51xlf| | 2023-11-12 09:13 | 只看该作者
在进行 FFT 计算之前,通常需要对原始数据进行一些预处理,如去噪、平滑等。这样可以提高频谱分析的结果质量。

使用特权

评论回复
8
mikewalpole| | 2023-11-12 09:35 | 只看该作者
可能需要考虑使用官方dsp库的fft函数来提高算法的效率。

使用特权

评论回复
9
uptown| | 2023-11-12 10:13 | 只看该作者
可以通过对亮度值进行归一化处理,将亮度范围限制在0-1之间,以避免亮度过高导致显示不准确。

使用特权

评论回复
10
ulystronglll| | 2023-11-12 10:54 | 只看该作者
在显示频谱的过程中,需要根据输入信号的频率和亮度来调整LED的亮度和频率,以保证频谱的清晰和准确。

使用特权

评论回复
11
uptown| | 2023-11-12 12:20 | 只看该作者
如果ADC的动态范围不足,可能会导致频谱分析结果失真或不准确。

使用特权

评论回复
12
jkl21| | 2023-11-12 12:29 | 只看该作者
根据奈奎斯特采样定理,采样频率至少应大于信号最高频率的两倍。否则,将会出现混叠现象,导致频谱失真。

使用特权

评论回复
13
janewood| | 2023-11-12 13:12 | 只看该作者
FFT能够实现的频率分辨率是,因此要求。误差主要来自于用FFT做频谱分析时,得到的是离散谱,而信号(周期信号除外)是连续谱。

使用特权

评论回复
14
robincotton| | 2023-11-12 13:23 | 只看该作者
FFT-LED算法的目的是为了得到LED光源的频谱分布

使用特权

评论回复
15
phoenixwhite| | 2023-11-12 13:40 | 只看该作者
需要在算法中加入噪声抑制的步骤,以减小噪声对频谱分析的影响。

使用特权

评论回复
16
bestwell| | 2023-11-12 13:48 | 只看该作者
算法的动态范围受到ADC的限制。

使用特权

评论回复
17
10299823| | 2023-11-12 14:26 | 只看该作者
在硬件实现过程中,要注意合理分配资源,确保算法的实时性和显示效果。

使用特权

评论回复
18
belindagraham| | 2023-11-12 14:37 | 只看该作者
设计 LED 频谱显示装置的时候,还要考虑到功耗和散热的问题

使用特权

评论回复
19
wangdezhi| | 2023-11-12 15:54 | 只看该作者
一般来说,采样频率越高,获得的频谱越准确;采样点数越多,则得到的频谱分辨率越高。

使用特权

评论回复
20
jkl21| | 2023-11-12 16:12 | 只看该作者
为提高显示质量,需要在频谱显示之前对信号进行滤波。

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

6

主题

1051

帖子

0

粉丝