找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 2470|回复: 18
收起左侧

51单片机实现等精度频率计Proteus仿真程序(半成品)调试几天没进展

[复制链接]
ID:991374 发表于 2022-4-10 14:32 | 显示全部楼层 |阅读模式
新人求助,因为近几天完全没有进展,所以发帖求助,另一方面,虽然是半成品,但测低频还是蛮准的(小数点后一位),可以当个参考。出现问题如下:低频时比较准,高频时显示频率就会不停改变而且误差较大。
仿真图如下:
1.png
程序如下:
#include<reg52.h>
#include<string.h>
#define u8 unsigned char

sbit Gate_ctl=P1^7;sbit Gate=P3^2;
sbit RW=P2^5;sbit RS=P2^6;sbit EN=P2^7;

u8 ledbuf[8],frequency[9],hand[10]="frequency:";
unsigned long count1,count0,overflow1,overflow0;
double fx,f0;
int i,f;
unsigned long fc,Nx,N0,a;
//*****************************************//
void delay(u8 time);
void lcd_init();
void interrupt_init();
void lcd_write_com(u8 com);
void lcd_write_data(u8 date);
void lcd_send(u8 i,u8 j,u8 date[],u8 all);
void lcd_math();
//*****************************************//
void interrupt_init()
{
        TMOD=0xD9;

        T2CON=0x00;
        PT2=1;
        RCAP2H=0x4c;RCAP2L=0x00;
        TH2=RCAP2H;TL2=RCAP2L;
        TH1=0;TL1=0;
        TH0=0;TL0=0;
        ET1=1;ET0=1;ET2=1;
        TR1=1;TR0=1;TR2=1;
        EA=1;
        
}
void main()
{
  f0=921600;
  lcd_init();
  lcd_send(1,0,hand,10);
  interrupt_init();
  while(1)
  {
           while(Gate==1);//Gate=0时跳出
           TR2=0;

           TR0=0;TR1=0;
Nx=(overflow1*65536+TL1+TH1*256);
           N0=overflow0*65536+TL0+TH0*256;

fx=(double)((Nx*f0)/N0);
           fc=(unsigned long)(fx*100+0.5);
           lcd_math();
           lcd_send(2,3,frequency,9);

overflow1=0;overflow0=0;
           TH1=0;TL1=0;TH0=0;TL0=0;
           TR2=1;

TR1=1;TR0=1;
while(Gate!=1);//Gate=1时跳出
  }
}

void time0() interrupt 1 //T0
{ overflow0++;}

void time1() interrupt 3   //T1
{  overflow1++;}

void time2() interrupt 5   //T2
{     TF2=0;
       i++;  
if(i==20)
   {    i=0;
    Gate_ctl=!Gate_ctl;
    TH2=RCAP2H;TL2=RCAP2L;
   }
}

void lcd_write_data(u8 date)//LCD写数据初始化
{
  RW=0;
  RS=1;
  P0=date;
  delay(100);
  EN=1;
  delay(100);
  EN=0;
}
void lcd_write_com(u8 com)//LCD写命令初始化
{
  RW=0;
  RS=0;
  P0=com;
  delay(100);
  EN=1;
  delay(100);
  EN=0;
}
void lcd_init()
{
  EN=0;
  lcd_write_com(0x38);//8线,2行,5*7;
  lcd_write_com(0x0c);//屏幕显示,光标不显示,光标不闪烁
  lcd_write_com(0x06);//光标右移,屏幕不动
  lcd_write_com(0x01);//清屏
}
void lcd_math()//整数转换为字符;
{
          u8 n=8;
    strcpy(frequency,"0000000.0");

       do{
                if(n==7)
                {
                 n--;
                 fc=fc*10;
                }
                else
                {
                 frequency[n]=fc%10+'0';
                 n--;
                 }
                }while(fc/=10);
}
void lcd_send(u8 i,u8 j,u8 date[],u8 all)//(行,列,数组,数组内字符个数)数组送入12864
{
  u8 m;
  if(i==1)
  {
    lcd_write_com(0x80+j);
  }
  else
  {
    lcd_write_com(0x80+0x40+j);
  }
  for(m=0;m<all;m++)
        {
         lcd_write_data(date[m]);
         delay(1);
         }

}
void delay(u8 time)
{
while(time--);
}

Keil代码与Proteus仿真下载: 测试3.rar (103.81 KB, 下载次数: 13)
回复

使用道具 举报

ID:991374 发表于 2022-4-10 14:35 | 显示全部楼层
提醒一下,lcd_send函数注释有误,不是12864,是1602,忘改了。
回复

使用道具 举报

ID:94031 发表于 2022-4-10 16:43 | 显示全部楼层
单片机主频不够高。电脑性能不够好。
回复

使用道具 举报

ID:991374 发表于 2022-4-10 16:55 | 显示全部楼层
xuyaqi 发表于 2022-4-10 16:43
单片机主频不够高。电脑性能不够好。

我用的这个单片机频率为11.0592MHZ,外部电路经过了74LS161进行了10分频,理论来说可以测到4MHZ,频率太高时有误差可以理解,但实际电路测量中,1MHZ就已经出现20~35的误差了,个人感觉这个是有点大了。所以我觉得应该是代码写的没那么好,中间漏测或者多测了些方波。
回复

使用道具 举报

ID:161164 发表于 2022-4-11 11:24 | 显示全部楼层
基操不应该是用定时器2的捕获模式来得出脉冲周期时间吗?
回复

使用道具 举报

ID:991374 发表于 2022-4-11 11:33 | 显示全部楼层
lkc8210 发表于 2022-4-11 11:24
基操不应该是用定时器2的捕获模式来得出脉冲周期时间吗?

是我拘泥于测频法了,学到了,这就去试一下
回复

使用道具 举报

ID:401564 发表于 2022-4-11 12:11 | 显示全部楼层
频率计这种东西,感觉也没什么用,不知道要用这玩意来干嘛
单片机推荐用STC8A8K64D,这个时钟可以到33MHZ
而且可以DMA操作,最大程度提高CPU效率
使用32MHZ有源晶振,提高精度
可以加入SN74LVC1G14之类的触发器进行整形
回复

使用道具 举报

ID:991374 发表于 2022-4-11 12:37 | 显示全部楼层
Y_G_G 发表于 2022-4-11 12:11
频率计这种东西,感觉也没什么用,不知道要用这玩意来干嘛
单片机推荐用STC8A8K64D,这个时钟可以到33MHZ
而 ...

主要是导师让我搞一下这个,说我基础不太好,提的要求还比较苛刻,要测5MHZ以上,精度在小数点后,实在没办法了,才来求助
回复

使用道具 举报

ID:161164 发表于 2022-4-11 14:28 | 显示全部楼层
起昵称真难 发表于 2022-4-11 11:33
是我拘泥于测频法了,学到了,这就去试一下

高速脉冲计数,
低速测量脉冲的周期,
两种结合就是固定采样时间内计数N个脉冲+脉冲周期,
比如采用一个外部中断源,
当脉冲下降沿开始计时100毫秒,
计数脉冲的个数N。
100ms时间到,
再计时T到下一个脉冲的下降沿。
那么总的脉冲数N+1个,
总的周期100ms+T.。

那么频率 =(N+1)/(0.1+T)
回复

使用道具 举报

ID:301191 发表于 2022-4-11 16:00 | 显示全部楼层
顶一下
回复

使用道具 举报

ID:991374 发表于 2022-4-11 18:34 | 显示全部楼层
lkc8210 发表于 2022-4-11 14:28
高速脉冲计数,
低速测量脉冲的周期,
两种结合就是固定采样时间内计数N个脉冲+脉冲周期,

很有参考价值,谢谢大佬。因为我使用的方法是单位时间内测量脉冲个数,在外部电路中使
用D触发器达到脉冲上升沿时停止计数的作用,并且使用fx=(Nx*f0)/N0进行误差的矫正。
(fx为待测信号频率,f0为时钟频率即晶振大小,Nx为单位时间内所计待测信号的脉冲,N0为
单位时间内所计时钟的脉冲个数)
。实际上达到的效果和您所说的差不多。而我目前所遇到的问题是在高频时误差较大并且不停
改变显示值。经过查找资料和向周围人了解,应该是在晶振不高的情况下,测高频就会产生误
差,除了换晶振好像没什么好办法,当然也可能是我刚刚接触单片机,理解的不到位。大佬的
思路很清晰,我会去试试的。
回复

使用道具 举报

ID:123289 发表于 2022-4-12 09:18 | 显示全部楼层
低频:在两次输入脉冲之间,数定时器的脉冲个数。
高频:用定时器给出一个时间间隔,数此间隔中输入脉冲的个数。
回复

使用道具 举报

ID:991374 发表于 2022-4-13 11:46 | 显示全部楼层
尬住,我问了另一个导师这个问题,那个老师说实现这种要求(5MHZ以上且精度为小数点)很难,不知道是这个东西本身就很难实现,还是以我的水平现在很难实现....跟导师说了之后,导师让我做到20MHZ精度不在要求,现在又有一个问题想请教大佬们,因为我是用的74LS161和74LS01在单片机外部构成的10分频,按理说,11.0592MHZ的单片机大概可以测到460KHZ左右,外部分频后应该可以测到4.6MHZ,但实际电路(非仿真)只能测到1MHZ。74系列芯片的最大工作频率也大概在25MHZ以上应该没问题,有大佬知道为什么或者你觉得会有那种情况导致这种问题呢?给一点思路也可以
回复

使用道具 举报

ID:161164 发表于 2022-4-13 11:54 | 显示全部楼层
460kHz是如何算出来的?
你知道89C52进出一次中断要多久?
你知道char类型++一次要多久?
回复

使用道具 举报

ID:991374 发表于 2022-4-13 14:43 | 显示全部楼层
lkc8210 发表于 2022-4-13 11:54
460kHz是如何算出来的?
你知道89C52进出一次中断要多久?
你知道char类型++一次要多久?

因为我单片机是12T的,11.0592MHZ的晶振12分频后为0.9216MHZ,测一个波形需要两个机械周期,所以除2得460800HZ。当然这只是理论值,就跟您说的一样我并没有求出中断一次和累加所消耗的时间,之所以确定是在460KHZ左右,是因为之前没有使用74LS161和74LS01进行外部电路10分频时,测得的界限大概为460KHZ(超过这个值误差会变得特别大)。而我想的是,外部10分频后,进入单片机(能被计算机准确测量的)的最大频率应该也为460KHZ,那么按理论值来说,就应该是可以测到4.6M。当然这可能是比较不成熟的想法,如有疏漏的地方请指点。
回复

使用道具 举报

ID:123289 发表于 2022-4-13 16:54 | 显示全部楼层
13#:
你们老师敷衍你了:
理论上:测量精度取决于你的时基精度(这里是你CPU使用晶振的精度),保守一点,计数时存在+-1的误差,即测试数量存在+-1的不确定度。这是极限精度了。
实际上:由于软件的不合理,捕捉不及时,中断延时等等,不确定度会增加,这就要看你对单片机的认知度了,也考验你编程的水平。懂汇编的人,会做得更精准。
例如:你用定时器做个2秒的脉冲,再打开一个计数器,CLK从引脚用被测的5MHz信号,用2秒脉冲作CLK的开关,即当脉冲为1时,让CLK通过,则脉冲过后,理论上计数器应收到10M个脉冲。你说是也不是。
回复

使用道具 举报

ID:991374 发表于 2022-4-13 17:22 | 显示全部楼层
yzwzfyz 发表于 2022-4-13 16:54
13#:
你们老师敷衍你了:
理论上:测量精度取决于你的时基精度(这里是你CPU使用晶振的精度),保守一点 ...

好像确实是这么回事
回复

使用道具 举报

ID:123289 发表于 2022-4-14 08:06 | 显示全部楼层
只要你用的时基是晶振,测量频率,做到6个有效数字的精度是没有问题的。
回复

使用道具 举报

ID:65956 发表于 2022-4-14 08:26 | 显示全部楼层
晶振改用有源温度晶振试试,我也曾经试过,用15W单片机,用有源温度晶振,用PCA采集频率,校准后采集1HZ时,可以达到小数点第5位的精度,可惜这样的精度还达不到我项目0.5PPM的要求,后来就没再用了
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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