单片机课设基于51单片机的波形发生器(公开资源)(四种波形)(同时输出两种波形)

本文主要是介绍单片机课设基于51单片机的波形发生器(公开资源)(四种波形)(同时输出两种波形),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

单片机课设-波形发生器

  • 前言
  • 一、课设任务是什么?
  • 二、如何解决这几个任务?
  • 三、仿真原理图
  • 四、代码
    • 4.1 LCD1602代码
    • 4.2 波形输出以及8*8点阵显示代码
    • 4.3 波形选择
  • 五、仿真源码下载
  • 关于使用仿真时的问题
  • 常见问题解释


前言

  这篇文章是自己写的单片机课设,发这篇文章就当留个小纪念;如果说有什么不太好的地方还请大神请指出
Keil C51的代码以及Proteus的仿真的百度网盘链接放在文章最后,需要的人可以自取


提示:以下是本篇文章正文内容,下面案例可供参考

一、课设任务是什么?

  1. 设计一款能产生3种以上波形的波形发生器
  2. 设计波形选择按钮(采用3个独立按键)
  3. 点阵显示波形图案;
  4. 能同时输出两种波形;
  5. 显示频率。

二、如何解决这几个任务?

  1. 能产生3种以上波形
    分析:通过查阅资料,得知常用的波形有正弦波、方波、锯齿波、三角波四种波形其余的被称为任意波,因此我主要的目的便是输出四种波形.
  2. 能同时输出两种波形
    同时输出两个波形,就要轮转着用相同的8个I/O口来将波形取码输出到数模转换电路中,也就是对P0这个口时分复用.
      对于波形的取码,采用二维数组来存放数据.
  3. 设计波形选择按钮(采用3个独立按键)
    硬件方面:同时输出两个波形,意味着需要对两个波形进行调控,需要两个按键;开始设置波形与结束设置波形各一个按键,共四个按键实现波形选择.
      程序方面:初步构想是不在主函数中调用键盘扫描,而是在外部中断0服务程序中调用,中断时查询能够节省大部分资源.同时输出两个波形,意味着需要对两个波形进行调控,需要两个按键.再定义两个变量,一个按键对应一个变量就能够解决.
  4. 点阵显示波形图案
    硬件方面:Proteus中最小的点阵是88点阵,如果直接连接到51单片机上I/O口是肯定的不够用的,所以采用串口输出的方式.串并转换芯片采用74HC595;只需要6个引脚就能够控制16个引脚的88点阵
      程序方面:用一个二维数组来存储点阵显示的数据;为了节省C51的空间,就利用上面波形选择时候两个变量来控制这个二维数组.
  5. 显示频率
    硬件方面:P1口连接LCD1602的8个数据口,其他的命令位是在P2.6 P2.7
     程序方面:第一行(也就是write_com(0x80))显示波形输出端一的波形.第二行(就是执行write_com(0xc0))显示的是频率.

三、仿真原理图


四、代码

我把关键部分的代码Po到下面,希望可以对大家有所帮助。
文章后面有关于代码常见问题的解释,有不懂的可以看一下。

4.1 LCD1602代码

对于LCD1602来说,将它的代码和主函数放到同一个.c文件中会显得十分的累赘;对于这个波形发生器来说LCD显示只是辅助功能,所以放到一个独立的头文件中是一个不错的选择.

/*LCD1602.h 是LCD1602头文件*/
#ifndef _LCD1602_H_
#define _LCD1602_H_
#include<REG52.H>
#define uint  unsigned int
#define uchar unsigned char
/*LCD1602位定义*/
sbit lcdrs = P2^7;//RS : 0=输入指令;1=输入数据
sbit lcden = P2^6;/*LCD1602函数声明*/
void lcd_ram();					//向LCDRAM中写入八个字节的点阵数据,就会组成一个字符
void init_lcd();				//初始化函数
void write_com(uchar com);		//写命令函数
void write_date(uchar date);	//写数据函数
void delay_LCD56(uint xms);
/*LCD1602要显示的字符*/
uchar code table[];	//1-9
uchar code table1[];//前面是Fout= 是0-9
uchar code zifu[];
#endif

相关的LCD1602.c文件在链接里面有,这里就不再展示


4.2 波形输出以及8*8点阵显示代码

 对于波形输出采用定时器中断的方式输出,通过设置定时/计数器的初值就能够控制波形的频率,对于以后功能的扩展是个不错的选择;

void T0_time() interrupt 1
{TH0=a;//重新装填初值TL0=b;u++;	//u自加1if(u>=64)	//如果u超过64,就要归零u=0;	//这是因为各个波形的取值只有64个/*开始输出第一个波形*/WR1 = 1;CS0 = 0;			 /*CS0低电平有效,选中第一个DAC0832*/CS1 = 1;			 /*CS1低电平有效,第二个DAC0832未被选中*/P0 = wave[flag_0][u];/*将数据通过P0口输出到数模转换电路中*/WR1 = 0;delay(20);/*第一个波形输出完成*//*8*8矩阵显示第一个波形*/for(temp = 0;temp<4;temp++){line_scan();send_595(matrix[flag_0][temp]);delay(3);ST_CP_0 = 0;ST_CP_0 = 1;	//上升沿,存储寄存器变为高电平_nop_();ST_CP_0 = 0;	//发送完}/*8*8矩阵显示第一个波形完成*//*开始输出第二个波形*/WR1 = 1;CS0 = 1;CS1 = 0;P0 = wave[flag_1][u];WR1 = 0;delay(20);/*第二个波形输出完成*//*8*8矩阵显示第2个波形*/for(temp = 0;temp<4;temp++){line_scan();send_595(matrix[flag_1][temp]);delay(3);ST_CP_0 = 0;ST_CP_0 = 1;	//上升沿,存储寄存器变为高电平_nop_();ST_CP_0 = 0;	//发送完}/*8*8矩阵显示第2个波形完成*/
}

4.3 波形选择

波形选择用的是外部中断0,节省资源;设置优先级高于定时器中断0,能够打断中断0的服务程序进行设置.

void keyscan()
{//当第一个键按下去if(s1 == 0){delay(1);if(s1 == 0){EA = 0;				//关闭总中断while(!s1);		//等待松开按键if(++flag_0==4)flag_0=0;display();		//展示函数EA = 1;				//开总中断}}//当第二个按键按下去if(s2==0)			{	 delay(1);			//防抖动if(s2==0)			//确认按键按下{EA=0;			//关闭总中断while(!s2);		//等待按键松开if(++flag_1==4)flag_1=0;EA=1;}}	
}
void interrupt_0() interrupt 0 using 3
{while (s3!=0)//等待S3按键按下,就跳出循环,结束中断服务程序{keyscan();}
}

五、仿真源码下载

  这篇文章是自己写的单片机课设,发这篇文章就当留个小纪念;如果说有什么不太好的地方还请大神请指出。
  链 接🔐: 点击跳转➡️基于51单片机的波形发生器(公开资源)(同时输出两种波形)


关于使用仿真时的问题

  1. 为什么我的Proteus 7.6打不开这个仿真源文件?
    因为我们这一级大部分仿真都使用的是Proteus 8.6,伦志新老师使用的是Proteus 7,会有不兼容的现象;
  2. 不兼容的话我是应该照着这个自己画一份还是安装Proteus 8.6?
    自己画一份需要一个小时,另安装8.6大约只需十分钟,自己权衡利弊;
  3. 去哪里下载Proteus 8.6?
    下载链接:安装Proteus8.6

常见问题解释

  1. ❓LCD显示正弦波时,为什么是write_date(0); ,就会显示正弦波的上半部分?有这个疑问可以看我发布的视频
    ✅ 关于LCD波形显示问题的解释
  2. ❓波形发生器如何通过按键来设置产生的波形,是怎样控制的?
    ✅可以看我当时给网友的回答(即下图)
  1. ❓博主你好,我需要实现一个记录一段时间波形的功能,就是按下按键开始记录,再按之后就停止记录开始展示这一段时间的波形,我想要设置一个数组记录这段时间的波形可以吗?可是51空间太小存不下应该怎么办?
    ✅由于51单片机空间较小,建议使用三个变量来代替你冗长且重复较多的记录数组;
      ①设置一个变量num,输出一次波形,num++;
      ②定义一个起始变量start来存开始记录时当前波形取值点数组的下标;
      ③定义一个结束变量end来存停止时当前波形取值点数组的下标;
     这样一来,你在展示记录波形的时候只需将波形数组(或者要输出的波形的取值点)下标从起始变量start开始循环num次之后到end结束即可。
  2. ❓学长你好,我是您的学弟,运行您的发生器在示波器上总是看不到正确的波形,不知道应该怎么调节,您能帮我一下吗?
    ✅见下图,如果你按照我的设置但是还是出不来正确的波形,但是又是按照我的仿真画的,那你可以考虑一下是否在数模转换电路上接线错误。
  1. ❓您好,我想问一下,如果我需要加入一个增加与减少频率的功能,我应该如何做呢?比较小白,希望能讲的详细点,谢谢
    ✅频率与定时器的重装值有关。因为产生波形我设置在了定时中断里面。所以,你可以设置两个按键,1号按键加频率,2号按键减频率。
      当1号按下时候,你可以增大定时器重装值,使得定时器更快的溢出,更快的到达最大值,每当到达最大值,就会发生中断,这使得发生中断的间隔时间减少,也就是使得频率增大。
      当2号按下时候,减少定时器重装值,使得定时器减慢溢出,更慢的到达最大值,每当到达最大值,就会发生中断,这使得发生中断的间隔时间增大,也就使得频率减少。

能力有限,若有错误,欢迎私信指出

这篇关于单片机课设基于51单片机的波形发生器(公开资源)(四种波形)(同时输出两种波形)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/664792

相关文章

Python获取C++中返回的char*字段的两种思路

《Python获取C++中返回的char*字段的两种思路》有时候需要获取C++函数中返回来的不定长的char*字符串,本文小编为大家找到了两种解决问题的思路,感兴趣的小伙伴可以跟随小编一起学习一下... 有时候需要获取C++函数中返回来的不定长的char*字符串,目前我找到两种解决问题的思路,具体实现如下:

Win11安装PostgreSQL数据库的两种方式详细步骤

《Win11安装PostgreSQL数据库的两种方式详细步骤》PostgreSQL是备受业界青睐的关系型数据库,尤其是在地理空间和移动领域,:本文主要介绍Win11安装PostgreSQL数据库的... 目录一、exe文件安装 (推荐)下载安装包1. 选择操作系统2. 跳转到EDB(PostgreSQL 的

Docker镜像pull失败两种解决办法小结

《Docker镜像pull失败两种解决办法小结》有时候我们在拉取Docker镜像的过程中会遇到一些问题,:本文主要介绍Docker镜像pull失败两种解决办法的相关资料,文中通过代码介绍的非常详细... 目录docker 镜像 pull 失败解决办法1DrQwWCocker 镜像 pull 失败解决方法2总

在C#中调用Python代码的两种实现方式

《在C#中调用Python代码的两种实现方式》:本文主要介绍在C#中调用Python代码的两种实现方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录C#调用python代码的方式1. 使用 Python.NET2. 使用外部进程调用 Python 脚本总结C#调

IDEA中Git版本回退的两种实现方案

《IDEA中Git版本回退的两种实现方案》作为开发者,代码版本回退是日常高频操作,IntelliJIDEA集成了强大的Git工具链,但面对reset和revert两种核心回退方案,许多开发者仍存在选择... 目录一、版本回退前置知识二、Reset方案:整体改写历史1、IDEA图形化操作(推荐)1.1、查看提

Android自定义Scrollbar的两种实现方式

《Android自定义Scrollbar的两种实现方式》本文介绍两种实现自定义滚动条的方法,分别通过ItemDecoration方案和独立View方案实现滚动条定制化,文章通过代码示例讲解的非常详细,... 目录方案一:ItemDecoration实现(推荐用于RecyclerView)实现原理完整代码实现

C++从序列容器中删除元素的四种方法

《C++从序列容器中删除元素的四种方法》删除元素的方法在序列容器和关联容器之间是非常不同的,在序列容器中,vector和string是最常用的,但这里也会介绍deque和list以供全面了解,尽管在一... 目录一、简介二、移除给定位置的元素三、移除与某个值相等的元素3.1、序列容器vector、deque

Redis解决缓存击穿问题的两种方法

《Redis解决缓存击穿问题的两种方法》缓存击穿问题也叫热点Key问题,就是⼀个被高并发访问并且缓存重建业务较复杂的key突然失效了,无数的请求访问会在瞬间给数据库带来巨大的冲击,本文给大家介绍了Re... 目录引言解决办法互斥锁(强一致,性能差)逻辑过期(高可用,性能优)设计逻辑过期时间引言缓存击穿:给

Java实现MD5加密的四种方式

《Java实现MD5加密的四种方式》MD5是一种广泛使用的哈希算法,其输出结果是一个128位的二进制数,通常以32位十六进制数的形式表示,MD5的底层实现涉及多个复杂的步骤和算法,本文给大家介绍了Ja... 目录MD5介绍Java 中实现 MD5 加密方式方法一:使用 MessageDigest方法二:使用

VSCode中C/C++编码乱码问题的两种解决方法

《VSCode中C/C++编码乱码问题的两种解决方法》在中国地区,Windows系统中的cmd和PowerShell默认编码是GBK,但VSCode默认使用UTF-8编码,这种编码不一致会导致在VSC... 目录问题方法一:通过 Code Runner 插件调整编码配置步骤方法二:在 PowerShell