基于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  10x00,0x07,0x04,0x04,0x04,0x04,0x1c,0x00,0x00,0x1c,0x04,0x04,0x04,0x04,0x07,0x00,	  //矩形波	   2  30x00,0x01,0x02,0x04,0x08,0x10,0x00,0x00,0x00,0x10,0x08,0x04,0x02,0x01,0x00,0x00,	  //三角波	   4  50x00,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,得到的商是一位数,赋值给qianbai=pinlv%1000/100;		   //将频率除以1000的余数再除以100就得到了频率的百位,赋值给baishi=pinlv%1000%100/10;	   //同上,得到频率的十位ge=pinlv%1000/100%10;write_com(0x80+40+9); //选中第二行第九个位置if(qian==0)				   //千位如果为0write_date(' ');		   //不显示else					   //千位不为0write_date(table[qian]);   //正常显示千位if(qian==0&&bai==0)		   //千位和百位都为0write_date(' ');		   //百位不显示else					   //不都为0write_date(table[bai]);	   //百位正常显示write_date(table[shi]);	   //显示十位数write_date('.');		   //显示小数点write_date(table[ge]);	   //显示个位write_date('H');		   //显示频率的单位Hzwrite_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)					 //百位是否为0write_date(' ');			 //百位不显示else						 //百位不为0write_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 valuewrite_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++;					  //步进值加1if(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原理图、开题报告、设计报告、结构框图、流程图、实物图、元件清单、讲解视频等。具体内容如下,全网最全! !

 

可以关注下方公众号!

点赞分享一起学习成长。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

UE5近战对抗系统Tutorial

文章目录 BP_Character 组合攻击Notify State 检测攻击BP_Character 攻击反馈BP_Character 生命系统BP_Character 死亡效果BP_Character 武器系统BP_Enemy 初始化和行为树 BP_Character 组合攻击 首先我们获取攻击动画&#xff0c;在这里使用的是 Easy Combo Buffering 的攻击…

嵌入式系统软件架构设计方法

1.嵌入式系统软件架构设计的目的 嵌入式系统软件架构是开发大型嵌入式系统密集型软件贯穿始终的关键桥梁&#xff0c;同时软件架构也是软件开发的基础。架构设计的目的是&#xff1a; 保证应用的代码逻辑清晰&#xff0c;避免重复的设计&#xff1b;实现软件的可移植性&#…

聊聊JSON

引言 JSON的概念 JSON&#xff08;JavaScript Object Notation&#xff09;是一种轻量级的数据交换格式&#xff0c;它基于JavaScript的一个子集&#xff0c;但独立于语言&#xff0c;这意味着它可以被许多编程语言轻松解析。JSON的简洁性和易读性使其成为Web开发中数据交换的…

jnp.linalg.norm

jnp.linalg.norm 是 JAX 中用于计算向量或矩阵的范数的函数。JAX 是一个用于高性能机器学习研究的 Python 库&#xff0c;它提供了与 NumPy 类似的 API&#xff0c;但支持自动微分和加速计算。jnp 是 JAX 的 NumPy 接口。 jnp.linalg.norm 的基本语法 jnp.linalg.norm(x, ord…

办公软件都需要学习哪些?沈阳计算机办公软件培训

学习办公软件可以提高你的工作效率和专业技能。以下是一些常见的办公软件及其需要学习的关键内容&#xff1a; 1. Microsoft Word 或 Google Docs&#xff08;文字处理软件&#xff09; 基本操作&#xff1a;创建、保存、打开和打印文档。文本格式化&#xff1a;字体、段落、…

掌握 NumPy:高效数组处理综合指南(第 2/2 部分)

照片由 兹比内克布里瓦尔 on Unsplash 一、介绍 欢迎来到我关于 NumPy 的教程的第二部分&#xff01;之前&#xff0c;我们已经介绍了以下列表中的前 7 章。现在在这篇文章中&#xff0c;我们将从第 8 章一直到第 14 章。 Numpy 安装数组初始化Numpy 数组限制计算速度和内存使用…

量子计算:1 从薛定谔的猫开始

大模型技术论文不断&#xff0c;每个月总会新增上千篇。本专栏精选论文重点解读&#xff0c;主题还是围绕着行业实践和工程量产。若在某个环节出现卡点&#xff0c;可以回到大模型必备腔调或者LLM背后的基础模型重新阅读。而最新科技&#xff08;Mamba,xLSTM,KAN&#xff09;则…

序列1bp插入有什么影响

1bp插入突变&#xff08;1个碱基插入&#xff09;在基因序列中通常会引起以下几种影响&#xff1a; 移码突变&#xff08;Frameshift Mutation&#xff09;&#xff1a; 插入的一个碱基会改变插入点之后所有的密码子&#xff0c;导致读取框的移动。这种变化通常会引起整个蛋白质…

PCL 点云RANSAC+SVD提取平面

文章目录 一、简介二、实现代码三、实现效果参考资料一、简介 这里的思路很简单,RANSAC算法具有很不错的抗噪性,但是得到的平面仍然是基于原始数据中的点,这会导致提取出的平面不够精确;因此我们可以基于RANSAC算法提取出的点云,使用最小二乘法拟合出更为精确的平面参数。…

基于PHP的民宿管理系统

有需要请加文章底部Q哦 可远程调试 基于PHP的民宿管理系统 一 介绍 此民宿管理系统基于原生PHP开发&#xff0c;数据库mysql&#xff0c;前端jquery.js和echarts.js。系统角色分为用户和管理员。用户可以在线浏览和预订民宿&#xff0c;管理员登录后台进行相关管理等。(在系统…

【python】OpenCV——Color Correction

文章目录 cv2.aruco 介绍imutils.perspective.four_point_transform 介绍skimage.exposure.match_histograms 介绍牛刀小试遇到的问题 参考学习来自 OpenCV基础&#xff08;18&#xff09;使用 OpenCV 和 Python 进行自动色彩校正 cv2.aruco 介绍 一、cv2.aruco模块概述 cv2.…

如何清理docker build的缓存

在使用 Docker 构建镜像时&#xff0c;Docker 会利用构建缓存来加速后续的构建过程。如果某一层及其所有上层未发生变化&#xff0c;Docker 就会重用这一层的缓存。虽然这可以显著提升构建速度&#xff0c;但有时你可能希望强制 Docker 忽略缓存&#xff0c;以确保从头开始重新…

JAVA小知识28:FIle类文件对象

Java 中的 File 类是 java.io 包中的一个类&#xff0c;用于表示文件和目录路径名的抽象表示。它提供了一些方法来操作文件和目录 一、File的创建 1.1、绝对路径 绝对路径是指从文件系统的根目录开始定位文件或目录的完整路径。它通常以根目录符号开始&#xff0c;在 Window…

【Mac】DMG Canvas for mac(DMG镜像制作工具)软件介绍

软件介绍 DMG Canvas 是一款专门用于创建 macOS 磁盘映像文件&#xff08;DMG&#xff09;的软件。它的主要功能是让用户可以轻松地设计、定制和生成 macOS 上的安装器和磁盘映像文件&#xff0c;以下是它的一些主要特点和功能。 主要特点和功能 1. 用户界面设计 DMG Canva…

Rocky Linux 更换CN镜像地址

官方镜像列表&#xff0c;下拉查找 官方镜像列表&#xff1a;https://mirrors.rockylinux.org/mirrormanager/mirrorsCN 开头的站点。 一键更改镜像地址脚本 以下是更改从默认更改到阿里云地址 cat <<EOF>>/RackyLinux_Update_repo.sh #!/bin/bash # -*- codin…

自研地面站!自主开源无人飞行系统 Prometheus V2 版重大升级详解

自主开源无人飞行系统 Prometheus V2 相对于 Prometheus V1 在多方面做了重大的升级&#xff0c;今天我们将聊聊 Prometheus V2 的地面站升级。 地面站的重大提升 熟悉 Prometheus 的小伙伴们可能知道&#xff0c;V1 版本是没有专门的地面站的。而在 Prometheus V2 中&#x…

java开发技巧01

1.参数传递不要太深&#xff0c;影响阅读&#xff0c;可以抽取单独的方法。 void method001(String param){ for(){ ...... } if(){ ...... } for(){ ...... } if(){ ...... } //在此处才用到 param ......; if(param){ param ...... } } 2.不要在循环里面频繁请求数据库&…

vue3 配置全局@符号

1.下载依赖包 npm install types/node --save 2.修改vite.config.ts配置文件 import path from "path"; export default defineConfig({plugins: [vue()],resolve: {alias: {"": path.resolve(__dirname, "./src"),},}, });3.修改tsconfig.jso…

VERYCLOUD睿鸿股份亮相亚马逊云科技中国峰会2024

5月30日&#xff0c;为期两天的亚马逊云科技中国峰会在上海世博中心圆满落幕。 多位大咖现场分享&#xff0c;生成式AI时代的数据战略&#xff0c;企业级AI应用&#xff0c;最新技术、产品重磅发布&#xff0c;创新行业解决方案 …… 作为亚马逊云科技的生态合作伙伴&#x…

C语言循环中获取之前变量的值

获取上个数组变量的值 #include <stdio.h> #include <string.h>enum { GG, DD }; int main() {int bi[] {0, 0};int bi_s1[] {0, 0};for (int i 0; i < 5; i) {memcpy(bi_s1, bi, sizeof(bi));bi[GG] i * 3;bi[DD] i * 2;printf("bigg %d, bigg_s1 …