admin管理员组

文章数量:821312

基于51的简易频率计(细讲解加代码)

基于51的简易频率计

主要用到的51功能是 ①外部中断和②定时计数器

注意:51的晶振最好是12Mhz,因为51十二分频后,也就是1Mhz了也就是说计数器每次进行加一计数实际上是进行加了1/f的时间
也就是1/(1mhz)的时间,其实主要是要这样计算时间会更准确些

并且此程序所能测试的脉冲宽度最大值为2的16减1ms,如果想扩大测量范围,此文章最后有说明。
在讲解代码之前,先普及一下51定时器的用法
51定时器主要由两个8位寄存器来控制的
第一个是工作方式寄存器TMOD
故名思意就是控制定时器的工作方式的寄存器
如图所示:
它一共是八位,低四位用于设置T0定时器,高四位用于设置T1定时器。

1、GATE是门控位,GATE=0时,只要用软件使TCON中的TR0或TR1为1,就可以启动定时/计数器工作
而GATA=1时,要用软件使TR0或TR1为1,同时外部中断引脚INT0/1也为高电平时,才能启动定时/计数器工作。
(而我们的程序设计主要用到的就是定时器门控位的作用,我们要让GATE=0,让中断和TCON寄存器同时控制定时器的开启)

2、C/T :定时/计数模式选择位。C/T =0为定时模式;C/T =1为计数模式。
3、M1M0:工作方式设置位。定时/计数器有四种工作方式
如图所示:

本程序中我们选的工作方式是方式0,即M1=0,M0=1,计数容量是2的16次方

第二 个寄存器就是TCON了
就是用来控制定时/计数器的启动和中断申请的
如图所示:

TF1(TCON.7):T1溢出中断请求标志位
TR1(TCON.6):T1运行控制位
TF0(TCON.5):T0溢出中断请求标志位,其功能与TF1类同。
TR0(TCON.4):T0运行控制位,其功能与TR1类同。
(这里就不细讲它了)

然后我们看代码部分

#include<reg52.h> //包含头文件,一般情况不需要改动,头文件包含特殊功能寄存器的定义#define uint unsigned int #define uchar unsigned charsbit K=P3^2;   //记录周期//数码管显示#define DataPort P0 //定义数据端口 程序中遇到DataPort 则用P0 替换sbit LATCH1=P2^4;//定义锁存使能端口 段锁存sbit LATCH2=P2^3;//                 位锁存unsigned char code
dofly_DuanMa[10]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};// 显示段码值0~9unsigned char code
dofly_WeiMa[]={0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f};//分别对应相应的数码管点亮,即位码unsigned char TempData[8]; //存储显示值的全局变量uint HIGH,LOW;//函数声明void Control_sudu(void);void Display(unsigned char
FirstBit,unsigned char Num);/*------------------------------------------------uS延时函数,含有输入参数 unsigned char t,无返回值unsigned char 是定义无符号字符变量,其值的范围是0~255 这里使用晶振12M,精确延时请使用汇编,大致延时长度如下 T=tx2+5 uS ------------------------------------------------*/void DelayUs2x(unsigned char t){   while(--t);}/*------------------------------------------------mS延时函数,含有输入参数 unsigned char t,无返回值unsigned char 是定义无符号字符变量,其值的范围是0~255 这里使用晶振12M,精确延时请使用汇编------------------------------------------------*/void DelayMs(unsigned char t){while(t--){//大致延时1mSDelayUs2x(245);DelayUs2x(245);}}void Init_T0(void){TMOD=0x09;TH0=0;TL0=0;}void Message_Width(void){while(K);TR0=1;while(!K); while(K);TR0=0;HIGH=TH0;LOW=TL0;}/*------------------------------------------------主程序------------------------------------------------*/main(){while(1){Init_T0();Control_sudu();Message_Width();}}/******************************************************************************** 函 数 名         : Int0()       interrupt 0* 函数功能             
: 外部中断0的中断函数* 输    入         : 无* 输    出         : 无*******************************************************************************/void Control_sudu(void){TempData[0]=dofly_DuanMa[(HIGH*256+TL0)*2/1000];    TempData[1]=dofly_DuanMa[((HIGH*256+TL0)*2%1000)/100];TempData[2]=dofly_DuanMa[((HIGH*256+TL0)*2%100)/10];TempData[3]=dofly_DuanMa[((HIGH*256+TL0)*2%1000)%10];Display(4,4);}/*------------------------------------------------显示函数,用于动态扫描数码管输入参数 FirstBit 表示需要显示的第一位,如赋值2表示从第三个数码管开始显示如输入0表示从第一个显示。Num表示需要显示的位数,如需要显示99两位数值则该值输入2------------------------------------------------*/void Display(unsigned char
FirstBit,unsigned char Num){static unsigned char i=0;DataPort=0;  
//清空数据,防止有交替重影LATCH1=1;     //段锁存LATCH1=0;DataPort=dofly_WeiMa[i+FirstBit]; //取位码 LATCH2=1;     //位锁存LATCH2=0;DataPort=TempData[i]; //取显示数据,段码LATCH1=1;     //段锁存LATCH1=0;i++;if(i==Num)i=0;}

然后我们单独讲一下每个函数的执行功能
sbit K=P3^2; //记录周期
**这个变量是设置外部中断的引脚,是作为脉冲测量的引脚输入io口 **

void Init_T0(void)
{
TMOD=0x09;TH0=0;TL0=0;
}

这部分函数是定时器的工作方式的赋值以及定时器的初值赋值
一开始清空计数器让计数器的低八位和高八位都为0
然后在检测到脉冲信号的高电平时再开启计数器

void Message_Width(void){while(K);   //等待下降沿到来TR0=1;     //开启定时计数器while(!K);   //等待上升沿到来while(K);       //再次等待下降沿到来TR0=0;   //关闭定时计数器HIGH=TH0;   //把计数器的高八位值赋给变量HIGHLOW=TL0;    //把计数器的低八位值赋给变量LOW}

这部分代码是检测脉冲宽度并把宽度值记录下来具体的原理我在这个函数里面写了注释

void Control_sudu(void){TempData[0]=dofly_DuanMa[(HIGH*256+TL0)*2/1000];    TempData[1]=dofly_DuanMa[((HIGH*256+TL0)*2%1000)/100];TempData[2]=dofly_DuanMa[((HIGH*256+TL0)*2%100)/10];TempData[3]=dofly_DuanMa[((HIGH*256+TL0)*2%1000)%10];Display(4,4);}

最后是这个函数,这是显示函数
本函数检测到的脉冲宽度是用四位数码管显示的,此部分则为显示函数
TempData[0]这是千位依此向下分别是百位,十位和个位

注意这个显示的单位是ms级的也就是说,如果你的数码管显示的是2000则代表频率计检测到的脉冲周期为2000ms,如果想让它显示的更高为大家可以自己增加数码管显示位数或者增大他的显示单位

再次注意本程序中定时器最高能检测的脉冲周期为2的16次方减1如果想增大它的测量范围大家可以再合理利用中断申请标志位来扩大他的存储记录容量。

本文标签: 基于51的简易频率计(细讲解加代码)