找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 1871|回复: 2
打印 上一主题 下一主题
收起左侧

关于51单片机的频率计设计的一些疑惑

[复制链接]
跳转到指定楼层
楼主
70黑币
下面是我在论坛上下载的频率计的代码和电路图,我在原电路图的基础上加了一个整形电路,晶振频率设置的是11.0592MHZ,仿真的结果也在下面。我的问题是:
1.为什么它会在较高频率时出现较大误差。我觉得这段代码设计算频率用的是直接测频法,可为什么会在测高频出现较大误差,而在测低频时很准确,是我理解错了,它用的是测周法?
2.为什么当我上调输入频率时(大概5kHZ以上),显示结果会出现闪动,调的越高闪动的越快,是动态显示的哪里出了问题吗?有什么解决思路?
3.x=T0count*65536+TH0*256+TL0,这段代码我还是不太明白,为什么要将计数器值这样转换才能成为频率值?
以上是我的疑惑,希望哪位大佬能帮我解答一下,十分感谢!


单片机源程序如下:
#include <AT89X51.H>
unsigned char codedispbit[]={0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f};     //P2的扫描位
unsigned char codedispcode[]={0x3f,0x06,0x5b,0x4f,0x66,
                              0x6d,0x7d,0x07,0x7f,0x6f,0x00,0x40};   //数码管的字形编码
unsigned char dispbuf[8]={0,0,0,0,0,0,10,10};//初始化显示值
unsigned char temp[8];     //存放显示的数据
unsigned char dispcount;   //显示计数器值
unsigned char T0count;     //T0的计数器值
unsigned char timecount;   //计时计数器值
bit flag;                  //标志位
unsigned long x;           //频率值
//频率计算函数
void HzCal(void)
{
unsigned char i;
x=T0count*65536+TH0*256+TL0; //得到T0的16位计数器值
for(i=0;i<8;i++)
  {
   temp[ i]=0;
  }
        i=0;
        while(x/10)         //拆分
          {
            temp[ i]=x%10;
            x=x/10;
             i++;
           }
        temp[ i]=x;
        for(i=0;i<6;i++)    //换算为显示数据
          {
            dispbuf[ i]=temp[ i];
          }
        timecount=0;
        T0count=0;
}

void main(void)
{

TMOD=0x15;              //设置定时器工作方式,T0计数,T1定时,均工作在方式1
TH0=0;
TL0=0;
TH1=(65536-5000)/256;
TL1=(65536-5000)%256;       //初始化T1
TR1=1;
TR0=1;
ET0=1;
ET1=1;
EA=1;                     //开中断

while(1)
   {
    if(flag==1)
       {
        flag=0;
        HzCal();   //频率计算函数
        TH0=0;
        TL0=0;
        TR0=1;
      }
   }
}
//定时器T0中断服务子函数
void t0(void) interrupt 1 using 0
{
T0count++;
}
//定时器T1中断服务子函数  
void t1(void) interrupt 3 using 0
{
TH1=(65536-5000)/256;
TL1=(65536-5000)%256;          //初始化T1预装值,1ms定时
timecount++;                   //扫描
if(timecount==200)             //秒定时
    {
     TR0=0;                     //启动T0
     timecount=0;
     flag=1;
    }
P2=0xff;                         //初始化选择引脚
P0=dispcode[dispbuf[dispcount]]; //输出待显示数据
P2=dispbit[dispcount];
dispcount++;                    //切换到下一个选择引脚
if(dispcount==8)                //如果已经扫描完成切换
    {
     dispcount=0;
    }


分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享淘帖 顶 踩
回复

使用道具 举报

沙发
ID:756622 发表于 2020-5-20 17:24 | 只看该作者
这应该是利用T1每秒使flag置1,T0测每秒内的脉冲数实现测量频率的。x=T0count*65536+TH0*256+TL0,T0count是计数器的溢出次数,假如说在未到达flag为1时,T0已经计数到最大值(65536)了(也就是已经检测到65536个脉冲了),所以会溢出,然后重新计数,TH0和TL0应该分别是T0当前计数值的高4位和低四位。通过这个式子可以把1s内的计数值(脉冲数)正确计算出来,单位周期的内的脉冲数不就是频率吗,所以就测量出频率了。我也不是很懂,以上是我的见解。

评分

参与人数 1黑币 +20 收起 理由
admin + 20 回帖助人的奖励!

查看全部评分

回复

使用道具 举报

板凳
ID:726557 发表于 2020-5-21 09:46 | 只看该作者
新征途 发表于 2020-5-20 17:24
这应该是利用T1每秒使flag置1,T0测每秒内的脉冲数实现测量频率的。x=T0count*65536+TH0*256+TL0,T0count ...

我懂了,谢谢大佬!也就是T0count溢出次数乘每次溢出的脉冲数,再加上现在的,TH0*256是要左移与TL0合并,得到1s脉冲数,就是现在的频率值了。
谢谢!
我还是对一二问不太明白,想了很久,还是不太明白,能解答一下吗?非常感谢!
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表