基于51单片机的函数信号发生器

基于51单片机函数信号发生器

(仿真+程序+原理图+设计报告)

功能介绍

具体功能:

1.LCD1602液晶显示波形种类和频率值(10-100HZ);

2.按键设置波形种类和设定频率步进值;

3.电位器器改变振幅(0V-3.5V稳定);

4.本设计可产生正弦波、锯齿波、三角波、矩形波;

5.有四个指示灯分别指示发出的是哪种波形,方便明了;

​演示视频:

基于51单片机的函数信号发生器 

添加图片注释,不超过 140 字(可选)

程序

#include<reg52.h>					   //包含头文件
#include<intrins.h>
#define uchar unsigned char			   //宏定义
#define uint unsigned int
/***公众号:木子单片机****/
sbit s1=P3^5; 						   //定义按键的接口
sbit s2=P3^6;
sbit s3=P3^7;
sbit s4=P3^4;

sbit led0=P3^0;							//定义四个LED,分别表示不同的波形
sbit led1=P3^1;
sbit led2=P3^2;
sbit led3=P3^3;
									   
sbit lcdrs=P2^7;					   //液晶控制引脚,还有一个控制脚是RW,因为我们只需要向液晶里写数据系那是就好了,所以,我们直接将RW引脚接地
sbit lcden=P2^6;

char num,boxing,u;					   //定义全局变量
uchar pinlv=100,bujin=1,bujin1=1;		   //频率初始值是10Hz,步进值默认是0.1,显示步进值变量
uchar code table[]="0123456789";		//定义显示的数组
uchar code table1[]="Fout=     Wave form:";	//初始化显示字符
unsigned int m;				   //定义变量 m
int a,b,h,num1;							//定义全局变量

//自定义字符
uchar code zifu[]={		   //此数组内数据为液晶上显示波形符号的自定义字符
						0x0e,0x11,0x11,0x00,0x00,0x00,0x00,0x00,
						0x00,0x00,0x00,0x00,0x11,0x11,0x0e,0x00,	  //正弦波	   0  1

						0x00,0x07,0x04,0x04,0x04,0x04,0x1c,0x00,
						0x00,0x1c,0x04,0x04,0x04,0x04,0x07,0x00,	  //矩形波	   2  3

						0x00,0x01,0x02,0x04,0x08,0x10,0x00,0x00,
						0x00,0x10,0x08,0x04,0x02,0x01,0x00,0x00,	  //三角波	   4  5

						0x00,0x01,0x03,0x05,0x09,0x11,0x00,0x00,  	  //锯齿波	   6
};
uchar code sin[64]={	   //此数组内的数据为,da输出对应电压值对应的数字量,0是0V,255是5V 
135,145,158,167,176,188,199,209,218,226,234,240,245,249,252,254,254,253,251,247,243,237,230,222,213,204,193,182,170,158,
146,133,121,108,96,84,72,61,50,41,32,24,17,11,7,3,1,0,0,2,5,9,14,20,28,36,45,55,66,78,90,102,114,128
};					  //正弦波取码
uchar code juxing[64]={		//一个周期是采样64个点, 所以数组内是64个数据
255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
};					  //矩形波取码

uchar code sanjiao[64]={
0,8,16,24,32,40,48,56,64,72,80,88,96,104,112,120,128,136,144,152,160,168,176,184,192,200,208,216,224,232,240,248,
248,240,232,224,216,208,200,192,184,176,168,160,152,144,136,128,120,112,104,96,88,80,72,64,56,48,40,32,24,16,8,0
};						//三角波取码
uchar code juchi[64]={
0,4,8,12,16,20,24,28,32,36,40,45,49,53,57,61,65,69,73,77,81,85,89,93,97,101,105,109,113,117,121,125,130,134,138,142,
146,150,154,158,162,166,170,174,178,182,186,190,194,198,202,206,210,215,219,223,227,231,235,239,243,247,251,255
};					  //锯齿波取码

void delay(uint xms)	 //延时函数
{
	int a,b;
	for(a=xms;a>0;a--)
		for(b=110;b>0;b--);
}
void write_com(uchar com)		//写命令函数
{
	lcdrs=0;
	P0=com;	
	delay(1);
	lcden=0;
	delay(1);						 			  
	lcden=1;
}

void write_date(uchar date)		//写数据函数
{
	lcdrs=0;
	P0=date;
	delay(1);
	lcden=0;
	delay(1);
	lcden=1;
}

//自定义字符集
void Lcd_ram()      
{ 
	uint i,j,k=0,temp=0x04; 
	for(i=0;i<7;i++)
	{
	   for(j=0;j<8;j++)
	   {
	    write_com(temp+j);
	    write_date(zifu[k]);
	    k++;
	   }
	   temp=temp+8;
	}
}

void init_lcd()					//初始化函数
{
	uchar i;								  
	lcden=0;					//默认开始状态为关使能端,见时序图  
	Lcd_ram();
	write_com(0x01);			//显示清屏,将上次的内容清除,默认为0x01.
	write_com(0x0f);
	write_com(0x38);			//显示模式设置,默认为0x38,不用变。 
	write_com(0x0c);			//显示功能设置0x0f为开显示,显示光标,光标闪烁;0x0c为开显示,不显光标,光标不闪
	write_com(0x06);			//设置光标状态默认0x06,为读一个字符光标加1. 
	write_com(0x80);			//设置初始化数据指针,是在读指令的操作里进行的
	for(i=10;i<20;i++)			   //显示初始化
	{
		write_date(table1[i]);		   //显示第一行字符
	}
	write_com(0x80+40);			   //选择第二行
	for(i=0;i<9;i++)
	{
		write_date(table1[i]);		   //显示第二行字符
	}
	write_com(0x80+10);				   //选择第一行第十个位置
	write_date(0);
	write_date(1);
	write_date(0);
	write_date(1);
	write_date(0);
	write_date(1);					   //显示自定义的波形图案
	write_com(0x80+40+9);		   //选择第二行第九个位置
	write_date(' ');
	write_date('1');
	write_date('0');
	write_date('.');
	write_date('0');
	write_date('H');
	write_date('z');				   //显示初始的频率值
}
void initclock()			   //定时器初始化函数
{
	TMOD=0x10;				   //定时器的工作方式
	TH0=a;
	TL0=b;					   //定时器赋初值
	EA=1;					   //打开中断总开关
	ET0=1;					   //打开定时器允许中断开关
	TR0=1;					   //打开定时器定时开关
}
void display()				   //显示函数
{
	uchar qian,bai,shi,ge;	   //定义变量用于显示
	qian=pinlv/1000;		   //将频率值拆成一位的数据,将数据除以1000,得到的商是一位数,赋值给qian
	bai=pinlv%1000/100;		   //将频率除以1000的余数再除以100就得到了频率的百位,赋值给bai
	shi=pinlv%1000%100/10;	   //同上,得到频率的十位
	ge=pinlv%1000/100%10;
	write_com(0x80+40+9); //选中第二行第九个位置

   	if(qian==0)				   //千位如果为0
	write_date(' ');		   //不显示
	else					   //千位不为0
	write_date(table[qian]);   //正常显示千位
	if(qian==0&&bai==0)		   //千位和百位都为0
	write_date(' ');		   //百位不显示
	else					   //不都为0
	write_date(table[bai]);	   //百位正常显示
	write_date(table[shi]);	   //显示十位数
	write_date('.');		   //显示小数点
	write_date(table[ge]);	   //显示个位
	write_date('H');		   //显示频率的单位Hz
	write_date('z');
	if(boxing==0)			   //判断波形为正弦波
	{
		write_com(0x80+10);	   //选中一行频率图案位置
		write_date(0);		   //显示正弦波图案
		write_date(1);
		write_date(0);
		write_date(1);
		write_date(0);
		write_date(1);
		led3=1;
		led0=0;					//点亮正弦波指示灯
	}
	if(boxing==1)				//注释同上
	{
		write_com(0x80+10);
		write_date(2);
		write_date(3);
		write_date(2);
		write_date(3);
		write_date(2);
		write_date(3);
		led0=1;
		led1=0;
	}


	if(boxing==2)
	{
		write_com(0x80+10);
		write_date(4);
		write_date(5);
		write_date(4);
		write_date(5);
		write_date(4);
		write_date(5);
		led1=1;
		led2=0;
	}
	if(boxing==3)
	{
		write_com(0x80+10);
		write_date(6);
		write_date(6);
		write_date(6);
		write_date(6);
		write_date(6);
		write_date(6);
		led2=1;
		led3=0;
	}
}
void keyscan()					//频率调节键盘检测函数
{
	if(s1==0)					//加按键是否按下
	{	 
		EA=0;					//关闭中断
		delay(2);			    //延时去抖
		if(s1==0)				//再次判断
		{
			while(!s1);			//按键松开
			pinlv+=bujin;		//频率以步进值加
			if(pinlv>1000)		//最大加到100Hz
			{
				pinlv=100;		//100Hz
			}
			display();			//显示函数
			m=65536-(15000/pinlv);//计算频率
/*频率值最小是10Hz,pinlv的值是100(因为要显示小数点后一位),150000/100=1500,这个1500就是定时器需要计时的,单位是us,65536-1500得到的是定时器的初值,
先不管初值,先看定时时间,1500us,一个波形的周期是由64个定时组成的,所以,一个波形周期就是64*1500us=96000,也就是96ms,约等
于100ms,也就是10Hz的频率*/
			a=m/256;			//将定时器的初值赋值给变量
			b=m%256;
			EA=1;				//打开中断总开关
		}
	}
	if(s2==0)					//减按键按下
	{	 
		
		delay(5);
		if(s2==0)
		{
			EA=0;	
			while(!s2);
			pinlv-=bujin;		   //频率以步进值减
			if(pinlv<100)
			{
				pinlv=100;
			}
			display();
			m=65536-(15000/pinlv);
			a=m/256;
			b=m%256;	
			EA=1;
		}
	}
	if(s3==0)					 //波形切换按键
	{	 
		delay(5);
		if(s3==0)
		{
			EA=0;
			while(!s3);
			boxing++;			   //波形切换
			if(boxing>=4)		   //4种波形
			{
				boxing=0;
			}
			display();
			EA=1;
		}
	}	
}
void bujindisplay()				 //步进值设置界面显示程序
{
	uint bai,shi,ge;			 //定义步进值 百十个位
	bai=bujin1/100;				 //将步进值除以100得到百位,也就是频率值的十位,因为有一个小数位
	shi=bujin1%100/10;			 //将步进值除以100的余数除以十得到十位
	ge=bujin1%100%10;			 //取余10后得到个位,也就是频率步进值的小数点后一位
	write_com(0x80+11);			 //选中液晶第一行第十一列
	if(bai==0)					 //百位是否为0
	write_date(' ');			 //百位不显示
	else						 //百位不为0
	write_date(table[bai]);		 //显示百位数据
	write_date(table[shi]);		 //显示十位数据
	write_date('.');			 //显示小数点
	write_date(table[ge]);		 //显示个位,也就是小数点后一位
}
void bujinjiance()				 //步进值设置键盘程序
{
	if(s4==0)					 //步进设置按键按下
	{
		delay(5);				 //延时去抖
		if(s4==0)				 //再次判断按键
		{
			 while(!s4);		 //按键释放,按键松开才继续向下执行
			 h++;				 //变量加
			 if(h==1)			 //进入设置状态时
			 {
			 	 write_com(0x01);			  //清屏
				 write_com(0x80);			  //初始化显示步进设置界面
				 write_date('S');delay(1);	  //step value
				 write_date('t');delay(1);
				 write_date('e');delay(1);
				 write_date('p');delay(1);
				 write_date(' ');delay(1);
				 write_date('v');delay(1);
				 write_date('a');delay(1);
				 write_date('l');delay(1);
				 write_date('u');delay(1);
				 write_date('e');delay(1);
				 write_date(':');delay(1);
				 bujin1=bujin;				  //步进值赋值给临时变量
				 
				 bujindisplay();			  //显示步进值
			 }
			 if(h==2)						  //退出设置
			 {
			 	h=0;						  //清零
				bujin=bujin1;				  //设置好的临时步进值赋值给步进变量
				
				init_lcd();					  //初始化液晶显示
				initclock();				  //定时器初始化
				display();					  //调用显示程序
			 }
		}
	}
	if(h==1)								  //设置步进值时
	{
		if(s1==0)							  //加按键按下
		{
			delay(5);						  //延时去抖
			if(s1==0)						  //再次判断
			{
				while(!s1);					  //按键释放
				bujin1++;					  //步进值加1
				if(bujin1>=101)				  //步进值最大100,也就是10.0Hz
				{
					bujin1=1;				  //超过最大值就恢复到0.1Hz
				}
				bujindisplay();				  //步进显示
			}
		}
		if(s2==0)							  //减按键,注释同上
		{
			delay(5);
			if(s2==0)
			{
				while(!s2);
				bujin1--;					  //步进减
				if(bujin1<=0)
				{
					bujin1=100;
				}
				bujindisplay();
			}
		}
	}
}

硬件设计

使用元器件:

单片机:STC89C52;

(注意:单片机是通用的,无论51还是52、无论stc还是at都一样,引脚功能都一样。程序也是一样的。)

9*15万用板;DAC0832芯片;

LM358芯片;8脚IC座;

20脚IC座;40脚IC座;

100欧姆电阻*2;220欧姆电阻;

5mmLED(红、黄、绿、雾白)*4;

30pf瓷片电容*2;104独石电容*2;

1602液晶;16p母座;

16p排针;4p排针;

103电位器;10k电阻*2;

2.2k电阻*3;1k电阻*2;

103排阻(10k);按键*5;

10uf电解电容;12M晶振;

自锁开关;DC电源插口;

导线:若干;

添加图片注释,不超过 140 字(可选)

流程图:

添加图片注释,不超过 140 字(可选)

设计资料

01仿真图

本设计使用proteus7.8和proteus8.9两个版本设计!具体如图!

添加图片注释,不超过 140 字(可选)

正弦波

添加图片注释,不超过 140 字(可选)

方波

添加图片注释,不超过 140 字(可选)

三角波

添加图片注释,不超过 140 字(可选)

锯齿波

添加图片注释,不超过 140 字(可选)

02原理图

本系统原理图采用Altium Designer19设计,具体如图!

添加图片注释,不超过 140 字(可选)

03程序

本设计使用软件keil5版本编程设计!具体如图!

添加图片注释,不超过 140 字(可选)

04设计报告

一万两千字设计报告,具体如下!

添加图片注释,不超过 140 字(可选)

05设计资料

        资料获取请关注同名公众号,全部资料包括程序(含注释)、仿真源文件 、AD原理图、开题报告、设计报告、结构框图、流程图、实物图、元件清单、讲解视频等。具体内容如下,全网最全! !

 

可以关注下方公众号!

点赞分享一起学习成长。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/729633.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Notepad++插件 Hex-Edit

Nptepad有个Hex文件查看器&#xff0c;苦于每次打开文件需要手动开插件显示Hex&#xff0c;配置一下插件便可实现打开即调用 关联多个二进制文件&#xff0c;一打开就使用插件的方法&#xff0c;原来是使用空格分割&#xff01;&#xff01;&#xff01;

螺蛳粉店外卖配送小程序商城的效果为何

螺蛳粉是广西地区的特色美食&#xff0c;在当地有着大量实体餐饮店或品牌商&#xff0c;其单品消费率非常高&#xff0c;在外地也不乏自创品牌或加盟店等&#xff0c;其特殊的味道及吸引力也同样复购率高&#xff0c;客户除了线下到店外&#xff0c;也会购买袋/桶装螺蛳粉到家自…

【无线感知】【P4】无线感知手势识别- WIFI 感知边界

前言&#xff1a; 这篇是北大2022 在Ubicomp 上面的论文 《placement Matters&#xff1a; understanding the Effects of Device placements for WiFi Sensing》 放置很重要&#xff1a;了解设备放置对WiFi传感的影响 目录&#xff1a; 简介 感知质量定义&#xff08;SSNR…

Bayanay:一款基于Python开发的无线网络安全研究工具

关于Bayanay Bayanay是一款基于纯Python开发的无线网络安全研究工具&#xff0c;在该工具的帮助下&#xff0c;无论你身处何地&#xff0c;都可以轻松地对周围地区的无线网络安全状况进行研究与分析。 该工具可以通过使用HTML5的地理位置定位功能并结合Scapy获取到的SSID信息…

Flutter ffi Failed to lookup symbol

iOS release版本&#xff0c;解决方式参考官方文档&#xff1a;在 iOS 中使用 dart:ffi 调用本地代码 如果debug版本也报这个错误&#xff0c;很可能是有多个.c文件&#xff0c;编译的时候没带上&#xff01; 假设你的ffi模块名字是 c_lib 对于Android端&#xff0c;需要修改…

Node.js中基于node-schedule实现定时任务之详解

文章目录 一、定时任务二、node-schedule、1、安装2、引入3、基于Cron表达式的规则4、基于Date的规则5、基于RecurrenceRule的规则6、API7、状态监听 一、定时任务 实际工作中&#xff0c;可能会遇到定时清除某个文件夹内容&#xff0c;定时发送消息或发送邮件给指定用户&…

Codepen Three.js环境依赖配置

Codepen Three.js环境依赖配置 前言 如果想在CodePen环境写Three.js依赖的项目&#xff0c;环境搭建可以参考该Codepen项目: Chill the lion 详细 打开设置可以看到以下配置 更多项目参考 1. Chill the Lion Chill the Lion 是一个基于 ThreeJS 制作的 WebGL 示例。它由…

FreeRTOS学习 -- 时间管理

在使用 FreeRTOS 的过程中通常会在一个任务函数中使用延时函数对这个任务延时&#xff0c;当执行延时函数的时候会进行任务切换&#xff0c;并且此任务就会进入阻塞态&#xff0c;直到延时完成&#xff0c;任务重新进入就绪态。 FreeRTOS 延时函数 1、函数 vTaskDelay() 在F…

【全开源】沃德会务会议管理系统(FastAdmin+ThinkPHP+Uniapp)

沃德会务会议管理系统一款基于FastAdminThinkPHPUniapp开发的会议管理系统&#xff0c;对会议流程、开支、数量、标准、供应商提供一种标准化的管理方法。以达到量化成本节约&#xff0c;风险缓解和服务质量提升的目的。适用于大型论坛、峰会、学术会议、政府大会、合作伙伴大会…

简单了解MyBatis

MyBatis 1、快速入门 MyBatis中文手册官网MyBatis中文网 1.1、创建数据表添加数据 create table user(id int auto_increment primary key comment 主键id,name varchar(20) comment 姓名,age int comment 年龄,gender char(1) comment 性别&#xff08;1&#xff1a;男, 2…

为什么我在 PostgreSQL 中 Commit 很慢?

有时&#xff0c;我们的一位客户会查看数据库中最耗时的语句&#xff08;使用pg_stat_statements或pgBadger&#xff09;&#xff0c;并发现COMMIT排名靠前。通常&#xff0c;COMMIT这是 PostgreSQL 中非常快的语句&#xff0c;因此值得研究。在本文中&#xff0c;我将探讨速度…

四川赤橙宏海商务信息咨询有限公司可信吗?

在数字化浪潮席卷全球的今天&#xff0c;电商行业正以前所未有的速度蓬勃发展。作为这一领域的佼佼者&#xff0c;四川赤橙宏海商务信息咨询有限公司凭借其在抖音电商服务领域的深厚积累和卓越表现&#xff0c;成为了引领行业创新发展的重要力量。 四川赤橙宏海商务信息咨询有…

华为设备telnet 远程访问配置实验简述

一、实验需求: 1、AR1模拟电脑telnet 访问AR2路由器。 二、实验步骤&#xff1a; 1、AR1和AR2接口配置IP&#xff0c;实现链路通信。 2、AR2配置AAA模式 配置用户及密码 配置用户访问级别 配置用户telnet 访问服务 AR2配置远程服务数量 配置用户远程访问模式为AAA 配置允许登录…

如何使用DeadFinder寻找失效链接

关于DeadFinder DeadFinder是一款功能强大的链接分析工具&#xff0c;该工具可以帮助广大研究人员快速地寻找目标页面中的无效链接&#xff08;死链&#xff09;。所谓死链&#xff0c;即一个页面中存在的无法被连接的一条链接。这些链接如果一直保留在页面中的话&#xff0c;…

【2024.6.21】今日科技时事:科技前沿大事件

人不走空 &#x1f308;个人主页&#xff1a;人不走空 &#x1f496;系列专栏&#xff1a;算法专题 ⏰诗词歌赋&#xff1a;斯是陋室&#xff0c;惟吾德馨 目录 &#x1f308;个人主页&#xff1a;人不走空 &#x1f496;系列专栏&#xff1a;算法专题 ⏰诗词歌…

[STM32]万年历

[STM32]万年历 需要资料的请在文章末尾获取~ ​​ 01描述 使用原件&#xff1a;stm32f103c8t6最小系统板x1&#xff0c;0.96寸OLED显示屏四角x1&#xff0c;4x4矩阵按键x1; 键位对应图&#xff1a; 1&#xff0c; 2&#xff0c; 3&#xff0c; 4------------- 切换页面 设置…

干货分享|如何将前端代理服务器(BFF)接入身份认证(1)

本篇文章将通过实例来详细讲解如何将前端代理服务器&#xff08;BFF&#xff09;接入身份认证。我们将使用一个示例应用来演示 BFF 与身份认证的集成过程。 通过这些实例讲解&#xff0c;你将掌握 BFF 与身份认证的集成技巧&#xff0c;为你的前端应用提供安全可靠的认证机制。…

APP IOS

APP IOS苹果源生应用程序 APP Android-CSDN博客

【Sa-Token|3】Sa-Token集成到现有微服务详细介绍

一、系统架构调整 用户中心&#xff1a;保持现有的用户登录、注册接口不变。多个项目&#xff1a;前后端分离&#xff0c;保持现有逻辑不变。网关服务&#xff1a;新增或配置网关服务&#xff0c;处理所有请求并进行 Token 校验和转发。统一 Token 管理&#xff1a;通过 Sa-Tok…

肇庆具有资质等保机构有几家?在哪里?

在近期揭晓的“中国百强城市排行榜”中&#xff0c;广东省共有12个城市入选&#xff0c;其中包括肇庆。肇庆-山水之城&#xff0c;文化之韵&#xff0c;端砚之乡&#xff0c;岭南瑰宝&#xff0c;是一个非常有发展的城市&#xff0c;企业多多。这不不少肇庆企业在问&#xff0c…