带分频整形的单片机频率计(1Hz—20MHz)

发布者:TranquilVibes最新更新时间:2021-12-29 来源: eefocus关键字:单片机  频率计 手机看文章 扫描二维码
随时随地手机看文章

单片机频率计 系统采用单片机+分频模块+整形模块+lcd1602液晶显示+按键设计而成。

频率的测量范围为1Hz—20MHz能测量各种周期信号,能测出正弦波、三角波或方波等波形的频率。通过LCD1602液晶显示屏显示检测到的即时频率数值(最多8位数,单位为Hz)。


废话不多说,先上图

正面,组装之前

在这里插入图片描述

正面,组装之后

在这里插入图片描述

背面,焊线面

在这里插入图片描述

频率计电路原理图如下:

在这里插入图片描述

PCB设计图如下:

在这里插入图片描述

74HC14电路设计

由于三极管放大电路输出的信号不是标准的方波信号,存在着上升沿不够陡峭,波形类似于正弦波等问题,为了使单片机对信号更好的采集,这里使用了施密特触发器74HC14对三极管放大电路输出的信号进行整形。电路图如图所示。

在这里插入图片描述

其中输入信号从芯片的1号脚输入,74HC14本身是一个芯片内部带有6个施密特触发器,我这里为了充分利用芯片使用了其中三个,实际上可以只使用一个。整形后的信号从芯片的6号脚输出。

3.5分频模块设计

3.5.1 74HC390芯片介绍

分频电路一般采用十进制计数器如74HC290、74HC390等来实现时间计数单元的计数功能。本次设计中选择74HC390。由其内部逻辑框图(如下图)可知,其为双2-5-10异步计数器,并每一计数器均有一个异步清零端(高电平有效)。由于我们要设计的是100分频电路,因此74HC390内部两个计数器都用上,分别都设置成10计数器。

在这里插入图片描述

3.5.2 74HC390分频电路设计

由于单片机运行速度有限,单片机运行一条基础指令需要1个机器周期即12个是时钟周期,换算成时间为1us。因此当频率过高的时候单片机就不能很精确的换算出频率。为了解决这个问题,这设计加入了一个100分频的计数器。当频率高于200KHZ的时候单片机计算分频后的信号,当频率低于200KHZ的时候计算分频前的信号。这样高低搭配可以扩大单片机的测量频率。最终换算出其真实对应的频率并在液晶上显示。其中电路图如图所示。

在这里插入图片描述

软件设计流程图

在这里插入图片描述

元器件清单

在这里插入图片描述

单片机仿真原理图如下

在这里插入图片描述

频率计仿真操作说明:

在这里插入图片描述
在这里插入图片描述

选择最后一项就可以了

在这里插入图片描述

单片机频率计参考源代码如下:

//******************************************************************************************

//连接框图: ___________________

// | P1.0 |->RS

// | P1.1 |->RW

// | P1.2 |->E

// | P0 |->DB

// | P3.4 |->1~9999hz的输入

// | P3.5 |->1~9999KHZ输入 (分频后)

//******************************************************************************************

#include

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(y1)

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(y1)

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{

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)count256+TL1; //count256强制转换成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++;

}


……………………

关键字:单片机  频率计 引用地址:带分频整形的单片机频率计(1Hz—20MHz)

上一篇:单片机做的半导体智能制冷小冰箱
下一篇:4个独立式按键控制LED移位

小广播
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved