<meter id="pryje"><nav id="pryje"><delect id="pryje"></delect></nav></meter>
          <label id="pryje"></label>

          新聞中心

          EEPW首頁 > 嵌入式系統(tǒng) > 設(shè)計應(yīng)用 > FFT算法在單片機中的使用&&LCD12864驅(qū)動

          FFT算法在單片機中的使用&&LCD12864驅(qū)動

          作者: 時間:2016-11-30 來源:網(wǎng)絡(luò) 收藏
          本次創(chuàng)新基金我是要做一個簡易的頻譜儀,核心就是要進行一個FFT運算。大家知道,如果采用DSP芯片效果那是相當好的。但由于項目資金以及時間不夠等情況,我采用的是ATMEL公司的AVR單片機,這款單片機的FLASH存儲和內(nèi)存比51單片機犀利得多。

          由于采用的是12864液晶,也就是一個橫128點豎64點的一個點陣,因而采用128點FFT運算已然夠了,因為即使得到再多的數(shù)據(jù)也無法在液晶上可視化顯示出來。本文是基于128點FFT運算。
          程序如下:
          #include
          #include
          #include
          #define N 128
          #define PI 3.141592653589
          #define uchar unsigned char
          #define uint unsigned int
          typedef struct
          {
          int real;
          int img;
          }complex;

          本文引用地址:http://www.ex-cimer.com/article/201611/323722.htm


          void initw(); //初始化旋轉(zhuǎn)因子
          void bitReverse(); //比特反轉(zhuǎn)
          void FFT();

          complex x[N];
          uchar vis[N];


          void delayms(uint ms)
          {
          uint i,j;
          for(i=0;i{
          for(j=0;j<3;j++);
          }
          }
          void FFT()
          {
          int i,j,k,t,P,B,m;
          complex up,down,product;
          for (i=0;i<7;i++)
          {
          B=1<for (j=0;j{
          t=1<<(6-i);
          P=t*j;
          for (k=j;k{
          complex product;
          product.real=x[k+B].real*cos(2*PI*P/N)+x[k+B].img*sin(2*PI*P/N);
          product.img=x[k+B].real*(-1)* sin(2*PI*P/N)+x[k+B].img*cos(2*PI*P/N);
          x[k+B].real=x[k].real-product.real;
          x[k+B].img=x[k].img-product.img;
          x[k].real=x[k].real+product.real;
          x[k].img=x[k].img+product.img;
          }
          }
          }
          }

          void initw() //初始化旋轉(zhuǎn)因子
          {
          int i;
          for (i=0;ivis[i]=0;
          }

          void bitReverse() //比特反轉(zhuǎn)
          {
          int i,j=0;
          int k=0;
          int q=0;
          complex tmp3;
          for (i=0;i{
          int tmp=i,tmp2=0,j;
          for(j=0;j<7;j++)
          tmp2+=((tmp>>j)&1)*(1<<(6-j));
          if(vis[i]==0)
          {
          tmp3=x[i];
          x[i]=x[tmp2];
          x[tmp2]=tmp3;
          vis[i]=1;
          vis[tmp2]=1;
          }
          }
          }
          void main()
          {
          uchar ii,y;
          float tmp;
          for (ii=0;ii<20;ii++)
          {
          x[ii].real=3;
          x[ii].img=0;
          }
          for (ii=20;ii<128;ii++)
          {
          x[ii].real=0;
          x[ii].img=0;
          }
          initw();
          bitReverse();
          FFT();
          while(1);
          }


          上圖是8點FFT運算,按照上圖的流程所示,F(xiàn)FT運算主要有兩步,一步是比特反轉(zhuǎn),就是右邊不是按照0、1、2、3……這樣順序進行計算的,而左邊是的,兩邊的關(guān)系就是進行一個比特反轉(zhuǎn)??梢钥吹接疫?對應(yīng)二進制為000,左邊對應(yīng)二進制為000,右邊1二進制001,左邊4對應(yīng)二進制100,依次下去,可以清楚看到,對于8位FFT運算,對應(yīng)二進制有三位,而左右兩邊的關(guān)系恰巧是按照中間位進行了個反轉(zhuǎn)。
          FFT運算第二步就是乘以旋轉(zhuǎn)因子,注意的是這里是復(fù)數(shù)運算,虛部和實部都要加入運算。乘以旋轉(zhuǎn)因子后對進行加減運算得到新的值,依次下去得到最終解。


          由于單片機內(nèi)存的限制,因而對于傳統(tǒng)的FFT算法,我進行了些改進,原則就是盡量地少使用變量,一個變量可以重復(fù)的使用是最理想的了,大家可以在程序中看出。個人意見這是能節(jié)省變量最少的了,如果有好的方法,希望可以告訴我下,我的郵箱是albertvictordu@139.com,謝謝!


          下面是12864液晶驅(qū)動程序的寫法:
          LCD12864液晶,即像素為128*64的顯示液晶。它的每一行橫向一共有128個可顯示點,每一列縱向有64個,這些“點”其實也都是一個個發(fā)光二極管。它可以在一個16*16的點陣區(qū)域上顯示一個中文,也可以在一個8*16的點陣區(qū)域顯示一個非中文字符,一般稱為半寬字體。即一個中文字所占顯示面積是一個非中文字符的兩倍。

          關(guān)于驅(qū)動函數(shù)的書寫,是液晶顯示的基礎(chǔ),整個液晶驅(qū)動主要有四個函數(shù)組成:

          1、寫命令函數(shù);

          2、寫數(shù)據(jù)函數(shù);

          3、讀狀態(tài)函數(shù);

          4、讀數(shù)據(jù)函數(shù);

          這四個函數(shù)并不是必須全部寫的,具體要看你實現(xiàn)的功能,如果只是單純的顯示漢字和字符,寫命令、寫數(shù)據(jù)、讀狀態(tài)這三個函數(shù)就夠了,如過你還需要進行一些繪圖的操作,那讀數(shù)據(jù)函數(shù)也必須書寫。

          另外關(guān)于讀狀態(tài)函數(shù),其實也就是用于判忙操作,原則上每次對控制器進行讀寫操作之前,都必須進行讀寫檢測,由于單片機的操作速度慢于液晶控制器的反應(yīng)速度,因此可不進行讀寫檢測,或者只進行簡短的延時即可。因此,讀狀態(tài)函數(shù)也可以不寫,只用簡短的延時函數(shù)替換即可。

          單片機用于控制LCD的管腳主要為RS、RW和E管腳,分別的功能是RS為0時,對應(yīng)單片機訪問的是命令寄存器,為1時對應(yīng)數(shù)據(jù)寄存器;RW為1時,對應(yīng)單片機操作為讀操作,為0時對應(yīng)單片機為寫操作;E是使能信號。

          讀操作如下圖所示


          寫操作如下圖所示


          在12864液晶中,開發(fā)商將一些基本指令已經(jīng)寫入到命令寄存器中,我們調(diào)用該指令就可以完成相應(yīng)的功能。

          LCD初始化

          初始化操作如下:

          1. 芯片上電;

          2. 延時40ms以上;

          3. 復(fù)位操作:RST出現(xiàn)一個上升沿(RST=1;RST=0;RST=1;);

          4. 功能設(shè)定;

          5. 延時100us以上;

          6. 再次進行功能設(shè)定;

          7. 延時37us;

          8. 顯示開關(guān)控制;

          9. 延時100us以上;

          10. 清除顯示;

          11. 延時10ms以上;

          12. 進入點設(shè)置;

          13. 初始化結(jié)束;

          LCD液晶屏初始化過程如圖所示為:

          打點函數(shù)

          打點函數(shù)是創(chuàng)建GUI的基礎(chǔ),打點函數(shù)的書寫分為以下幾個步驟:

          1. 進入擴展模式

          2. 寫入打點地址

          3. 讀取該地址的數(shù)據(jù)

          4. 修改該地址的數(shù)據(jù)

          5. 將修改后的數(shù)據(jù)輸入LCD中

          6. 進入普通模式

          GDRAM地址分布情況,需要注意的是橫縱坐標的起始地址都是0x80,還有上下半屏的橫坐標是不一樣的,下半屏的橫坐標要加上0x08,而縱坐標跟對應(yīng)的上半屏的縱坐標是一樣的。GDRAM地址分布圖,如圖所示。

          下面的函數(shù)是12864與FFT算法的一個結(jié)合,里面設(shè)置了一個門函數(shù),12864上顯示的結(jié)果則是一個sinc函數(shù),證明結(jié)果是正確的。

          #include

          #include

          #include

          #define N 128

          #define PI 3.141592653589

          #define uchar unsigned char

          #define uint unsigned int

          #define RS (1<<4)

          #define RW (1<<5)

          #define EN (1<<6)

          //

          typedef struct

          {

          int real;

          int img;

          }complex;


          上一頁 1 2 3 下一頁

          評論


          技術(shù)專區(qū)

          關(guān)閉
          看屁屁www成人影院,亚洲人妻成人图片,亚洲精品成人午夜在线,日韩在线 欧美成人 (function(){ var bp = document.createElement('script'); var curProtocol = window.location.protocol.split(':')[0]; if (curProtocol === 'https') { bp.src = 'https://zz.bdstatic.com/linksubmit/push.js'; } else { bp.src = 'http://push.zhanzhang.baidu.com/push.js'; } var s = document.getElementsByTagName("script")[0]; s.parentNode.insertBefore(bp, s); })();