1、多功能信号发生器设计河南理工大学河南理工大学微机原理与单片机接口技术课程设计报告 2012年01月15日摘要本设计是本设计是通过软件对键盘输入的频率数值进行处理,处理结果送与D/A转换部分实现数/模转换,输出的电流再经过电流/电压转换环节,进而形成模拟电压波形,最后经过过载保护电路输出。信号发生器是一种常用的信号源,广泛地应用于电子电路、自动控制系统和教学实验等领域。目前使用的信号发生器大部分是利用分立元件组成的体积大,可靠性差,准确度低。课程设计需要各个波形的基本输出,这些波形的实现的具体步骤:方波的产生过程是通过定时器产生一个方波半周期的定时信号,每到这个信号产生,就改变一次D/A输出的数
2、据,这两个数据值由事先给定的峰峰值计算出,方波的实现是比较简单的。而三角波,则每次累加1,当达到峰值时,则改为每次累减1,这个过程需要根据峰峰值算出增加及减小的步数,以及根据频率算出步进间隔,由此间隔算出定时器重装值,以精确定时。锯齿波的产生与三角波类似,但相对简单,同样要算出步数及步进时间间隔,产生精确定时信号,不同的是锯齿波从谷值增加至峰值只是单一方向的增长。该设计使用的是STC单片机构成的发生器,可产生三角波、方波、正弦波等多种波形,波形的频率可用程序控制改变。在单片机上加外围器件独立式开关,通过开关控制波形的选择。在单片机的输出端口接DAC0832进行DA转换,再通过运放进行波形调整,
3、最后输出波形接在示波器上显示. 同时在数码管内显示该频率数值。波形的切换可以通过按键直接实现。关键词:信号发生器 单片机 三角波 锯齿波 方波1 概述1.1 系统框图1.2基本要求(1)具有产生方波、锯齿波、三角波三种周期性波形的功能。(2)输出波形的频率范围为100Hz1kHz;频率步进间隔100Hz。(3)输出波形幅度范围05V,可按步进0.1V(峰-峰值)调整。(4)具有显示输出波形的类型、周期和幅度的功能。1.3主要设计思想(一)、课设需要各个波形的基本输出。如输出三角波、锯齿波、方波。这些波形的实现的具体步骤:方波的产生过程是通过定时器产生一个方波半周期的定时信号,每到这个信号产生,
4、就改变一次D/A输出的数据,这两个数据值由事先给定的峰峰值计算出,方波的实现是比较简单的。而三角波,则每次累加1,当达到峰值时,则改为每次累减1,这个过程需要根据峰峰值算出增加及减小的步数,以及根据频率算出步进间隔,由此间隔算出定时器重装值,以精确定时。锯齿波的产生与三角波类似,但相对简单,同样要算出步数及步进时间间隔,产生精确定时信号,不同的是锯齿波从谷值增加至峰值只是单一方向的增长。(二)、整个程序的设计思想是按照精确产生波形优先的原则,能够简单的设置及显示波形类型,幅值,频率等参数。将波形输出的控制放入定时器中断里执行,在程序里执行的优先级最高,在主程序里有按键扫描,数码管扫描及相关参数
5、修改等内容。这样的程序结构使整个信号发生器能够很好的工作。2 系统总体方案及硬件设计2.1芯片功能介绍(1)DAC0832芯片介绍DAC0832为一个8位D/A转换器,单电源供电,在+5+15V范围内均可正常工作。基准电压的范围为10V,电流建立时间为1s,CMOS工艺,低功耗20mW。DAC0832的内部结构框图如下图所示DI0DI7:数据输入线,TLL电平。 ILE:数据锁存允许控制信号输入线,高电平有效。 CS:片选信号输入线,低电平有效。 WR1:为输入寄存器的写选通信号。 XFER:数据传送控制信号输入线,低电平有效。 WR2:为DAC寄存器写选通输入线。 Iout1:电流输出线。当
6、输入全为1时Iout1最大。 Iout2: 电流输出线。其值与Iout1之和为一常数。 Rfb:反馈信号输入线,芯片内部有反馈电阻.(2)、DAC0832的应用:DAC0832一是用作单极性电压输出,二是用作双极性电压输出,最后是用作程控放大器。(3)、DAC0832与8031的连接方式:DAC0832的与单片机的连接方式有三种方式:一、单缓冲二、双缓冲、三是直通方式。本程序采用的是方式一即单缓冲方式,ILE为高电平,CS、WR1、WR2、XFER为低电平。3 软件设计3.1、方波的实现过程方波的产生过程是通过定时器产生一个方波半周期的定时信号,每到这个信号产生,就改变一次D/A输出的数据,这
7、两个数据值由事先给定的峰峰值计算出。3.2、锯齿波实现过程锯齿波产生的过程是,通过事先给定的峰峰值以及D/A数据每增加1所增加的电压值算出产生这个变化范围的电压所需要增加的步数,然后以锯齿波的周期除以这个步数,算出相邻两步之间的时间间隔,用该时间间隔计算出定时器的重装值以产生定时信号。再者利用前述步数计算出D/A数据上限及下限值,当D/A数据每步自增1后增加至上限值时就回到下限值继续自增,依此产生一个锯齿波。3.3、三角波的实现过程三角波产生的过程是,通过事先给定的峰峰值以及D/A数据每增加1所增加的电压值算出产生这个变化范围的电压所需要增加的步数,然后以锯齿波的周期的一半除以这个步数,算出相
8、邻两步之间的时间间隔,用该时间间隔计算出定时器的重装值以产生定时信号。再者利用前述步数计算出D/A数据上限及下限值,当D/A数据每步自增1后增加至上限值时变数据自增为数据自减,当减至下限值时,再次改变为自增,由此产生一个三角波。4 Proteus软件仿真方波protues仿真锯齿波protues仿真三角波protues仿真5课程设计体会本次课程设计让我们熟悉了从硬件设计及调试,软件编写及调试及软硬件联合调试的全过程,也熟悉了单片机系统开发的一般过程。从中我们明白了细节决定成败的问题,在这段时间里,我们不断的碰到问题,比如说protues不能仿真,硬件电路焊接问题,焊好了不能用的问题,以及许许多
9、多的问题,在不断解决问题的同时我们明白,每一个细节都能可能会导致设计不成功。在这段时间里我们分工合作明确,遇到问题一块讨论解决,不懂的同学间相互讨论解决或是查阅资料,最终我们取得不错的成果,学到了很多以前自己没有学到的知识,收获很多。在设计过程中我们明白分工在设计中的重要作用,分工明确,可以加快时间效率,更有效的解决问题,如果让一个热人同时做很多工作,可能会有很多疏漏,时间效率也比较低。我们俩个都很感谢对方,从对方那里学习到了许多。6参考文献1川李勋、刘源主编.单片机实用教程.北京:北京航空航天大学出版社,2000.2李珍付、植桐主编.单片机原理与应用技术.北京:清华大学出版社,2003.3李
10、朝清主编.单片机原理及接口技术.北京:北京航空航天大学出版社,1999.4谭浩强主编 C程序设计.北京:清华大学出版社,2007.附1 源程序代码#include#define uint unsigned int #define uchar unsigned char #define MAIN_FOSC 11.0592#define DIV (5.0/128)uchar code table=0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d, 0x07,0x7f,0x6f, 0xBF,0x86,0xDB,0xCF,0xE6,0xED,0xFD, 0x87,0xFF,0xEF
11、; /数码管编码sbit l1=P05; /按键行列定义sbit l2=P06;sbit l3=P07;sbit h1=P36;sbit h2=P37;sbit cs=P44;sbit wr=P45;uchar frq; /频率uchar vpp; /峰峰值uchar v_h,v_l; /正负向的峰值uchar step,step_z,step_f,t_step,add_step; /步数,正向步数,负向步数,时间间隔,增值间隔uchar dac_dat; /转换数据uchar timer0_load; /定时器重装值uchar key_value;uchar out_type; /输出波形u
12、char count;bit up; /三角波增长方向变量bit change;bit key_flag;void type_set();void amp_set();void frq_set();void tri_init();void saw_init();void squ_init();void dis(uchar,uchar);void dis1(uchar,uchar);void delay(uint);void key_scan();bit key_up(); void main() uint time_count=0; /数码管交替显示控制 P4SW|=0X70; P1M1=0;
13、 P1M0=0XFF; TMOD=0X02; ET0=1; EA=1; /定时器0中断初始化 cs=1; wr=1; cs=0; wr=0; /0832初始化 dac_dat=0x80; P2=dac_dat; key_value=0; out_type=1; count=0; up=1; change=1; frq=10; vpp=60; /变量初始化 while(1) /按键扫描设置/ h1=0;l1=l2=l3=1; if(!l1) delay(10); if(!l1) type_set(); while(!l1); if(!l2) delay(10); if(!l2) amp_set(
14、); while(!l2); if(!l3) delay(10); if(!l3) frq_set(); while(!l2); h1=l1=l2=l3=1;/数码管扫描显示,频率、幅值交替/ time_count+; if(time_count100) dis1(vpp/10,1);delay(1); dis(vpp%10,2);delay(1); else if(time_countv_h) up=up; dac_dat-; dac_dat-; else P2=dac_dat; dac_dat-; if(dac_datv_h) dac_dat=v_l; else if(out_type=3
15、) count+; if(count=t_step) count=0;up=up; if(up) P2=v_h; else P2=v_l; /*三角波输出参数初始化*/void tri_init() step=(uchar)(vpp/(10*DIV)+0.5); /四舍五入求步数 if(step%2=0) step_z=step_f=step/2; else if(step%2!=0) step_z=(step-1)/2;step_f=(step+1)/2; v_h=128+step_z; v_l=128-step_f; t_step=(uchar)(100000.0/(frq*2*step)
16、+0.5); /每步间隔,单位微秒 timer0_load=(256-(uchar)(t_step*MAIN_FOSC/12+0.5); TH0=timer0_load; TL0=timer0_load;/*锯齿波输出参数初始化*/void saw_init() step=(uchar)(vpp/(10*DIV)+0.5); /四舍五入求步数 if(step%2=0) step_z=step_f=step/2; else if(step%2!=0) step_z=(step-1)/2;step_f=(step+1)/2; v_h=128+step_z; v_l=128-step_f; t_st
17、ep=(uchar)(100000.0/(frq*step)+0.5); /计数变量 timer0_load=(256-(uchar)(t_step*MAIN_FOSC/12+0.5); TH0=timer0_load; TL0=timer0_load; /*方波输出参数初始化*/void squ_init() step=(uchar)(vpp/(10*DIV)+0.5); /四舍五入求步数 if(step%2=0) step_z=step_f=step/2; else if(step%2!=0) step_z=(step-1)/2;step_f=(step+1)/2; v_h=128+ste
18、p_z; v_l=128-step_f; t_step=(uchar)(100000.0/(frq*2)/50)+0.5); /每步间隔,单位微秒 count=0; timer0_load=(256-(uchar)(50*MAIN_FOSC/12+0.5); /定时50微秒 TH0=timer0_load; TL0=timer0_load;/*波形设置*/void type_set() change=1; key_value=0; while(key_value!=6) if(!key_flag) key_flag=key_up(); /按键未弹起时需检测弹起 if(key_flag) key
19、_scan();if(key_value=4)key_flag=0; /前次按键弹起后才能再次扫描按键 if(key_value=4)out_type+;if(out_type=4) out_type=1;key_value=0; dis(out_type,1);delay(1); key_value=0;/*幅度设置*/void amp_set() bit set=1; change=1; key_value=0; while(key_value!=6) if(!key_flag) key_flag=key_up(); /按键未弹起时需检测弹起 if(key_flag) key_scan()
20、;if(key_value!=0)key_flag=0; /前次按键弹起后才能再次扫描按键 if(key_value=2) set=set;key_value=0; else if(set) if(key_value=4)vpp+=10;if(vpp99) vpp=(90+vpp%10);key_value=0; if(key_value=5)vpp-=10;if(vpp99) vpp=2;key_value=0; else if(key_value!=6) key_value=0; if(!set) if(key_value=4)vpp=(vpp/10*10)+(vpp%10)+1)%10;
21、key_value=0; if(key_value=5)vpp=(vpp/10*10)+(vpp%10)-1)%10;key_value=0; else if(key_value!=6) key_value=0; dis1(vpp/10,1);delay(1); dis(vpp%10,2);delay(1); key_value=0;/*频率设置*/void frq_set() change=1; key_value=0; while(key_value!=6) if(!key_flag) key_flag=key_up(); /按键未弹起时需检测弹起 if(key_flag) key_sca
22、n();if(key_value!=0)key_flag=0; /前次按键弹起后才能再次扫描按键 if(key_value=4)frq=frq+10;key_value=0;if(frq100) frq=100; else if(key_value=5)frq=frq-10;key_value=0;if(frq=0) frq=10; else if(key_value!=6)key_value=0; dis(0,4);delay(1); dis(0,3);delay(1); dis(frq/10%10,2);delay(1); if(frq/100) dis(1,1);delay(1); ke
23、y_value=0;/*键盘扫描函数(不等待按键弹起)*/void key_scan(void) h1=1;h2=1; l1=0;l2=0;l3=0; if(h1=0) delay(8); if(h1=0) l1=0;l2=1;l3=1; if(h1=0) key_value=1; l1=1;l2=0;l3=1; if(h1=0) key_value=2; l1=1;l2=1;l3=0; if(h1=0) key_value=3; else if(h2=0) delay(8); if(h2=0) l1=0;l2=1;l3=1; if(h2=0) key_value=4; l1=1;l2=0;l
24、3=1; if(h2=0) key_value=5; l1=1;l2=1;l3=0; if(h2=0) key_value=6; /*按键弹起检测*/bit key_up(void) bit k_up=0; h1=1;h2=1; l1=0;l2=0;l3=0; if(h1=1&h2=1) k_up=k_up; return k_up;/*1T单片机延时毫秒程序参数:i延时毫秒数*/void delay(uint i) uint j,k; for(j=i;j0;j-) for(k=850;k0;k-);/*共阴数码管显示程序参数:r显示的数字 c第几位数码管*/void dis(uchar r,uchar c) P0=(0x01(c-1); P1=tabler;/*共阴数码管显示程序(带小数点)参数:r显示的数字 c第几位数码管*/void dis1(uchar r,uchar c) P0=(0x01(c-1); P1=tabler+10;附2 系统原理图