标题: 带分频整形的单片机频率计(1Hz—20MHz)源程序,仿真与设计论文等全套资料 [打印本页]
作者: micoco 时间: 2018-5-2 18:51
标题: 带分频整形的单片机频率计(1Hz—20MHz)源程序,仿真与设计论文等全套资料
单片机频率计 系统采用单片机+分频模块+整形模块+lcd1602液晶显示+按键设计而成。
频率的测量范围为1Hz—20MHz能测量各种周期信号,能测出正弦波、三角波或方波等波形的频率。通过LCD1602液晶显示屏显示检测到的即时频率数值(最多8位数,单位为Hz)。
频率计电路原理图如下:
74HC14电路设计
由于三极管放大电路输出的信号不是标准的方波信号,存在着上升沿不够陡峭,波形类似于正弦波等问题,为了使单片机对信号更好的采集,这里使用了施密特触发器74HC14对三极管放大电路输出的信号进行整形。电路图如图3-10所示。
图3-10施密特触发器电路原理图
其中输入信号从芯片的1号脚输入,74HC14本身是一个芯片内部带有6个施密特触发器,我这里为了充分利用芯片使用了其中三个,实际上可以只使用一个。整形后的信号从芯片的6号脚输出。
3.5分频模块设计
3.5.1 74HC390芯片介绍
分频电路一般采用十进制计数器如74HC290、74HC390等来实现时间计数单元的计数功能。本次设计中选择74HC390。由其内部逻辑框图(如图3)可知,其为双2-5-10异步计数器,并每一计数器均有一个异步清零端(高电平有效)。由于我们要设计的是100分频电路,因此74HC390内部两个计数器都用上,分别都设置成10计数器。
图3-11 74HC390内部逻辑框图
3.5.2 74HC390分频电路设计
由于单片机运行速度有限,单片机运行一条基础指令需要1个机器周期即12个是时钟周期,换算成时间为1us。因此当频率过高的时候单片机就不能很精确的换算出频率。为了解决这个问题,这设计加入了一个100分频的计数器。当频率高于200KHZ的时候单片机计算分频后的信号,当频率低于200KHZ的时候计算分频前的信号。这样高低搭配可以扩大单片机的测量频率。最终换算出其真实对应的频率并在液晶上显示。其中电路图如图3-12所示。
图3-12 74HC390分频电路原理图
4.系统软件设计
4.1系统软件总体设计
4-1系统主流程图
频率计元件清单:
单片机仿真原理图如下(proteus仿真工程文件可到本帖附件中下载)
频率计仿真操作说明:
鼠标右击这个元件,
选择最后一项就可以了
单片机频率计源程序如下:
- //******************************************************************************************
- //连接框图: ___________________
- // | P1.0 |->RS
- // | P1.1 |->RW
- // | P1.2 |->E
- // | P0 |->DB
- // | P3.4 |->1~9999hz的输入
- // | P3.5 |->1~9999KHZ输入 (分频后)
- //******************************************************************************************
- #include <reg52.h>
- unsigned long int fre;
- unsigned char time;
- unsigned int count;
- unsigned int count1;
- //端口及函数说明----------------------------------------------------------------------------
- sbit LCD_RS=P1^0; //片选信号
- sbit LCD_RW=P1^1; //读写信号
- sbit LCD_E=P1^2; //使能信号
- #define LCD_DB P0 //数据信号
- unsigned char character[10]={0};//在屏幕上显示的字符串
- unsigned char character_1[]={"fre= Hz"};
- unsigned char FLAG = 0;
- void LCD_init(void);//初始化函数
- void LCD_write_command(unsigned char command);//写指令函数
- void LCD_write_data(unsigned char dat);//写数据函数
- void LCD_disp_char(unsigned char x,unsigned char y,unsigned char dat);//在某个屏幕位置上显示一个字符,X(0-15),y(1-2)
- void delay_n40us(unsigned int n);//延时函数
-
- void timer_init(); //中断初始化函数
- //-------------------------------------------------------------------------------
- void delay_n40us(unsigned int n) //延时函数
- {
- unsigned int i;
- unsigned char j;
- for(i=n;i>0;i--)
- for(j=0;j<2;j++);
- }
- void delay_1s()
- {
- unsigned int i,j;
- for(i = 0;i<100;i++)
- for(j = 0;j<1000;j++);
- }
- void LCD_init(void) //液晶初始化函数
- {
- LCD_write_command(0x38);//设置8位格式,2行,5x7
- LCD_write_command(0x38);//设置8位格式,2行,5x7
- LCD_write_command(0x38);//设置8位格式,2行,5x7 切记要写三遍!!!!
- LCD_write_command(0x0c);//整体显示,关光标,不闪烁
- LCD_write_command(0x06);//设定输入方式,增量不移位
- LCD_write_command(0x01);//清除屏幕显示
- delay_n40us(100);//清屏延时
- }
- void LCD_write_command(unsigned char dat) //写命令函数
- {
- LCD_DB=dat;
- LCD_RS=0;//指令
- LCD_RW=0;//写入
- LCD_E=1; //使能
- LCD_E=0;
- delay_n40us(1);//写命令延时
- }
- void LCD_write_data(unsigned char dat) //写数据函数
- {
- LCD_DB=dat;
- LCD_RS=1;//数据
- LCD_RW=0;//写入
- LCD_E=1;//使能
- LCD_E=0;
- delay_n40us(1); //写数据延时
- }
- void LCD_disp_char(unsigned char x,unsigned char y,unsigned char dat)//显示一个字符
- {
- unsigned char address;
- if(y==1)
- address=0x80+x; //显示在第一排的时候的x的地址
- else
- address=0xc0+x; //显示在第二排的时候的x的地址
- LCD_write_command(address); //输入地址
- LCD_write_data(dat); //输入数据
- }
- void LCD_disp_num(unsigned char x,unsigned char y,unsigned char dat)//显示一个数字
- {
- unsigned char address;
- if(y==1)
- address=0x80+x; //显示在第一排的时候的x的地址
- else
- address=0xc0+x; //显示在第二排的时候的x的地址
- LCD_write_command(address); //输入地址
- LCD_write_data(dat+48); //输入数据
- }
- void dis_num(void)
- {
- unsigned char i=0,j=0,k=0;
- LCD_write_command(0x01);//清除屏幕显示
-
- character[0] = fre/1000000;
- character[1] = fre/100000%10;
- character[2] = fre/10000%10;
- character[3] = fre/1000%10;
- character[4] = fre/100%10;
- character[5] = fre/10%10;
- character[6] = fre%10;
- character[7] = 'H';
- character[8] = 'z';
-
- for(i = 0;i<4;i++) //显示fre
- {
- LCD_disp_char(i+0,1,character_1[i]);
- }
- for(i = 0;i<10;i++) //判断第一个不为0的数
- {
- if(character[i]!=0)
- break;
- }
- k = 10-i-2;
- for(j = 0;j<k;j++) //显示所有的数字
- {
- LCD_disp_num(4+j,1,character[i++]);
- }
-
- for(i = 5;i<7;i++) //显示Hz
- {
- LCD_disp_char(j+4,1,character_1[i]);
- j++;
- }
- }
- void main()
- {
- unsigned char i;
- LCD_init();
- timer_init(); //定时/计数器初始化
-
- for(i = 0;i<4;i++)
- {
- LCD_disp_char(i+0,1,character_1[i]);
- }
- while(1)
- {
- dis_num(); //显示
- delay_1s();
-
- }
- }
- void timer_init(void) //定时/计数器初始化
- {
- TMOD=0x66; //计数器0工作工作方式2,自动重装初值
- TH0=0; //计数器初值为0
- TL0=0;
- TR0=1; //计数器开始计数
- ET0=1; //打开计数器0中断
- TH1=0; //计数器初值为0
- TL1=0;
- TR1=1; //计数器开始计数
- ET1=1; //打开计数器0中断
- RCAP2H=(65536-62500)/256; //在程序初始化的时候给RCAP2L和RCAP2H赋值,
- RCAP2L=(65536-62500)%256; //TH2和TL2将会在中断产生时自动使TH2=RCAP2H,TL2=RCAP2L。
- TH2=RCAP2H; //12M晶振下每次中断62.5ms
- TL2=RCAP2L;
- ET2=1; //打开定时器2中断
- TR2=1; //定时器2开始计时
- EA=1; //开总中断
- }
- //----------------------------------------------------------------
- void timer2(void) interrupt 5 //定时器2中断(62.5ms)
- {
- double temp;
- time++;
- TF2=0; //定时器2的中断标志位TF2不能够由硬件清零,所以要在中断服务程序中将其清零
- if (time==16) //定时1s时间到
- {
- time=0; //计时清0
- fre=(long)count*256+TL1; //count*256强制转换成long型,否则将不产生进位 先判断分频后的
- FLAG = 0;
-
- if(fre<2000)//200K之后读取分频后的频率
- {
- fre = (long)count1*256+TL0;
- FLAG = 1;
- }
-
- count=0; //清零计数器0计数
- count1=0;
- EA=1; //开中断
- }
- }
- //----------------------------------------------------------------
- void timer0(void) interrupt 1 //计数器0中断
- {
- count++;
- }
- //----------------------------------------------------------------
- void timer1(void) interrupt 3 //计数器1中断
- {
- count1++;
- }
-
- ……………………
- …………限于本文篇幅 余下代码请从51黑下载附件…………
复制代码
所有资料51hei提供下载:
作者: hqpos 时间: 2018-11-2 14:02
资料配套齐全,很有参考价值。
作者: aking991 时间: 2018-11-27 11:50
很不错,收藏了
作者: 张小宝1 时间: 2018-12-10 11:02
下载打开根本是乱码,一点用都没有
作者: jadyjayjay 时间: 2018-12-10 15:06
新手来看看
作者: 都市郎 时间: 2018-12-11 01:27
资料非常全,很好,感谢楼主分享!
作者: 黑点哥iii 时间: 2018-12-13 21:39
赞一个
作者: wpppmlah 时间: 2019-3-29 16:52
已经下载了资料,很不错很有学习价值!谢谢.
作者: 一只猫的过客 时间: 2019-4-13 20:47
为什么我测不到1MHZ以上的频率啊,仿真一直崩溃
作者: cnc202 时间: 2019-4-14 22:21
感谢楼主分享
作者: 774388942 时间: 2019-4-18 10:19
谢谢分享
作者: 774388942 时间: 2019-4-18 10:28
感谢楼楼
作者: 竹之君 时间: 2019-5-31 18:30
内容很详细,看的非常清楚,会一直关注这个网站的。
作者: 快乐眼泪 时间: 2019-5-31 21:26
感谢楼主分享,有时间做个!
作者: 物业tuan 时间: 2019-12-9 23:10
资料很全面,这两天正好在学习这个,感谢楼主分享
作者: 517087308 时间: 2019-12-31 16:47
很给力
作者: 517087308 时间: 2020-1-2 14:11
很不错哟
作者: saine 时间: 2020-3-4 22:50
能帮我设计一下吗?
作者: wangjinlongd 时间: 2020-3-10 22:16
资料非常全,很好,感谢楼主分享!
作者: 329575852 时间: 2020-4-28 19:22
仿真图文件夹里边的hex跟程序文件夹里边的不是同一个吧,仿真图文件夹里边的那个很准,程序文件夹里边的那个老是出错
作者: 单片机新手12.15 时间: 2020-5-4 18:44
谢谢楼主
作者: 195470880 时间: 2020-5-14 21:38
很不错,收藏了
作者: zxcvgfd 时间: 2020-5-17 13:41
楼主怎么计算这个频率计能测多少频率范围???
作者: asdfqw 时间: 2020-5-23 18:03
这里的分频期间我认为可以设计成50分频,可以更好地利用资源
作者: 初晴2000 时间: 2020-6-13 15:16
很实用的资料,棒棒哒!!!
作者: swustlx86 时间: 2020-6-17 09:03
好资料,51黑有你更精彩!!!
作者: xieyebao1995 时间: 2020-6-18 08:37
正想学习这方面,谢谢分享
作者: peeta 时间: 2020-7-2 22:14
超好的东西,收藏慢慢学!
作者: rayin 时间: 2020-11-15 17:32
不错,值得学习。51hei有你更精彩!!
作者: lele88888 时间: 2021-1-26 14:31
很不错,收藏了
作者: xuliya282 时间: 2021-3-9 07:18
不错不错,正好想学习一下频率计。
作者: 蚂蚁科技 时间: 2023-7-4 11:56
能不能测试晶振频率?
作者: 王秋冬 时间: 2023-7-27 08:46
能不能测试晶振频率?如果不超测量上限,应该能测试晶振频率。
作者: 蚂蚁科技 时间: 2023-11-27 19:26
防制了一个,感觉有点误差,不知道什么原因,有谁做成功的分享一下经验
作者: 蚂蚁科技 时间: 2024-5-25 19:23
4M以下不能测试,4M以上测试精度还可以,点赞!!!
作者: xlhlydd 时间: 2024-6-18 10:42
能否改成数码管的,1602显示的字能改大字吗
作者: nanfuB 时间: 2024-6-19 19:35
看起来好全的资,收下了谢谢
欢迎光临 (http://www.51hei.com/bbs/) |
Powered by Discuz! X3.1 |