给大家分享一个由模拟电子和数字电子技术组成的函数发生器proteus仿真,还带单片机测量电路和源程序。适合电气课程设计,有论文、proteus仿真、LED显示波形频率.
电路能输出正弦波、方波和三角波等三种波形,并可由单片机来测试准确性.
模数电函数发生器仿真原理图如下(proteus工程文件可到本帖附件中下载):
单片机测量电路仿真原理图:
包含c语言和汇编语言的单片机测量波形的程序源码:
课设论文 仿真等都有 资料很全:
单片机源程序如下:
- #include <AT89x52.h>
- #include <stdio.h>
- #include <math.h>
- #include <intrins.h>
- float f; //频率
- float p; //周期
- float sj; //闸门时间
- char idata buff[20];
- char flag=0; //频率\周期选择标志位
- char xs=0; //设置闸门时间结束后是否显示结果的标志位
- unsigned char m=0,n=0,yichu=0,fenpin; //m定时中断次数 n计数中断次数 yichu判断是定时器还是计数器溢出
- #define Key_Set P1
- #define K1 0xbf
- #define K2 0x7f
- #define NO_Set 0xff
- #define Freq 0
- #define Peri 1
- sbit B153=P2^4;
- sbit A153=P2^3;
- sbit P17=P1^7;
- sbit P16=P1^6;
- sbit P35=P3^5;
- sbit Set=P3^2;
- unsigned char LCD_Wait(void);
- void LCD_Write(bit style, unsigned char input);
- void LCD_SetDisplay(unsigned char DisplayMode);
- void LCD_SetInput(unsigned char InputMode);
- void LCD_Initial();
- void GotoXY(unsigned char x, unsigned char y);
- void Print(unsigned char *str);
- void C52_Initial();
- void Delay(unsigned int t);
- void display(float f);
- void cepin();
- void panduan();
- void timedisplay(float sj);
- void Time_Set1();
- void Time_Set2();
- void t0();
- void t1();
- /***************************************************************************
- * *
- * 模块名称: LCD1602显示程序 *
- * *
- * Author: SSP *
- * Created: 2015/12/15 *
- ***************************************************************************/
- /***********************Port Definitions***********************************/
- sbit LcdRs= P2^0;
- sbit LcdRw= P2^1;
- sbit LcdEn= P2^2;
- sfr DBPort= 0x80; //P0=0x80,P1=0x90,P2=0xA0,P3=0xB0.数据端口
- /************************内部等待函数***************************************/
- unsigned char LCD_Wait(void)
- {
- LcdRs=0; //寄存器选择输入端 1:数据 0:指令
- LcdRw=1; _nop_(); //RW:为0:写状态;为1:读状态;
- LcdEn=1; _nop_(); //使能输入端,读状态,高电平有效;写状态,下降沿有效
- LcdEn=0;
- return DBPort;
- }
- /***********************向LCD写入命令或数据*********************************/
- #define LCD_COMMAND 0 // Command
- #define LCD_DATA 1 // Data
- #define LCD_CLEAR_SCREEN 0x01 // 清屏
- #define LCD_HOMING 0x02 // 光标返回原点
- void LCD_Write(bit style, unsigned char input)
- {
- LcdEn=0;
- LcdRs=style;
- LcdRw=0; _nop_();
- DBPort=input; _nop_();//注意顺序
- LcdEn=1; _nop_();//注意顺序
- LcdEn=0; _nop_();
- LCD_Wait();
- }
- /********************设置显示模式****************************************/
- #define LCD_SHOW 0x04 //显示开
- #define LCD_HIDE 0x00 //显示关
- #define LCD_CURSOR 0x02 //显示光标
- #define LCD_NO_CURSOR 0x00 //无光标
- #define LCD_FLASH 0x01 //光标闪动
- #define LCD_NO_FLASH 0x00 //光标不闪动
- void LCD_SetDisplay(unsigned char DisplayMode)
- {
- LCD_Write(LCD_COMMAND, 0x08|DisplayMode);
- }
- /*********************设置输入模式***************************************/
- #define LCD_AC_UP 0x02
- #define LCD_AC_DOWN 0x00 // default
- #define LCD_MOVE 0x01 // 画面可平移
- #define LCD_NO_MOVE 0x00 //default
- void LCD_SetInput(unsigned char InputMode)
- {
- LCD_Write(LCD_COMMAND, 0x04|InputMode);
- }
- /******************初始化LCD******************************************/
- void LCD_Initial()
- {
- LcdEn=0;
- LCD_Write(LCD_COMMAND,0x38); //8位数据端口,2行显示,5*7点阵
- LCD_Write(LCD_COMMAND,0x38);
- LCD_SetDisplay(LCD_SHOW|LCD_NO_CURSOR); //开启显示, 无光标
- LCD_Write(LCD_COMMAND,LCD_CLEAR_SCREEN); //清屏
- LCD_SetInput(LCD_AC_UP|LCD_NO_MOVE); //AC递增, 画面不动
- }
- /************************************************************************/
- void GotoXY(unsigned char x, unsigned char y)
- {
- if(y==0)
- LCD_Write(LCD_COMMAND,0x80|x);
- if(y==1)
- LCD_Write(LCD_COMMAND,0x80|(x-0x40));
- }
- void Print(unsigned char *str)
- {
- while(*str!='\0')
- {
- LCD_Write(LCD_DATA,*str);
- str++;
- }
- }
- /**************************************************************************/
- /***************************************************************************
- * *
- * 模块名称: 频率测量程序 *
- * 主要技术指标: 测量范围:0.1Hz~4MHz,闸门时间:0.05s~10s可调。 *
- * Author: SSP *
- * Created: 2015/12/15 *
- ***************************************************************************/
- /***************************89c52初始化************************************/
- void C52_Initial()
- {
- sj=1000000.00;
- Key_Set=0xff;
- TMOD=0x51; // 01010001 T1为计数器,T0为定时器
- EA=1;
- ET0=1;
- ET1=1;
- EX0=1;
- PX0=1; //外部中断0设置为高优先级
- IT0=0; //电平触发方式
- }
- /**************************ms延时子程序*******************************************/
- void Delay(unsigned int t) //t随着数值越大,误差趋于平衡.
- {
- unsigned char i;
- while(t--)
- {
- for(i=0;i<123;i++){;}
- }
- }
- /*************************计数中断************************************************/
- void t1(void) interrupt 3 //计数器1溢出,yichu=1
- {n++;
- yichu=1;
- TH1=0;
- TL1=0;
- }
- /*************************定时中断************************************************/
- void t0(void) interrupt 1
- {
- m++;
- yichu=2; //定时器0溢出,yichu=2
- TH0=0x3c; //定时50ms
- TL0=0xb0;
- }
- /*************************频率显示************************************************/
- void Fdisplay(float f)
- {
- if(f>999400.00)
- {
- if(f<4000400.00)
- {sprintf(buff," Freq:%2.4fmHz ",(f/1000000.00));}
- }
- else
- {
- if(f>1040.00)
- {sprintf(buff," Freq:%4.2fkHz ",(f/1000.00));}
- else
- {
- if(f>0.06)
- {sprintf(buff," Freq:%3.2fHz ",f);}
- }
-
- }
- GotoXY(0,1);
- Print(buff);
- }
- /*************************周期显示************************************************/
- void Pdisplay(float p)
- {
- if(p>999400.00)
- {
- if(p<10004000.00)
- {sprintf(buff," Cycle:%2.4fs ",(p/1000000.00));}
- else
- {sprintf(buff,"error(Time or F)",p);}
- }
- else
- {
- if(p>9950.00)
- {sprintf(buff," Cycle:%4.2fms ",(p/1000.00));}
- else
- {
- if(p>0.248)
- {sprintf(buff," Cycle:%3.3fus ",p);}
- else
- {sprintf(buff,"error(Time or F)",p);}
- }
- }
- GotoXY(0,1);
- Print(buff);
- }
- /*************************测试频率*************************************************/
- void cepin()
- {
- unsigned char a;
- unsigned long js;
- m=0;
- n=0;
- TMOD=0x51;
- TH0=0x3c; //定时50ms
- TL0=0xb0;
- TH1=0;
- TL1=0;
- a=sj/50000.00;
- TCON=0x50; //启动定时器和计数器
- while(m!=a);
- TCON=0;
- js=TH1*256+n*65536+TL1;
- f=(js/(sj/1000000.00))*fenpin;
- p=sj/(js*fenpin);
- if(xs==0) //设置结束后第一次不显示结果
- {
- if(flag==Freq) Fdisplay(f);
- else Pdisplay(p);
- }
- }
- /************************判断频率**************************************************/
- void panduan()
- {
- xs=0; //设置结束后第二次循环显示结果
- B153=1; //选择16分频
- A153=0;
- yichu=0;
- TMOD=0x51;
- TH0=0xff; //定时器0 200us
- TL0=0x38;
- TH1=0xff; //计数器1 100脉冲
- TL1=0x9c;
- TR0=1; //启动定时器0和计数器1
- TR1=1;
- while(yichu==0); //如果没有溢出一直循环
- TR0=0; //已经溢出关闭定时器0和计数器1
- TR1=0;
- if(yichu==1) //计数器先溢出:在200ms内测得的脉冲过多,说明频率较高(f>500khz)
- {fenpin=16; //转为测16分频后的频率 16
- cepin();}
- else //定时器先溢出:100个脉冲的时间比较短,即频率较低,可以减少分频数
- {
- yichu=0;
- B153=0;
- A153=1;
- TH0=0xfc; //定时器0 1ms
- TL0=0x18;
- TH1=0xff; //计数器1 100个脉冲
- TL1=0x9c;
- TR0=1; //启动定时器0和计数器1
- TR1=1;
- while(yichu==0); //如果没溢出一直循环
- TR0=0; //已经溢出关闭定时器0和计数器1
- TR1=0;
- if(yichu==1) //计数器先溢出:在1ms内测得的脉冲过多,说明频率较高(1khz<f<500khz)
- {fenpin=4; //转为测4分频后的频率 4
- cepin();}
- else //定时器先溢出:100个脉冲的时间比较短,即频率较低
- { fenpin=1;
- B153=0;
- A153=0;
- cepin();}
- }
- }
- /*************************显示闸门时间************************************************/
- void timedisplay(float GTime)
- {
- sprintf(buff,"GTime=%7.0fus ",GTime);
- GotoXY(0,1);
- Print(buff);
- Delay(50);
- }
- /***************************减按键***********************************************/
- void Time_Set2()
- {
- Delay(1000);
- if(P17==1)
- { sj=sj-50000.00;
- if(sj>50000.00) timedisplay(sj);
- else
- {sj=50000.00;
- timedisplay(sj); }
- }
- else
- {while(P17==0)
- { Delay(500);
- sj=sj-500000.00;
- if(sj>50000.00) timedisplay(sj);
- else
- {sj=50000.00;
- timedisplay(sj); }
- }
- }
- }
- /***************************加按键***********************************************/
- void Time_Set1()
- {
- Delay(1000);
- if(P16==1)
- {
- sj=sj+50000.00;
- if(sj<10000000.00) timedisplay(sj);
- else
- {sj=10000000.00;
- timedisplay(sj);}
- }
- else
- {while(P16==0)
- { Delay(500);
- sj=sj+500000.00;
- if(sj<10000000.00) timedisplay(sj);
- else
- {sj=10000000.00;
- timedisplay(sj);} //按住1s快加0.5s
- }
- }
- }
- /***************************闸门时间设置*******************************************/
- void Time_Set() interrupt 0
- {
- EA=0; //防止无限中断
- Delay(100);
- if(Set==0)
- {
- Delay(1000); //判断处于哪种设置状态
- if(Set==1)
- {
- GotoXY(0,1);
- Print(" Press Button...");
- GotoXY(0,0);
- Print(" T Settings ");
- while(Set==1)
- {
- switch(Key_Set)
- {
- case K1: Time_Set1();break;
- case K2: Time_Set2();break;
- default: break;
- }
- }
- }
- else //选择测试频率或周期
- ……………………
- …………限于本文篇幅 余下代码请从51黑下载附件…………
复制代码
所有资料51hei提供下载:
模数电函数发生器.zip
(1.77 MB, 下载次数: 190)
|