《多波形发生器的设计(共29页).doc》由会员分享,可在线阅读,更多相关《多波形发生器的设计(共29页).doc(29页珍藏版)》请在淘文阁 - 分享文档赚钱的网站上搜索。
1、精选优质文档-倾情为你奉上基于51单片机的多波形发生器1.设计原理与技术方法1.1电路工作原理分析与原理图 本次课设使用芯片PCF8591进行D/A转换,通过I2C协议(短距离通信传输协议)与单片机进行通信,当写入255时,D/A输出5V电压,因此改变写入芯片的值可以输出不同的电压值,也就可以输出不同的波形。当改变每次数据写入PCF8591的时间间隔,也就可以实现输出不同频率的波形。通过按键可以步进调节幅度,占空比和频率,并且可以通过数码管显示方波的频率,并可以通过按键直接设置频率的大小。总的系统结构框图如图1所示。图 1 系统框图总的电路图见附录,下面是各部分的电路图:(1)STC89C51
2、6使用12M的晶振,接5V电源,STC89C516的电路图如图2所示。图 2 STC89C516电路图(2)D/A转换模块,使用PCF8591的D/A转换功能,AOUT引脚接示波器显示,其电路图如图3所示。图 3 DA模块电路图(3)独立按键部分,使用的是共阴极的接法,当按键按下时,I/O口为低电平。其电路图如图4所示。图 4 独立按键电路图(4)动态数码管采用八个共阴数码管进行动态显示,利用人眼的视觉暂留,用74LS138译码器进行位选,再输出相应的段码后进行延时,就可以观察到八位数码管同时点亮,电路图如图5所示。图 5 动态数码管电路图1.2元器件选择1.2.1 单片机的选择因为 STC8
3、9C516是一种灵活性高且廉价的芯片,所以课设选择此芯片。 并且抗干扰能力强,保密性能强悍,很难被破解,单片机时钟有防外部电磁辐射功能。 1.2.2 DA芯片的选择由于课设开发板自带的D/A模块运用的PWM调制,再通过运算放大器产生模拟信号,这种方法再改变频率和幅度时不稳定,输出波形不理想,所以使用PCF8591。 PCF8591是一个单片集成、单独供电、低功耗、8-bitCMOS数据获取器件。PCF8591具有4个模拟输入、1个模拟输出和1个串行I2C总线接口。PCF8591的3个地址引脚A0,A1和A2可用于硬件地址编程,允许在同个I2C总线上接入8个PCF8591器件,而无需额外的硬件。
4、在PCF8591器件上输入输出的地址、控制和数据信号都是通过双线双向I2C总线以串行的方式进行传输。1.2.3数码管 采用八个共阴数码管,进行动态显示。数码管动态显示接口是单片机中应用最为广泛的一种显示方式之一,动态驱动是将所有数码管的8个显示笔划a,b,c,d,e,f,g,dp的同名端连在一起,另外为每个数码管的公共极COM增加位选通控制电路,位选通由各自独立的I/O线控制,当单片机输出字形码时,所有数码管都接收到相同的字形码,但究竟是哪个数码管会显示出字形,取决于单片机对位选通COM端电路的控制,所以我们只要将需要显示的数码管的选通控制打开,该位就显示出字形,没有选通的数码管就不会亮。通过
5、分时轮流控制各个数码管的的COM端,就使各个数码管轮流受控显示,这就是动态驱动。在轮流显示过程中,每位数码管的点亮时间为12ms,由于人的视觉暂留现象及发光二极管的余辉效应,尽管实际上各位数码管并非同时点亮,但只要扫描的速度足够快,给人的印象就是一组稳定的显示数据,不会有闪烁感,动态显示的效果和静态显示是一样的,能够节省大量的I/O端口,而且功耗更低。1.2.4 译码器的选择由于使用八位数码管进行动态显示,为了减少I/O口的使用,所以采用74LS138译码器,使用3个I/O口控制数码管的八位位选。74LS138的工作原理是以下四点:当一个选通端(E1)为高电平,另两个选通端(/E2)和(/E3
6、)为低电平时,可将地址端(A0、A1、A2)的二进制编码在Y0至Y7对应的输出端以低电平译出。(即输出为Y0至Y7的非)比如:A2A1A0=110时,则Y6输出端输出低电平信号。利用 E1、E2和E3可级联扩展成 24 线译码器;若外接一个反相器还可级联扩展成 32 线译码器。若将选通端中的一个作为数据输入端时,74LS138还可作数据分配器。可用在8086的译码电路中,扩展内存。2.系统软件设计2.1主程序流程图程序采用模块化编程,分为main.c和iic.c两个文件。iic.c文件内是I2C通信协议和PCF8591写入数据函数的编程;main.c文件内是全部功能实现的程序,即显示各种波形,
7、调整幅度、频率、占空比,显示频率等功能。程序流程图如图6所示。图 6 主程序流程图2.2主程序的源程序代码main.c/*74HC138 A接P22 B接P23 C接P24按键接P1*/#include reg51.h /#include iic.h#include math.h#define u8 unsigned char#define u16 unsigned int#define GPIO_KEY P1sbit Wei_A=P22;sbit Wei_B=P23;sbit Wei_C=P24;u8 code smg_du=0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7
8、D,0x07,0x7F,0x6F,0x00; /0-9 /u8 idata zhengxuan_table128;u8 code zhengxuan_table=0x00,0x00,0x00,0x00,0x00,0x01,0x02,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0d,0x0e,0x10,0x11,0x13,0x15,0x16,0x18,0x1a,0x1c,0x1e,0x20,0x22,0x25,0x27,0x29,0x2b,0x2e,0x30,0x33,0x35,0x38,0x3a,0x3d,0x40,0x43,0x45
9、,0x48,0x4c,0x4e,0x51,0x55,0x57,0x5a,0x5d,0x60,0x63,0x66,0x69,0x6c,0x6f,0x72,0x76,0x79,0x7c,0x80,0x80,0x83,0x86,0x89,0x8d,0x90,0x93,0x96,0x99,0x9c,0x9f,0xa2,0xa5,0xa8,0xab,0xae,0xb1,0xb4,0xb7,0xba,0xbc,0xbf,0xc2,0xc5,0xc7,0xca,0xCC,0xcf,0xd1,0xd4,0xD6,0xd8,0xda,0xdd,0xDF,0xe1,0xe3,0xe5,0xE7,0xf9,0xea
10、,0xec,0xee,0xef,0xf1,0xf2,0xF4,0xf5,0xf6,0xf7,0xf8,0xF9,0xfa,0xfb,0xfc,0xfd,0xfD,0xfe,0xff,0xfe,0xff,0xff,0xff,0xff,0xff,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFE,0xfd,0xfd,0xFC,0xfb,0xfa,0xf9,0xf8,0xF7,0xf6,0xf5,0xF4,0xf2,0xF1,0xef,0xee,0xec,0xea,0xe9,0xe7,0xe5,0xe3,0xe1,0xde,0xdd,0xda,0xd8,0xd6,0xd4,0xd1
11、,0xcf,0xcc,0xca,0xc7,0xc5,0xc2,0xBF,0xbc,0xba,0xb7,0xb4,0xb1,0xae,0xab,0xA8,0xa5,0xA2,0x9F,0x9C,0x99,0x96,0x93,0x90,0x8d,0x89,0x86,0x83,0x80,0x80,0x7c,0x79,0x78,0x72,0x6f,0x6c,0x69,0x66,0x63,0x60,0x5d,0x5a,0x57,0x55,0x51,0x4e,0x4c,0x48,0x45,0x43,0x40,0x3d,0x3a,0x38,0x35,0x33,0x30,0x2E,0x2b,0x29,0x27
12、,0x25,0x22,0x20,0x1e,0x1c,0x1A,0x18,0x16,0x15,0x13,0x11,0x10,0x0E,0x0D,0x0B,0x0a,0x09,0x08,0x07,0x06,0x05,0x04,0x03,0x02,0x02,0x01,0x00,0x00,0x00,0x00,0x00,0x00;u8 inform_display8;u8 set_display8;u8 AM=255;/波形幅度 255对应5vu8 U_out=10;u16 T=5000;/一半周期5000u16 T_count=0;/周期计数u16 F = 1;/频率初始1hzu16 mid_squr
13、e=2500 ;u16 T_temp;u16 C_temp;u8 Fig_choice=0;/ 1-方波 2-三角波u8 tri_temp=0;u8 ti_temp=0;u8 zx_temp=0;u8 function=0;sbit PWM = P21;#define NO_KEY 0xff /无按键按下#define KEY_STATE0 0 /判断按键按下#define KEY_STATE1 1 /确认按键按下#define KEY_STATE2 2 /释放unsigned char Key_Scan() static unsigned char key_state=KEY_STATE0;
14、 u8 key_value=0,key_temp;/GPIO_KEY=0xff;key_temp=GPIO_KEY; switch(key_state) case KEY_STATE0: if(key_temp!=NO_KEY) key_state=KEY_STATE1; break; case KEY_STATE1: if(key_temp=NO_KEY) key_state=KEY_STATE0; else switch(key_temp) case 0xFE: key_value=1;break; case 0xFD: key_value=2;break; case 0xFB: key_
15、value=3;break; case 0xF7: key_value=4;break; case 0xEF: key_value=5;break; case 0xDF: key_value=6;break; case 0xBF: key_value=7;break; case 0x7F: key_value=8;break; key_state=KEY_STATE2; break; case KEY_STATE2: if(key_temp=NO_KEY) key_state=KEY_STATE0; break; return key_value;void Timer0Init(void)/1
16、毫秒12.000MHzTMOD &= 0xF1;/设置定时器模式TL0 = 0x18;/设置定时初值TH0 = 0xFC;/设置定时初值/TF0 = 0;/清除TF0标志ET0=1;EA=1;TR0 = 1;/定时器0开始计时void Timer1Init(void)/100微秒12.000MHzTMOD &= 0x1F;/设置定时器模式TL1 = 0x9C;/设置定时初值TH1 = 0xFF;/设置定时初值/TF0 = 0;/清除TF0标志ET1=1;EA=1;TR1 = 1;/定时器1开始计时bit key_flag;u8 key_dis=0;u8 test=0;bit high_flag
17、;bit low_flag;bit DIR=1;bit set_flag;bit click_flag;void main(void)u8 key_val=NO_KEY;float a=0;Timer0Init(); /1msTimer1Init();/1uswhile(1)if(function=1)inform_display0=0x40;inform_display1=0x71;inform_display2=0x40;inform_display3=0;inform_display4=0;inform_display7=smg_duF%10;if(F/100=0)inform_disp
18、lay5=0;elseinform_display5=smg_duF/100;if(F%100/10=0)&(F/100=0)inform_display6=0;elseinform_display6=smg_duF%100/10;else if(function=2)set_display0=0x40;set_display1=0x71;set_display2=0x40;set_display3=0;set_display4=0;if(click_flag)if(F/100=0)set_display5=0;elseset_display5=smg_duF/100;if(F%100/10=
19、0)&(F/100=0)set_display6=0;elseset_display6=smg_duF%100/10;set_display7=smg_duF%10;elseset_display4=0;set_display5=0;set_display6=0;set_display7=0; if(key_flag) /10ms key_flag=0; key_val=Key_Scan(); switch(key_val) case 1:/调节幅度+test=1;if(AM=255)AM=0;AM=AM+6; break; case 2:/调节频率+test=2;if(function=0)
20、F=F+100;T=5000.0/F;mid_squre=T/2.0;if(function=2)F=F+50;break;case 3:/占空比+test=3;mid_squre=mid_squre+T/100;break;case 4:/波形选择test=4;Fig_choice+;if(Fig_choice=5)Fig_choice=0;break; case 5:/调节幅度- test=5; if(AM=0)AM=255;AM=AM-6; break;case 6:/调节频率-test=6;if(function=0)F=F-50;T=5000.0/F;a=T;mid_squre=a/
21、2.0;if(function=2)F=F-50;break;case 7:test=7;mid_squre=mid_squre-T/100;break;case 8:/设置test=8;function+;if(function=3)function=0;T=5000.0/F;mid_squre=T/2.0;/set_flag=!set_flag;break; /方波 EA=0;if(Fig_choice=0)if(high_flag)DAC_write(AM);if(low_flag)/EA=0;DAC_write(0);/EA=1;/三角波if(Fig_choice=1)if(DIR=1
22、)tri_temp+;/EA=0;DAC_write(tri_temp); /EA=1;if(DIR=0)tri_temp-;/EA=0;DAC_write(tri_temp); /EA=1;if(tri_temp=AM)DIR=0;if(tri_temp=0)DIR=1;/锯齿波if(Fig_choice=2)tri_temp+;/EA=0;DAC_write(tri_temp);/EA=1;if(tri_tempAM)tri_temp=0;/正弦波if(Fig_choice=3) zx_temp+;/EA=0;DAC_write(zhengxuan_tablezx_temp); /通过PC
23、F8591输出正弦波/EA=1;/if(zx_temp128)zx_temp=0;/梯形波if(Fig_choice=4)if(DIR=1)&(ti_temp=0)tri_temp+;/EA=0;DAC_write(tri_temp);/EA=1;if(DIR=0)tri_temp-;/EA=0;DAC_write(tri_temp); /EA=1;if(tri_temp=AM)ti_temp+;/EA=0;DAC_write(tri_temp);/EA=1;if(ti_temp=100)/梯形波高电平时间ti_temp=0;DIR=0;if(tri_temp=0)DIR=1; EA=1; v
24、oid timer0() interrupt 1 using 1 static int key_count=0,smg_count=0,i=0,count_1s=0;/tri_bet为每个数据的时间间隔TL0 = 0x18;/设置定时初值TH0 = 0xFC;/设置定时初值key_count+;smg_count+;count_1s+;/T_count+;if(count_1s=1000)count_1s=0;click_flag=!click_flag;if(key_count=10)/10ms key_count=0; key_flag=1;if(smg_count=1)/1mssmg_c
25、ount=0;P0=0x00;/消隐switch(i) /位选,选择点亮的数码管,case(0):Wei_A=0;Wei_B=0;Wei_C=0; break;/显示第0位case(1):Wei_A=1;Wei_B=0;Wei_C=0; break;/显示第1位case(2):Wei_A=0;Wei_B=1;Wei_C=0; break;/显示第2位case(3):Wei_A=1;Wei_B=1;Wei_C=0; break;/显示第3位case(4):Wei_A=0;Wei_B=0;Wei_C=1; break;/显示第4位case(5):Wei_A=1;Wei_B=0;Wei_C=1; b
26、reak;/显示第5位case(6):Wei_A=0;Wei_B=1;Wei_C=1; break;/显示第6位case(7):Wei_A=1;Wei_B=1;Wei_C=1; break;/显示第7位if(function=1)P0=inform_displayi;/发送段码else if(function=2)P0=set_displayi;elseP0=0;i+;if(i=8) i=0;void timer1() interrupt 3TL1 = 0x9C;/设置定时初值TH1 = 0xFF;/设置定时初值T_count+;if(Fig_choice=0)if(T_countmid_sq
27、ure)high_flag=1;low_flag=0; /DAC_write(255);else if(T_countT)high_flag=0;low_flag=1; / DAC_write(0);elseT_count=0;2.3 I2C数据传输流程图I2C通信协议的启动信号是SDA的下降沿,终止信号是SDA的上升沿。在SCL的低电平的时候改变数据,高电平的时候保持数据不变。其流程图如图7。图 7 I2C数据传输流程图2.4 I2C数据传输源程序#include reg52.h#include intrins.h#define somenop _nop_();_nop_();_nop_()
28、;_nop_();_nop_(); #define SlaveAddrW 0xA0#define SlaveAddrR 0xA1/总线引脚定义sbit SDA = P21; /* 数据线 */sbit SCL = P20; /* 时钟线 */总线启动条件void IIC_Start(void)SDA = 1;SCL = 1;somenop;SDA = 0;somenop;SCL = 0;/总线停止条件void IIC_Stop(void)SDA = 0;SCL = 1;somenop;SDA = 1;/应答位控制void IIC_Ack(bit ackbit)if(ackbit) SDA =
29、0;else SDA = 1;somenop;SCL = 1;somenop;SCL = 0;SDA = 1; somenop;/等待应答bit IIC_WaitAck(void)SDA = 1;somenop;SCL = 1;somenop;if(SDA) SCL = 0;IIC_Stop();return 0;else SCL = 0;return 1;/通过I2C总线发送数据void IIC_SendByte(unsigned char byt)unsigned char i;for(i=0;i8;i+) if(byt&0x80) SDA = 1;else SDA = 0;somenop
30、;SCL = 1;byt = 1;somenop;SCL = 0;/从I2C总线上接收数据unsigned char IIC_RecByte(void)unsigned char da;unsigned char i;for(i=0;i8;i+) SCL = 1;somenop;da = 1;if(SDA) da |= 0x01;SCL = 0;somenop;return da;void DAC_write(unsigned char dat)IIC_Start();IIC_SendByte(0x90);IIC_WaitAck();IIC_SendByte(0x40);IIC_WaitAck
31、();IIC_SendByte(dat);IIC_WaitAck();IIC_Stop();3.实验结果与分析3.1 实验结果将程序下载到单片机开发板上,示波器接PCF8591模块的UOUT引脚,初始状态下,示波器显示方波,可以通过KEY1/KEY5调节幅度, KEY2/KEY6调节频率,KEY3/KEY7调节占空比.按下KEY4,每按一下,波形变化一次,循环显示正弦波、三角波、锯齿波、方波、梯形波,如下面图片所示。第一次按下KEY8显示方波频率信息,再次按下,数码管闪烁,表示此时可以通过按键 KEY2/KEY6设置任意频率,设置完成后,再次按下KEY8,保存设置的频率,退出数码管显示界面,数
32、码管全部熄灭,数码管显示部分如下图13。实物连接图如图14。图 8 方波图 9 三角波图 10 锯齿波图 11正弦波图 12 梯形波图 13 频率显示界面图 14 实物连接图3.2实验中遇到的问题 (1)在设计独立按键部分时,出现一段时间按键有效,一段时间按键无效,一直研究是不是程序出现问题,后来查看原理图的时候才找到原因。因为独立按键连接的是P1口,而P1.7在开发板上连接着74HC165,所以把对应的跳帽拔掉后,就可以正常使用。 (2)在设计数码管显示时,一开始数码管闪烁着显示,于是加快扫描时间,结果不闪烁而变得暗淡,又放慢一些扫描时间,最终调整完成。 (3)在设计波形时,波形的算法设计没
33、有问题,可是就不能显示出正常的波形,后来分析后找到原因:需要连续的产生波形,就需要在产生波形的时候,不受其他中断的影响。因此在产生波形的时候将所有的中断关闭。 (4)在设计步进调整频率时,按照要求步进100HZ调整,设计的方波初始频率为1HZ,步进增加100HZ后,可以正常得到大约100HZ的方波,但是再增加100HZ后,方波的频率还是100HZ左右,调节的范围只能是0-100HZ左右。分析其主要原因是定时器T1使用的是100us计时,当设置200HZ时,计数的精度达不到。3.3 程序设计的优点 (1)程序中没有使用延时函数,极大地提高了单片机的实时性,有效性。按键检测和动态数码管的显示都使用
34、的是定时器计时,到达规定时间时,对按键和数码管扫描。 (2)按键没有使用传统的延时消抖的方式,而是采用状态机的方式,一共三个状态,即判断按键按下、确定按下和按键松开。这种方式避免了按键一直按下其他程序等待的情况,更加实用。 (3)数码管显示的时候,可以将用不到的位熄灭,要改变频率时,数码管闪烁显示,还显示了频率的标识“-F-”。4. 课程设计工作记录4.1 时间安排 6月19日 确定设计课题并讲解相关注意问题,分发实验板; 6月20日 查找相关资料,并了解相关模块电路图及工作原理,设计初步流程图; 6月21日 根据相关模块的原理,设计总体的流程图,然后查找相关资料进行基本要求的设计;6月22日
35、至6月26日 对应基本要求,逐步完成基于51单片机波形发生设计;6月27日至7月3日 完成拓展要求,并完善程序;7月4日课设结果验收,开始撰写实验报告,并进一步完善实验设计;7月5日至7月6日 完成课程实验报告并进行验收,递交实验板,递交修改后的实验报告。4.2课程设计的心得与体会经过三周的学习和探索,完成了基于51单片机的多波形发生器设计。一开始,使用的是实验板上自带的由运算放大器组成的D/A转换,利用PWM的脉冲宽度不同,产生不同的电压幅值。但是在设计过程中,改变频率的时候,时序很难实现,误差特别大,因此放弃此方法。最终使用PCF8591模块的D/A转换,实现效果良好。在数码管显示上面,经过调整更加符合人类的观感,即频率最大可以达到三位数,但是当显示两位数的时候,第三位数码管应该处于熄灭状态,而且再修改频率的时候,还能够使数码管闪烁,更加实用。 单片机是在我们的生活应用中十分广泛,首先要学好C语言的编程和应用,再对单片机的硬件结构进行掌握,加强自己的动手能力,不断在实践中学习,掌握新的知识。这次的课设让我意识到了硬件资料的重要性,必须详细了解硬件的功能结构,才能够游刃有余的运用它,不然就会出现很多摸不着头绪的问题。三周的课程设计实习即将结束,这是第一次将单片机课本上的理论知识付诸于实践,为以后做项目奠定了基础,最后感谢老师三周的辛勤指导与陪伴。附录1专心-专注-专业
限制150内