您的位置 首页 电源

FFT算法在单片机中的运用&&LCD12864驱动

本次创新基金我是要做一个简易的频谱仪,核心就是要进行一个FFT运算。大家知道,如果采用DSP芯片效果那是相当好的。但由于项目资金以及时间

本次立异基金我是要做一个简易的频谱仪,中心便是要进行一个FFT运算。咱们知道,假如选用DSP芯片作用那是相当好的。但因为项目资金以及时刻不行等状况,我选用的是ATMEL公司的AVR单片机,这款单片机的FLASH存储和内存比51单片机尖锐得多。

因为选用的是12864液晶,也便是一个横128点竖64点的一个点阵,因而选用128点FFT运算已然够了,因为即便得到再多的数据也无法在液晶上可视化显现出来。本文是根据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;

void initw(); //初始化旋转因子
void bitReverse(); //比特回转
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() //初始化旋转因子
{
int i;
for (i=0;ivis[i]=0;
}

void bitReverse() //比特回转
{
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运算,依照上图的流程所示,FFT运算主要有两步,一步是比特回转,便是右边不是依照0、1、2、3……这样次序进行核算的,而左面是的,两头的联系便是进行一个比特回转。能够看到右边0对应二进制为000,左面对应二进制为000,右边1二进制001,左面4对应二进制100,顺次下去,能够清楚看到,关于8位FFT运算,对应二进制有三位,而左右两头的联系恰巧是依照中间位进行了个回转。
FFT运算第二步便是乘以旋转因子,留意的是这里是复数运算,虚部和实部都要参加运算。乘以旋转因子后对进行加减运算得到新的值,顺次下去得到终究解。

因为单片机内存的约束,因而关于传统的FFT算法,我进行了些改善,准则便是尽量地少运用变量,一个变量能够重复的运用是最理想的了,咱们能够在程序中看出。个人定见这是能节约变量最少的了,假如有好的办法,期望能够告诉我下,我的邮箱是albertvictordu@139.com,谢谢!

下面是12864液晶驱动程序的写法:
LCD12864液晶,即像素为128*64的显现液晶。它的每一行横向一共有128个可显现点,每一列纵向有64个,这些“点”其实也都是一个个发光二极管。它能够在一个16*16的点阵区域上显现一个中文,也能够在一个8*16的点阵区域显现一个非中文字符,一般称为半宽字体。即一个中文字所占显现面积是一个非中文字符的两倍。

关于驱动函数的书写,是液晶显现的根底,整个液晶驱动主要有四个函数组成:

1、写指令函数;

2、写数据函数;

3、读状况函数;

4、读数据函数;

这四个函数并不是有必要悉数写的,详细要看你完结的功用,假如仅仅单纯的显现汉字和字符,写指令、写数据、读状况这三个函数就够了,如过你还需求进行一些绘图的操作,那读数据函数也有必要书写。

别的关于读状况函数,其实也便是用于判忙操作,准则上每次对操控器进行读写操作之前,都有必要进行读写检测,因为单片机的操作速度慢于液晶操控器的反应速度,因而可不进行读写检测,或许只进行简略的延时即可。因而,读状况函数也能够不写,只用简略的延时函数替换即可。

单片机用于操控LCD的管脚主要为RS、RW和E管脚,别离的功用是RS为0时,对应单片机拜访的是指令寄存器,为1时对应数据寄存器;RW为1时,对应单片机操作为读操作,为0时对应单片机为写操作;E是使能信号。

读操作如下图所示

写操作如下图所示

在12864液晶中,开发商将一些根本指令现已写入到指令寄存器中,咱们调用该指令就能够完结相应的功用。

LCD初始化

初始化操作如下:

1. 芯片上电;

2. 延时40ms以上;

3. 复位操作:RST呈现一个上升沿(RST=1;RST=0;RST=1;);

4. 功用设定;

5. 延时100us以上;

6. 再次进行功用设定;

7. 延时37us;

8. 显现开关操控;

9. 延时100us以上;

10. 铲除显现;

11. 延时10ms以上;

12. 进入点设置;

13. 初始化完毕;

LCD液晶屏初始化进程如图所示为:

打点函数

打点函数是创立GUI的根底,打点函数的书写分为以下几个过程:

1. 进入扩展形式

2. 写入打点地址

3. 读取该地址的数据

4. 修正该地址的数据

5. 将修正后的数据输入LCD中

6. 进入一般形式

GDRAM地址散布状况,需求留意的是横纵坐标的开始地址都是0x80,还有上下半屏的横坐标是不相同的,下半屏的横坐标要加上0x08,而纵坐标跟对应的上半屏的纵坐标是相同的。GDRAM地址散布图,如图所示。

下面的函数是12864与FFT算法的一个结合,里边设置了一个门函数,12864上显现的成果则是一个sinc函数,证明成果是正确的。

#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;

声明:本文内容来自网络转载或用户投稿,文章版权归原作者和原出处所有。文中观点,不代表本站立场。若有侵权请联系本站删除(kf@86ic.com)https://www.86ic.net/dianyuan/318079.html

为您推荐

联系我们

联系我们

在线咨询: QQ交谈

邮箱: kf@86ic.com

关注微信
微信扫一扫关注我们

微信扫一扫关注我们

返回顶部