久久久久久久999_99精品久久精品一区二区爱城_成人欧美一区二区三区在线播放_国产精品日本一区二区不卡视频_国产午夜视频_欧美精品在线观看免费

 找回密碼
 立即注冊(cè)

QQ登錄

只需一步,快速開(kāi)始

搜索
查看: 4150|回復(fù): 2
收起左側(cè)

使用0.96OLED與STC單片機(jī)的音樂(lè)頻譜程序

[復(fù)制鏈接]
ID:570019 發(fā)表于 2019-6-23 13:42 | 顯示全部樓層 |閱讀模式
自己寫的一個(gè)項(xiàng)目,基于FFT算法實(shí)現(xiàn)的音樂(lè)頻譜,利用OLED實(shí)現(xiàn)顯示,需要在32M晶振運(yùn)行

單片機(jī)源程序如下:
  1. #include"OLED.H"

  2. sbit sb0=P3^6;//定義按鈕位置
  3. sbit sb1=P3^5;

  4. idata uchar fft_shuzu[2][32];
  5. uint s_time;

  6. struct compx                                                                           //定義復(fù)數(shù)結(jié)構(gòu)體
  7. {
  8.         float real;
  9.         float imag;
  10. };
  11. xdata struct compx s[ 64 ];                                                 //FFT數(shù)據(jù)緩存放在XDATA空間
  12. struct compx EE(struct compx,struct compx);                 //復(fù)數(shù)乘法函數(shù)的聲明
  13. void FFT(struct compx xin[],int N);                                  //FFT函數(shù)的聲明
  14. struct compx EE(struct compx a1,struct compx b2)         //復(fù)數(shù)乘法
  15. {
  16.         struct compx b3;
  17.         b3.real=a1.real*b2.real-a1.imag*b2.imag;
  18.         b3.imag=a1.real*b2.imag+a1.imag*b2.real;
  19.         return(b3);
  20. }
  21. /*FFT函數(shù)*/
  22. void FFT(struct compx xin[],int N)                                  
  23. {
  24.         int f,m,nv2,nm1,i,k,j=1,l;
  25.         struct compx v,w,t;
  26.         nv2=N/2;
  27.         f=N;
  28.         for(m=1;(f=f/2)!=1;m++){;}
  29.         nm1=N-1;
  30.         for(i=0;i<nm1;i++)                                           //倒序操作
  31.         {
  32.                 if(i<j)
  33.                 {
  34.                         t=xin[j];
  35.                         xin[j]=xin[i];
  36.                         xin[i]=t;
  37.                 }
  38.                 k=nv2;                                                       //k為倒序中相應(yīng)位置的權(quán)值
  39.                 while(k<j)
  40.                 {
  41.                         j=j-k;
  42.                         k=k/2;
  43.                 }
  44.                 j=j+k;
  45.         }
  46.         {
  47.                 int le,lei,ip;
  48.                   float pi;
  49.                   for(l=1;l<=m;l++)
  50.                    {
  51.                 le=pow(2,l);                                                 //乘方
  52.                     lei=le/2;
  53.                     pi=3.14159265;
  54.                     v.real=1.0;
  55.                 v.imag=0.0;  
  56.                    w.real=cos(pi/lei);                                           //旋轉(zhuǎn)因子
  57.                     w.imag=-sin(pi/lei);
  58.                    
  59.                 for(j=1;j<=lei;j++)                                           //控制蝶形運(yùn)算的級(jí)數(shù)
  60.                      {
  61.                         for(i=j-1;i<N;i=i+le)                                         //控制每級(jí)蝶形運(yùn)算的次數(shù)
  62.                               {
  63.                                     ip=i+lei;
  64.                                        t=EE(xin[ ip ],v);
  65.                                        xin[ ip ].real=xin[ i ].real-t.real;   //蝶形計(jì)算
  66.                                        xin[ ip ].imag=xin[ i ].imag-t.imag;
  67.                                        xin[ i ].real=xin[ i ].real+t.real;
  68.                                        xin[ i ].imag=xin[ i ].imag+t.imag;
  69.                               }
  70.                               v=EE(v,w);   
  71.                       }     
  72.                    }
  73.           }
  74. }
  75. void showbar0()//延時(shí)跳帽函數(shù)
  76. {                               
  77.     unsigned char i,j,x,p,high,tigh,temp,itemp;
  78.         xdata unsigned char dis_rdata[16];
  79.         for(i=0;i<16;i++)          //讀取FFT轉(zhuǎn)換數(shù)據(jù)
  80.         {
  81.                 float t0=0;
  82.                 t0=sqrt(pow((s[i  ].real+s[i+1].real),2)+pow((s[i  ].imag+s[i+1].imag),2))/2;
  83.                 dis_rdata[i]=(unsigned char)t0;
  84.         }
  85. //        OLED_Display_On();
  86.         for(i=0;i<16;i++)//16個(gè)條形柱控制
  87.         {
  88.                 itemp=high=0;
  89.                 itemp=high=dis_rdata[i];//對(duì)處理變量賦值
  90. //                high=high/1;
  91.                 for(x=0;x<8;x++)//清空當(dāng)前條形柱空間
  92.                 {
  93.                         OLED_Set_Pos(i*8,7-x);
  94.                         temp=0x00;
  95.                         for(j=0;j<8;j++)
  96.                         {
  97.                                 OLED_WR_Byte(temp,1);
  98.                         }
  99.                 }
  100.                
  101.                 if(high>64)high=64;//溢出值限制
  102.                 if(fft_shuzu[0][i]<=high)//檢測(cè)當(dāng)前大小
  103.                 {
  104.                         fft_shuzu[0][i]=high;//大于賦值當(dāng)前頻譜帽為此值
  105.                         fft_shuzu[1][i]=10;//重新設(shè)置當(dāng)前延時(shí)
  106.                 }
  107.                 fft_shuzu[1][i]--;//當(dāng)前延時(shí)自減
  108.                 if(fft_shuzu[1][i]==0)//如果當(dāng)前延時(shí)為0
  109.                 {
  110.                         fft_shuzu[0][i]=high;//強(qiáng)度等于當(dāng)前大小
  111.                 }
  112.                
  113.                 p=high/8;                //掃描圖形生成
  114.                 tigh=high%8;
  115.                 for(x=0;x<p;x++)//填滿單元區(qū)域
  116.                 {
  117.                         OLED_Set_Pos(i*8,7-x);
  118.                         temp=0xff;
  119.                         for(j=0;j<7;j++)
  120.                         {
  121.                                 OLED_WR_Byte(temp,1);
  122.                         }
  123.                 }
  124.                
  125.                 p=fft_shuzu[0][i]/8;//生成延時(shí)帽所在位置函數(shù)
  126.                 tigh=fft_shuzu[0][i]%8;
  127.                 if((itemp/8)==p)//如果與所在位置重合
  128.                 {
  129.                         OLED_Set_Pos(i*8,7-p);//到達(dá)所在位置
  130.                         temp=0x80>>tigh;//生成延時(shí)帽
  131.                         temp=temp|~0xff>>(high%8);//合并當(dāng)前位置
  132.                         for(j=0;j<7;j++)//發(fā)送屏幕
  133.                         {
  134.                                 OLED_WR_Byte(temp,1);
  135.                         }
  136.                 }
  137.                 else//如果不重合
  138.                 {
  139.                         OLED_Set_Pos(i*8,7-p);//到達(dá)生成位置
  140.                         temp=0x80>>tigh;//生成延時(shí)帽
  141.                         for(j=0;j<7;j++)//發(fā)送屏幕
  142.                         {
  143.                                 OLED_WR_Byte(temp,1);
  144.                         }
  145.                        
  146.                         OLED_Set_Pos(i*8,7-(high/8));//到達(dá)非滿數(shù)單元
  147.                         temp=~0xff>>(itemp%8);//生成條形柱
  148.                         for(j=0;j<7;j++)//發(fā)送
  149.                         {
  150.                                 OLED_WR_Byte(temp,1);
  151.                         }
  152.                 }
  153.         }
  154. }

  155. /*----以下生成函數(shù)原理差不多----*/

  156. void showbar1()//條形柱函數(shù)
  157. {                               
  158.     unsigned char i,j,x,p,high,tigh,temp;
  159.         xdata unsigned char dis_rdata[16];
  160.         for(i=0;i<16;i++)          //讀取FFT轉(zhuǎn)換數(shù)據(jù)
  161.         {
  162.                 float t0=0;
  163.                 t0=sqrt(pow((s[i  ].real+s[i+1].real),2)+pow((s[i  ].imag+s[i+1].imag),2))/2;
  164.                 dis_rdata[i]=(unsigned char)t0;
  165.         }
  166. //        OLED_Display_On();
  167.         for(i=0;i<16;i++)
  168.         {
  169.                 high=0;
  170.                 high=dis_rdata[i];
  171. //                high=high/1;
  172.                 for(x=0;x<8;x++)
  173.                 {
  174.                         OLED_Set_Pos(i*8,7-x);
  175.                         temp=0x00;
  176.                         for(j=0;j<8;j++)
  177.                         {
  178.                                 OLED_WR_Byte(temp,1);
  179.                         }
  180.                 }
  181.                 if(high>64)high=64;
  182.                 if(high==0)high=1;
  183.                 p=high/8;
  184.                 tigh=high%8;
  185.                 for(x=0;x<p;x++)
  186.                 {
  187.                         OLED_Set_Pos(i*8,7-x);
  188.                         temp=0xff;
  189.                         for(j=0;j<7;j++)
  190.                         {
  191.                                 OLED_WR_Byte(temp,1);
  192.                         }
  193.                 }
  194.                 OLED_Set_Pos(i*8,7-(high/8));
  195.                 temp=~0xff>>(high%8);
  196.                 for(j=0;j<7;j++)
  197.                 {
  198.                         OLED_WR_Byte(temp,1);
  199.                 }
  200.         }
  201. }

  202. void showbar2()//等號(hào)指示函數(shù)
  203. {                               
  204.     unsigned char i,j,x,p,high,tigh,temp,itemp;
  205.         xdata unsigned char dis_rdata[16];
  206.         for(i=0;i<16;i++)          //讀取FFT轉(zhuǎn)換數(shù)據(jù)
  207.         {
  208.                 float t0=0;
  209.                 t0=sqrt(pow((s[i  ].real+s[i+1].real),2)+pow((s[i  ].imag+s[i+1].imag),2))/2;
  210.                 dis_rdata[i]=(unsigned char)t0;
  211.         }
  212. //        OLED_Display_On();
  213.         for(i=0;i<16;i++)
  214.         {
  215.                 itemp=high=0;
  216.                 itemp=high=dis_rdata[i];
  217. //                high=high/1;
  218.                 for(x=0;x<8;x++)
  219.                 {
  220.                         OLED_Set_Pos(i*8,7-x);
  221.                         temp=0x00;
  222.                         for(j=0;j<8;j++)
  223.                         {
  224.                                 OLED_WR_Byte(temp,1);
  225.                         }
  226.                 }
  227.                 if(high>64)high=64;
  228.                 p=high/8;
  229.                 tigh=high%8;
  230.                 if(p==0)
  231.                 {
  232.                         p=1;
  233.                         temp=0x80;
  234.                 }
  235.                 else temp=0x88;
  236.                 for(x=0;x<p;x++)
  237.                 {
  238.                         OLED_Set_Pos(i*8,7-x);
  239.                         for(j=0;j<7;j++)
  240.                         {
  241.                                 OLED_WR_Byte(temp,1);
  242.                         }
  243.                 }
  244.         }
  245. }

  246. void showbar3()//延時(shí)跳帽函數(shù)取反
  247. {                               
  248.     unsigned char i,j,x,p,high,tigh,temp,itemp;
  249.         xdata unsigned char dis_rdata[16];
  250.         for(i=0;i<16;i++)          //讀取FFT轉(zhuǎn)換數(shù)據(jù)
  251.         {
  252.                 float t0=0;
  253.                 t0=sqrt(pow((s[i  ].real+s[i+1].real),2)+pow((s[i  ].imag+s[i+1].imag),2))/2;
  254.                 dis_rdata[i]=(unsigned char)t0;
  255.         }
  256. //        OLED_Display_On();
  257.         for(i=0;i<16;i++)
  258.         {
  259.                 itemp=high=0;
  260.                 itemp=high=dis_rdata[i];
  261. //                high=high/1;
  262.                 for(x=0;x<8;x++)
  263.                 {
  264.                         OLED_Set_Pos(i*8,7-x);
  265.                         temp=0xFF;
  266.                         for(j=0;j<8;j++)
  267.                         {
  268.                                 OLED_WR_Byte(temp,1);
  269.                         }
  270.                 }
  271.                
  272.                 if(high>64)high=64;
  273.                 if(fft_shuzu[0][i]<=high)
  274.                 {
  275.                         fft_shuzu[0][i]=high;
  276.                         fft_shuzu[1][i]=10;
  277.                 }
  278.                 fft_shuzu[1][i]--;
  279.                 if(fft_shuzu[1][i]==0)
  280.                 {
  281.                         fft_shuzu[0][i]=high;
  282.                 }
  283.                
  284.                 p=high/8;
  285.                 tigh=high%8;
  286.                 for(x=0;x<p;x++)
  287.                 {
  288.                         OLED_Set_Pos(i*8,7-x);
  289.                         temp=0x00;
  290.                         for(j=0;j<7;j++)
  291.                         {
  292.                                 OLED_WR_Byte(temp,1);
  293.                         }
  294.                 }
  295.                
  296.                 p=fft_shuzu[0][i]/8;
  297.                 tigh=fft_shuzu[0][i]%8;
  298.                 if((itemp/8)==p)
  299.                 {
  300.                         OLED_Set_Pos(i*8,7-p);
  301.                         temp=~0x80>>tigh;
  302.                         temp=temp|0xff>>(high%8);
  303.                         for(j=0;j<7;j++)
  304.                         {
  305.                                 OLED_WR_Byte(temp,1);
  306.                         }
  307.                 }
  308.                 else
  309.                 {
  310.                         OLED_Set_Pos(i*8,7-p);
  311.                         temp=~0x80>>tigh;
  312.                         for(j=0;j<7;j++)
  313.                         {
  314.                                 OLED_WR_Byte(temp,1);
  315.                         }
  316.                        
  317.                         OLED_Set_Pos(i*8,7-(high/8));
  318.                         temp=0xff>>(itemp%8);
  319.                         for(j=0;j<7;j++)
  320.                         {
  321.                                 OLED_WR_Byte(temp,1);
  322.                         }
  323.                 }
  324.         }
  325. }

  326. void showbar4()//條形柱取反函數(shù)
  327. {                               
  328.     unsigned char i,j,x,p,high,tigh,temp;
  329.         xdata unsigned char dis_rdata[16];
  330.         for(i=0;i<16;i++)          //讀取FFT轉(zhuǎn)換數(shù)據(jù)
  331.         {
  332.                 float t0=0;
  333.                 t0=sqrt(pow((s[i  ].real+s[i+1].real),2)+pow((s[i  ].imag+s[i+1].imag),2))/2;
  334.                 dis_rdata[i]=(unsigned char)t0;
  335.         }
  336. //        OLED_Display_On();
  337.         for(i=0;i<16;i++)
  338.         {
  339.                 high=0;
  340.                 high=dis_rdata[i];
  341. //                high=high/1;
  342.                 for(x=0;x<8;x++)
  343.                 {
  344.                         OLED_Set_Pos(i*8,7-x);
  345.                         temp=0xff;
  346.                         for(j=0;j<8;j++)
  347.                         {
  348.                                 OLED_WR_Byte(temp,1);
  349.                         }
  350.                 }
  351.                 if(high>64)high=64;
  352.                 if(high==0)high=1;
  353.                 p=high/8;
  354.                 tigh=high%8;
  355.                 for(x=0;x<p;x++)
  356.                 {
  357.                         OLED_Set_Pos(i*8,7-x);
  358.                         temp=0x00;
  359.                         for(j=0;j<7;j++)
  360.                         {
  361.                                 OLED_WR_Byte(temp,1);
  362.                         }
  363.                 }
  364.                 OLED_Set_Pos(i*8,7-(high/8));
  365.                 temp=0xff>>(high%8);
  366.                 for(j=0;j<7;j++)
  367.                 {
  368.                         OLED_WR_Byte(temp,1);
  369.                 }
  370.         }
  371. }

  372. void showbar5()//等號(hào)指示函數(shù)
  373. {                               
  374.   unsigned char i,j,x,p,high,tigh,temp,itemp;
  375.         xdata unsigned char dis_rdata[16];
  376.         for(i=0;i<16;i++)          //讀取FFT轉(zhuǎn)換數(shù)據(jù)
  377.         {
  378.                 float t0=0;
  379.                 t0=sqrt(pow((s[i  ].real+s[i+1].real),2)+pow((s[i  ].imag+s[i+1].imag),2))/2;
  380.                 dis_rdata[i]=(unsigned char)t0;
  381.         }
  382. //        OLED_Display_On();
  383.         for(i=0;i<16;i++)
  384.         {
  385.                 itemp=high=0;
  386.                 itemp=high=dis_rdata[i];
  387. //                high=high/1;
  388.                 for(x=0;x<8;x++)
  389.                 {
  390.                         OLED_Set_Pos(i*8,7-x);
  391.                         temp=0xff;
  392.                         for(j=0;j<8;j++)
  393.                         {
  394.                                 OLED_WR_Byte(temp,1);
  395.                         }
  396.                 }
  397.                 if(high>64)high=64;
  398.                 p=high/8;
  399.                 tigh=high%8;
  400.                 if(p==0)
  401.                 {
  402.                         p=1;
  403.                         temp=~0x80;
  404.                 }
  405.                 else temp=~0x88;
  406.                 for(x=0;x<p;x++)
  407.                 {
  408.                         OLED_Set_Pos(i*8,7-x);
  409.                         for(j=0;j<7;j++)
  410.                         {
  411.                                 OLED_WR_Byte(temp,1);
  412.                         }
  413.                 }
  414.         }
  415. }

  416. /*主函數(shù)*/
  417. void main()                                                                    
  418. {
  419.         int N=64,i,k;                                                             //變量初始化,64點(diǎn)FFT運(yùn)算
  420.         float offset;
  421.         s_time=0;
  422.        
  423.         TMOD=0X01;                                                //定時(shí)器開(kāi)到模式1
  424.         TH0=(65535-10000)/256;                        //設(shè)置延時(shí)時(shí)間
  425.         TL0=(65535-10000)%256;
  426.         TR0=1;                                                        //啟動(dòng)定時(shí)器0
  427.         ET0=1;                                                        //開(kāi)啟定時(shí)器0中斷
  428.         EA=1;                                                        //開(kāi)啟中斷
  429.        
  430.         oled_init();  //OLED
  431.         OLED_Clear();
  432.        
  433.         P1ASF=0x01;                                                                      //P10口做AD 使用
  434.         P1M0 = 0x01;                                                //0000,0001用于A/D轉(zhuǎn)換的P1.x口,先設(shè)為開(kāi)漏
  435.         P1M1 = 0x01;                                                //0000,0001 P1.0先設(shè)為開(kāi)漏。斷開(kāi)內(nèi)部上拉電阻
  436.         ADC_CONTR=0xC8;                                                                 //40.96K采樣率
  437.         while(!(ADC_CONTR&0x10));
  438.         offset=((float)ADC_RES*4+(float)(ADC_RESL%0x04)); //AD結(jié)果高8位左移2位,低2位不變,然后相加
  439.         while(1)
  440.         {                if(P3==(P3&0xFE))IAP_CONTR=0x60;               
  441.                         for(i=0;i<N;i++)                                      //采集音頻信號(hào)
  442.                           {
  443.                                                 ADC_CONTR=0xC8;                                         //40.96K采樣率
  444.                                                 while(!(ADC_CONTR&0x10));
  445.                                                         s[i].real=((float)ADC_RES*4+(float)(ADC_RESL%0x04)-offset);//((((int)ADC_DATA-128)/2))*4;
  446.                                                         s[i].imag=0;
  447.                           }
  448.                           FFT(s,N);                        //調(diào)用FFT函數(shù)進(jìn)行變換
  449.                         EA=0;
  450.                         if(sb0==0)                        //模式調(diào)節(jié)按鈕控制
  451.                         {
  452.                                 delay(100);
  453.                                 if(sb0==0)
  454.                                 {
  455.                                         while(!sb0);
  456.                                         delay(100);
  457.                                         k+=1;
  458.                                         if(k==6)k=0;
  459.                                 }
  460.                         }
  461.                         if(sb1==0)                        //延時(shí)調(diào)節(jié)按鈕控制
  462.                         {
  463.                                 delay(100);
  464.                                 if(sb1==0)
  465.                                 {
  466.                                         while(!sb1);
  467.                                         delay(100);
  468.                                         s_time+=100;
  469.                                         if(s_time==1100)s_time=0;
  470.                                 }
  471.                         }
  472.                         switch(k)                        //顯示頻譜
  473.                         {
  474.                                 case 0:showbar0();break;                        //延時(shí)跳帽函數(shù)
  475.                                 case 1:showbar1();break;                        //條形柱函數(shù)
  476.                                 case 2:showbar2();break;                        //等號(hào)條函數(shù)
  477.                                 case 3:showbar3();break;                        //延時(shí)跳帽函數(shù)取反
  478.                                 case 4:showbar4();break;                        //條形柱函數(shù)取反
  479.                                 case 5:showbar5();break;                        //等號(hào)條函數(shù)取反
  480.                         }
  481.                         EA=1;
  482.                         delay(s_time);//顯示延時(shí)函數(shù)
  483.         }
  484. }

  485. void yp_l()interrupt 1
  486. {
  487.        
  488.         TH0=(65535-10000)/256;                //設(shè)置延時(shí)時(shí)間
  489.         TL0=(65535-10000)%256;
  490. }
復(fù)制代碼

所有程序51hei提供下載:
OLED FFT.rar (72.2 KB, 下載次數(shù): 152)

評(píng)分

參與人數(shù) 1黑幣 +50 收起 理由
admin + 50 共享資料的黑幣獎(jiǎng)勵(lì)!

查看全部評(píng)分

回復(fù)

使用道具 舉報(bào)

ID:546014 發(fā)表于 2019-10-30 22:14 | 顯示全部樓層
有原理圖嗎
回復(fù)

使用道具 舉報(bào)

ID:48994 發(fā)表于 2021-9-20 14:31 | 顯示全部樓層
感謝分享,正在學(xué)習(xí)這方面的知識(shí)!
回復(fù)

使用道具 舉報(bào)

本版積分規(guī)則

手機(jī)版|小黑屋|51黑電子論壇 |51黑電子論壇6群 QQ 管理員QQ:125739409;技術(shù)交流QQ群281945664

Powered by 單片機(jī)教程網(wǎng)

快速回復(fù) 返回頂部 返回列表
主站蜘蛛池模板: 全免一级毛片 | 国产露脸国语对白在线 | 亚洲精品视频免费看 | 欧美一区二区成人 | 超碰97人人人人人蜜桃 | 在线欧美视频 | 亚洲深夜福利 | 日韩欧美国产一区二区三区 | 久久丝袜视频 | 久久成人国产精品 | 伊人久久精品 | 日韩一区二区精品 | 欧洲亚洲一区 | 97在线超碰 | 日韩第一夜 | 日韩午夜| 特一级毛片| 成人午夜黄色 | 欧美高清视频在线观看 | 日韩三级一区 | 激情婷婷 | 日韩在线精品视频 | 天堂男人av| 欧美视频xxx | 精品视频在线观看 | 成人免费视频网站在线观看 | 久久美女网 | 久久99精品国产 | 久热国产精品 | 日韩高清三区 | av手机在线免费观看 | 欧美综合一区 | 91天堂| 麻豆精品一区二区三区在线观看 | 精品欧美激情精品一区 | 国产一区不卡 | 一区二区视频在线 | 精品在线观看入口 | 国产丝袜av | 国产1区2区| 精品一二区 |