1、基于单片机的多功能波形发生器设计基于MSP430单片机的多功能波形发生器设计1. 设计目的与任务本次设计旨在利用msp430单片机设计一个多功能波形发生器,并且利用lcd12864液晶屏进行当前波形的特征值的测量及显示,例如频率。2. 设计指标与技术要求(1)借助现有的单片机系统;(2)能产生正弦波、方波、三角波、锯齿波等波形;(3)各种波形频率可调,频率范围为1003000Hz;(4)正弦波输出电压为5V峰峰值,方波、三角波、锯齿波输出电压为5V(5)采用8位D/A转换器;(6)进行硬件平滑滤波;(7)编写程序并调试;(8)提供程序清单;(9)能实物演示。3. 总体设计图1.1所示是基于单片
2、机的多波形发生器的总体设计流程图。 图1.1 总体设计流程图3.1总体设计功能说明:根据设计要求,分析得本次设计需要硬件和软件两部分。硬件上,如图。键盘输入部分主要用于选择波形。键盘共设4个键,用于选择三角波、矩形波、锯齿波、正弦波4种不同的波形,。msp430单片机用来执行某一波形发生程序,向DA转换器的输入端发送数据,将其转化成模拟量,并通过运算放大器调节波形的幅值,经过滤波器的滤波,从而在输出端得到所需的波形。软件上,如图。可由硬件设计好后,再根据要求进行具体编写。程序的主要功能是:首先程序在开始后,先判断P0.0,P0.1 ,P0.2相应的波形,然后根据选择的波形输出相应的波形.程序将
3、根据要求进行调节波形.再下一步程序再判断用户继续从键盘输入要输出的波形,可以进行必要的延迟。 3.2总体电路图3.2如下所示: 图1.2 总体电路图3.3总体程序流程图3.2如下所示: 图1.3 总体程序流程图4. 总体设计4.1 msp430单片机 MSP430单片机称之为混合信号处理器,是由于其针对实际应用需求,将多个不同功能的模拟电路、数字电路模块和微处理器集成在一个芯片上,处理能力强、运算速度快,功能强大 4.2 DAC0832芯片图2.2 DAC0832芯片图DAC0832是采样频率为八位的D/A转换芯片,集成电路内有两级输入寄存器。DAC0832输出的是电流,一般要求输出是电压,所
4、以还必须经过一个外接的运算放大器转换成电压。DAC0832芯片具备双缓冲、单缓冲和直通三种输入方式,以便适于各种电路的需要(如要求多路D/A异步输入、同步转换等)。所以这个芯片的应用很广泛,关于DAC0832的引脚功能如下:D0D7:数字信号输入端。ILE:输入寄存器允许,高电平有效。CS:片选信号,低电平有效。WR1:写信号1,低电平有效。XFER:传送控制信号,低电平有效。WR2:写信号2,低电平有效。IOUT1、IOUT2:DAC电流输出端。RfB:是集成在片内的外接运放的反馈电阻。 VREF:基准电压(-1010V)。Vcc:是源电压(+5+15V)。AGND:模拟地 NGND:数字地
5、,可与AGND接在一起使用。4.3 硬件滤波电路图2.3 滤波电路图由图知,截止频率w0 =w =1/RC,即f =1/2pRC,再根据公式Q=Rf/(2Rf-R2)及RfR2=2R可算出Rf及R2的值。5. 调试实验调试过程需要使用到装有CCS的电脑、DP-51PRO单片机综合仿真实验仪以及示波器。附:程序代码:msp430控制的液晶、键盘、AD转换程序此程序未加CD4051,只能实现对单通道AD的转换1.MAIN函数部分/ 这一部分为主程序i,LCD,7289,程序详见附件#include #includeZLG7289.h#includeLCD12864.h#define uchar u
6、nsigned char#define uint unsigned intuchar dis1 = 电压值:;uchar dis2 = 上限电压:;uchar dis3=0;uchar number;uint column_num=0;#define Num_of_Results 8unsigned char index = 0;double aver=0.0;unsigned char text40;double num=0.0;unsigned int resultsNum_of_Results;void main(void) WDTCTL = WDTPW + WDTHOLD; / Sto
7、p watchdog timer P6SEL=0x00; P8DIR |= BIT1+BIT2; _enable_interrupts(); ZLG7289_initial(); LCD_Init(); LCD_Set_XY(0,0,dis1); /使能总中断 LCD_Set_XY(1,2,dis2); P6SEL |= 0x01; / Enable A/D channel A0 ADC12CTL0 = ADC12ON+ADC12SHT0_8+ADC12MSC; / Turn on ADC12, set sampling time / set multiple sample conversio
8、n ADC12CTL1 = ADC12SHP+ADC12CONSEQ_2; / Use sampling timer, set mode ADC12IE = 0x01; / Enable ADC12IFG.0 ADC12CTL0 |= ADC12ENC; / Enable conversions ADC12CTL0 |= ADC12SC; / Start conversion _bis_SR_register(LPM4_bits + GIE); _no_operation(); / For debugger #pragma vector = PORT2_VECTOR_interrupt voi
9、d PORT2_ISR(void) uchar key_data; key_data=ZLG7289_Key(); switch(key_data) case 0x00: dis30=0+48;numbercolumn_num=dis30;LCD_Set_XY(column_num,3,dis3);column_num+; break; case 0x01: dis30=1+48;numbercolumn_num=dis30;LCD_Set_XY(column_num,3,dis3);column_num+; break; case 0x02: dis30=2+48;numbercolumn_
10、num=dis30;LCD_Set_XY(column_num,3,dis3);column_num+; break; case 0x03: dis30=3+48;numbercolumn_num=dis30;LCD_Set_XY(column_num,3,dis3);column_num+; break; case 0x08: dis30=4+48;numbercolumn_num=dis30;LCD_Set_XY(column_num,3,dis3);column_num+; break; case 0x09: dis30=5+48;numbercolumn_num=dis30;LCD_S
11、et_XY(column_num,3,dis3);column_num+; break; case 0x0a: dis30=6+48;numbercolumn_num=dis30;LCD_Set_XY(column_num,3,dis3);column_num+; break; case 0x0b: dis30=7+48;numbercolumn_num=dis30;LCD_Set_XY(column_num,3,dis3);column_num+; break; case 0x10: dis30=8+48;numbercolumn_num=dis30;LCD_Set_XY(column_nu
12、m,3,dis3);column_num+; break; case 0x11: dis30=9+48;numbercolumn_num=dis30;LCD_Set_XY(column_num,3,dis3);column_num+; break; case 0x12: P8OUT=BIT1; break; case 0x13: P8OUT=BIT2; break; case 0x18: dis30=46; numbercolumn_num=dis30;LCD_Set_XY(column_num,3,dis3);column_num+;break; case 0x19: if(dis30=(9
13、+48) dis30=0+48; else if(dis30=46|dis30=95); else dis30+; column_num-;LCD_Set_XY(column_num,3,dis3);column_num+; break; case 0x1a: if(dis30=(0+48) dis30=9+48; else if(dis30=46|dis30=95); else dis30-; column_num-;LCD_Set_XY(column_num,3,dis3);column_num+; break; case 0x1b:if(column_num!=0) column_num
14、-;dis30=32; LCD_Set_XY(column_num,3,dis3); break; P2IFG=0; /退出中断前必须手动清除IO口中断标志#pragma vector=ADC12_VECTOR_interrupt void ADC12ISR (void) uchar i=0; int j; switch(_even_in_range(ADC12IV,34) case 0: break; / Vector 0: No interrupt case 2: break; / Vector 2: ADC overflow case 4: break; / Vector 4: ADC
15、timing overflow case 6: / Vector 6: ADC12IFG0 resultsindex = ADC12MEM0; / Move results index+; if (index = 8) index = 0; num=0; for(i=0;i 0;i-) _NOP(); void LCD_delayms(uint ms) uint i; while(ms-) for(i = 150;i 0;i-) _NOP(); void LCD_Write_8bits(uint W_bits) uint i,Temp_data; Clr_SCLK(); for(i=0; i8
16、; i+) Temp_data = W_bits; Temp_data = i; if(Temp_data&0x80)=0) Clr_SID(); else Set_SID(); Set_SCLK(); Clr_SCLK(); void W_1byte(uint RW, uint RS, uint W_data) uint H_data,L_data,S_ID = 0xf8; /11111RWRS0 if(RW = 0) S_ID &= 0x04; else /if(RW=1) S_ID |= 0X04; if(RS = 0) S_ID &= 0x02; else /if(RS=1) S_ID
17、 |= 0X02; H_data = W_data; H_data &= 0xf0; /屏蔽低4位的数据 L_data = W_data; /xxxx0000格式 L_data &= 0x0f; /屏蔽高4位的数据 L_data = 4; /xxxx0000格式 Set_CS(); LCD_Write_8bits(S_ID); /发送S_ID LCD_Write_8bits(H_data); /发送H_data LCD_Write_8bits(L_data); /发送L_data Clr_CS();void LCD_Set_XY(uchar x, uchar y, uchar *p) /W_1
18、byte(0,0,0x02); if(y = 0) W_1byte(0,0,(0x80+x); /在开始显示字符 if(y = 1) W_1byte(0,0,(0x90+x); if(y = 2) W_1byte(0,0,(0x88+x); if(y = 3) W_1byte(0,0,(0x98+x); while(*p != 0) W_1byte(0,1,*p+); void LCD_Set_XY_LETTERL(uchar x, uchar y, uchar p) /等号 0x3D 加号0x2B if(y = 0) W_1byte(0,0,(0x80+x); if(y = 1) W_1by
19、te(0,0,(0x90+x); if(y = 2) W_1byte(0,0,(0x88+x); if(y = 3) W_1byte(0,0,(0x98+x); W_1byte(0,1,p);void LCD_Set_XY_NUM(uchar x, uchar y, int p) uchar a=0; uchar b=0; a=p/10; b=p%10; if(y = 0) W_1byte(0,0,(0x80+x); if(y = 1) W_1byte(0,0,(0x90+x); if(y = 2) W_1byte(0,0,(0x88+x); if(y = 3) W_1byte(0,0,(0x
20、98+x); /W_1byte(0,1,a+0x30); if(y = 0) W_1byte(0,0,(0x81+x); if(y = 1) W_1byte(0,0,(0x91+x); if(y = 2) W_1byte(0,0,(0x89+x); if(y = 3) W_1byte(0,0,(0x99+x); W_1byte(0,1,b+0x30);/=*/void LCD_Init(void) uchar cmd; P8DIR |=(CS+SID+SCLK); /P6DIR = BIT1 + BIT2 + BIT3; P8OUT |= BIT3; cmd=0x30; /功能设置 8位数据,
21、基本指令 W_1byte(0,0,cmd); LCD_DelaymS(2); cmd=0x0C; /显示状态 ON,游标OFF,反白OFF W_1byte(0,0,cmd); /写指令 LCD_DelaymS(2); cmd=0x01; /清除显示 W_1byte(0,0,cmd); /写指令 LCD_DelaymS(2); cmd=0x02; /地址归位 W_1byte(0,0,cmd); /写指令 LCD_DelaymS(2); cmd=0x80; /设置DDRAM地址 W_1byte(0,0,cmd); /写指令 LCD_DelaymS(2); /延时3.ZLG7289函数部分void
22、Delay(unsigned int t) /延时 t us unsigned int i; for (i=0;it;i+) DELAY_1US;/*函数:ZLG7289_SPI_Write()功能:向SPI 总线写入1 个字节的数据参数:dat:要写入的数据*/void ZLG7289_SPI_Write(char dat) /5 unsigned char t = 8; ZLG7289_OperateIO &=ZLG7289_CLK; /clk=0 do if(dat&0x80) ZLG7289_OperateIO |=ZLG7289_DAT; /输入为1 else ZLG7289_Ope
23、rateIO &=ZLG7289_DAT; ZLG7289_OperateIO |=ZLG7289_CLK; /clk=1 dat = 1; Delay(4); ZLG7289_OperateIO &=ZLG7289_CLK; /clk=0 Delay(4); while ( -t != 0 );/*函数:ZLG7289_SPI_Read()功能:从SPI 总线读取1 个字节的数据返回:读取到的数据*/unsigned char ZLG7289_SPI_Read() unsigned char dat=0x00; unsigned char t = 8; ZLG7289_OperateIO &
24、=ZLG7289_CLK; /clk=0 /ZLG7289_DAT = 1; /读取数据之前DIO 引脚要置1 以切换到输入状态 do ZLG7289_OperateIO |=ZLG7289_CLK; /clk=1 Delay(4); dat = 1; if (ZLG7289_OperateIO_IN&ZLG7289_DAT) dat+; ZLG7289_OperateIO &=ZLG7289_CLK; /clk=0 Delay(4); while ( -t != 0 ); return dat;/*函数:ZLG7289_cmd()功能:执行ZLG7289 纯指令参数:cmd:命令字*/ /6
25、void ZLG7289_cmd(char cmd) ZLG7289_OperateIO_DIR |=ZLG7289_DAT; /output ZLG7289_OperateIO &=ZLG7289_CS; /CS=0 Delay(24); ZLG7289_SPI_Write(cmd); ZLG7289_OperateIO |=ZLG7289_CS; /CS=1 ZLG7289_OperateIO_DIR &=ZLG7289_DAT; /input 将这一位转化为输入/*函数:ZLG7289_cmd_dat()功能:执行ZLG7289 带数据指令参数:cmd:命令字dat:数据*/void ZLG7289_cmd_dat(char cmd, char dat) ZLG7289_OperateIO_DIR |=ZLG7289_DAT; /output ZLG7289_OperateIO &=ZLG7289_CS; /CS=0 Delay(24); ZLG7289_SPI_Write(cmd); Delay(14); ZLG7289_SPI_Write(dat); ZLG7289_