数字信号发生器设计Word下载.docx
《数字信号发生器设计Word下载.docx》由会员分享,可在线阅读,更多相关《数字信号发生器设计Word下载.docx(19页珍藏版)》请在冰豆网上搜索。
其中jisuan函数主要完成的功能是计算显示数字,还有给根据频率给计数器赋初值。
2.数码管输出模块:
主要用到了74LS1383-8译码器,和16个反相器,以及8个数码管。
8位数码管分别显示占空比,输出波形的类型,以及频率(包括万位,千位,百位,十位,个位)。
3.按键模块:
按键模块没有采用中断,而是利用循环不断进行中断扫描。
系统键盘实现
工作原理如下:
(1).检测键盘上是否有键按下:
将行线送入低电平,列线送入高电平。
读入P1口的状态来判别。
其具体过程如下:
P1口输出0FH,即所有行线置成高电平,所有列线置成低电平,然后将P1口状态读入与0FH比较。
如果有键按下,总会有一根行线电平被拉至低电平,从而使行输入状态不全为1。
(2).识别键盘中哪一个键按下:
确认有键按下后,保存行扫描时有键按下时的状态X。
P1口输出F0H,进行列扫描,保存列扫描状态Y,取出键值Z=X|Y.例如第一行第一列有键按下,那么行扫描读入的状态为00001110,列扫描读入的状态为11100000,最后键值Z=11101110=EEH,然后转去执行相应的服务程序。
(3).按键还需要考虑连击和去抖动的问题,为了去抖动,在按键扫描程序中如果感知有键按下,先等待10ms,然后再进行一次判断。
为了避免连击,在确认有键按下后,需要延时0.5s才响应。
这样虽然不能完全避免连击,但是一般操作不会有连击现象。
我们也考虑过利用按键抬起的边沿来触发,但是鉴于本按键的设计,这样做着实比较难,所以就用此方法代替。
4.DAC转换模块:
用到的是TLC7528芯片,此芯片利用如下原理可以直接在输出实现电流量向电压量的转变,从而省去了原本需要的基于运放的转换电路。
5.数字滤波器:
数字滤波器采用的是MAX7400芯片。
按照如上连接即可,clock输入时钟是根据INPUT频率的变化而变化的,要求是必须大于INPUT信号100倍的截止频率。
我们最后选定clock信号的频率为INPUT信号频率的120倍。
两个0.1uF的电容起到稳压的作用。
调试流程
1.根据目标编写程序,使用Proteus设计原理图并进行仿真。
在电路板上焊接基本元器件(单片机仿真器串口,DAC转换芯片,3-8译码器,滤波器芯
2.实验室以单片机仿真器为基础,将基础程序输入单片机,用示波器观察输出波形,调节内置频率,找到频率显示范围。
3.根据波形以及参数修改后的显示状况和频率范围,修改源程序,反复调试。
4.基本功能调试好后,在电路板上焊接数码管,按键以及三极管反相器器件,连接相应线路。
5.调试按键控制下示波器输出情况,根据与期望的差距修改源程序及检查电路连接,以测试及优化键控及显示输出。
6.调试完成,等待验收。
遇到的问题及解决方法
问题1:
在Proteus仿真过程中,没有TLC7528这个DAC元件,影响仿真。
解决:
在Proteus中找到了一个不带锁存器的DAC芯片,在其输出端加上锁存器,就可以实现与TCL7528相同的功能。
问题2:
波形显示设计阶段,只能达到很低的输出频率,没有超过10Hz。
经过检查,源程序中初次设计的采样点是256个,要多次调用中断,每次调用中断又占用一定机器周期,使得采样周期过长。
将采样点设为10个后,频率最大值大大增加。
牺牲的采样精度在经过滤波器后可以得到解决,依然是较漂亮的正弦波。
问题3:
80C51的剩余管脚数不能满足对8个数码管的控制。
在80C51的P3.0-P3.2口加上了3-8译码器74LS138,将输出扩展即可满足要求。
问题4:
74LS138输出为高电平有效,而实验提供的数码管是共阳极的,需要低电平输入才能控制。
在数码管阴极加上由三极管组成的8组反相器,即可为数码管提供低电平。
问题5:
数码管显示的问题,最初设计数码管显示输出8位片选和8为位选信号,但发现如果这样设计管脚不够用,所以最后选择用一个3-8译码器来减少单片机管脚的使用,但是我们有发现实验室提供的3-8译码器输出是低电平有效,而数码管恰恰又是共阴极的,所以只能再次加入反相器已达到显示效果,最后由于在显示电路搭接的过程中可能出现了些小失误,虽然在仿真中能够实现数码管的显示,但是在最后的电路中没能实现(很是遗憾)。
问题6:
在编写软件时,开始希望能够实现四种输出波型,所以中断服务程序很长,经过调试后发现如果这样,那么最后正弦波的频率收到很大限制,所以最后无奈将其他三种波形的输出放弃掉。
问题7:
在软件的编写中,为了使中断服务程序能尽量的短,从而达到更大的极限频率,想分别对clock和INPUT信号使用中断,中断的周期为24的关系,此处解释一下为什么是24倍的关系:
因为想要得到的clock和INPUT信号的频率为120倍的关系,而INPUT信号每个正弦信号周期采样10个点,而clock信号一个中期只需采样2个点,这里相差了5倍的关系,
120/5=24
为了不影响INPUT信号的正常输出,将INPUT信号的中断优先级设为最高,但是经过仿真,并没能达到预期的效果,clock信号输出正常,但是INPUT信号输出反而不正常,并不符合优先级的设定,这个问题到最后也没能找出解决的方案,所以只能采用一个中断的方法,在中断函数中在用判断的方法实现24周期的关系。
问题8:
尽管程序再优化,中断服务程序再简短,正弦波的频率也很难再高,出现了瓶颈,出现这种问题的原因在芯片上,要解决这个问题只能更换更高速的芯片。
原理图及实物照片
原理图
实物照片
程序流程图和源代码(附注释)
#include<
reg52.h>
sbitP3_0=P3^0;
sbitP3_1=P3^1;
sbitP3_2=P3^2;
sbitP3_3=P3^3;
#defineucharunsignedchar
ucharcodetab[10]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};
//0---9数字共阴极
ucharcodetab1[8]={0X73,0x73,0x73,0x76,0x79,0x38,0x38,0x3f};
//PPP.HELLO共阴极
ucharcodetosin[11]={0x80,0xca,0xf9,0xf8,0xc7,0x7c,0x30,0x04,0x09,0x3d};
//正弦波数据
ucharcount=0,b=0,c=0,d=0,e=0,i,k,tl,th;
intww=0,qw=0,bw=0,sw=5,gw=0,zkgw=0,zksw=5;
//ww为万位数字,qw为千位数字,bw为百位数字,
//sw为十位数字,gw为个位数字,zkgw为占空比个位数字,zksw为占空比十位数字
intf,m,choice=1,zk=50;
//f为频率变量,choice为波形类型选择变量,zk为占空比变量,默认占空比为50%
unsignedlongt,ff;
//t为时间变量
voiddelay10ms()//延时10ms程序
{
unsignedchari,j;
for(i=20;
i>
0;
i--)
for(j=248;
j>
j--);
}
/*1键选择发波类型,1为正弦波,2为三角波,3为方波*/
voidkey1(void)
{
if(choice<
4)
choice=choice+1;
else
choice=1;
/*个位频率调整*/
voidkey2(void)
if(gw<
9)
gw=gw+1;
else
gw=0;
/*十位频率调整*/
voidkey3(void)
{if(sw<
9)
sw=sw+1;
sw=0;
/*百位频率调整*/
voidkey4(void)
if(bw<
bw=bw+1;
bw=0;
/*千位频率调整*/
voidkey5(void)
if(qw<
qw=qw+1;
qw=0;
/*万位频率调整*/
voidkey6(void)
if(ww<
5)
ww=ww+1;
ww=0;
/*方波占空比加大*/
voidkey7(void)
{if(zk<
100)
zk=zk+1;
zk=0;
/*方波占空比减小*/
voidkey8(void)
if(zk>
=1)
zk=zk-1;
/*计算显示数字*/
voidjisuan(void)
f=1000*qw+100*bw+10*sw+gw;
ff=120*f;
t=65536-1000000/ff;
th=t/256;
tl=t%256;
ww=f/10000;
f=f%10000;
qw=f/1000;
f=f%1000;
bw=f/100;
f=f%100;
sw=f/10;
gw=f%10;
zkgw=zk%10;
zksw=zk/10;
/*显示*/
voiddisplay(void)
{/*P3_0=0;
//此处为略去的初始化
P3_1=1;
P3_2=0;
P2=tab[choice];
for(i=0;
i<
=60;
i++);
P2=0x80;
//小数点显示
P3_0=1;
P2=tab[ww];
P3_0=0;
P3_1=0;
P3_2=1;
P2=tab[qw];
*/
P3_0=1;
P3_1=0;
P3_2=1;
P2=tab[bw];
P3_0=0;
P3_1=1;
P2=tab[sw];
P2=tab[gw];
/*for(i=0;
//此处为使数码管显示连续,去掉显示占空比的两位
if(choice==3){
P2=tab[zkgw];
for(i=0;
P3_0=0;
P3_1=0;
P3_2=0;
P2=tab[zksw];
P3_0=1;
P2=0x80;
}*/}
/*键盘扫描*/
voidjudge(void)
{unsignedcharX,Y,Z;
P1=0xff;
P1=0x0f;
//先对P3置数行扫描
if(P1!
=0x0f)//判断是否有键按下
{delay10ms();
//延时,软件去干扰
=0x0f)//确认按键按下X=P1;
{TR0=0;
X=P1;
//保存行扫描时有键按下时状态
P1=0xf0;
//列扫描
Y=P1;
//保存列扫描时有键按下时状态
Z=X|Y;
//取出键值
switch(Z)//判断键值(那一个键按下)
{case0x7d:
key1();
break;
case0xee:
key2();
//对键值赋值
case0xde:
key3();
case0xbe:
key4();
case0x7e:
key5();
case0xed:
key6();
case0xdd:
key7();
case0xbd:
key8();
}
for(i=50;
i--)
delay10ms();
TR0=1;
}}}}
voidmain(void)
TMOD=0X01;
TR0=1;
ET0=1;
EA=1;
P3_3=0;
while
(1)
{jisuan();
display();
judge();
}}
voidtime0_int(void)interrupt1//中断服务程序
/*TR0=0;
/*if(choice==1)
{*/
P3_3=P3_3^1;
count++;
if(count==24)
{count=0;
P0=tosin[b];
if(b==9)
b=0;
elseb++;
}//正弦波
/*}*/
/*elseif(choice==2)//三角波之所以去掉是因为终端服务程序太长,导致频率不能到达很高
{if(c<
=128)P0=c;
elseP0=255-c;
c++;
elseif(choice==3)//方波
{k=zk*256/100;
d++;
if(d<
=k)P0=0x00;
elseP0=0xff;
elseif(choice==4)//锯齿波
{if(e<
=255)P0=255-e;
elseP0=0;
e++;
}*/
TH0=th;
TL0=tl;
/*TR0=1;
感谢老师的耐心阅读,有不对的地方还请老师斧正!