矿石收音机论坛

 找回密码
 加入会员

QQ登录

只需一步,快速开始

搜索
楼主: ygnlhxyzj

自制10hz到2.4G频率计

  [复制链接]
     
发表于 2017-10-15 00:59:15 来自手机 | 显示全部楼层
硬件部分后来换了个4脚有源晶振,用4.7uH电感和0.1u电容做电源滤波,输出端串一个33Ω电阻缓冲信号,总台式频率计测量为25.0003MHZ,已经很准了,还有施密特触发器的输入端13脚我是直接接在前置放大后级三极管的C极的,在测量50HZ交流电,32.768K时钟,100K正弦波的时候,用示波器观察74HC14D触发器的13脚波形,然后反复调整三极管的工作点,使整形后的方波为最佳状态,在测量50HZ交流电的时候,用台式频率计测量74HC393分频后的25HZ,  12.5HZ,   6.25HZ也很准确了,按理说硬件应该没问题了。看来高频档不准确的原因还是出在低频档,像对讲机的频率,有些是要精确到百HZ位的,经过128分频后更不是一个整数的频率,如418.1375MHZ,分频后则为3.266699219MHZ,这就要求低频档要能很精准地把这个频率测出来才能正确显示。
回复 支持 反对

使用道具 举报

     
 楼主| 发表于 2017-10-15 06:45:18 | 显示全部楼层
cuijl1881840 发表于 2017-10-15 00:59
硬件部分后来换了个4脚有源晶振,用4.7uH电感和0.1u电容做电源滤波,输出端串一个33Ω电阻缓冲信号,总台式 ...

感谢cuijl1881840老师精确测试,找到了缺陷,我想毛病也许在这里,当计时器到达一秒时,程序输P1_2=0;//停止计数而这时计数器2恰好计数溢出归零,而没有来得及执行溢出中断让jishu加1(中断要几个指令周期后才执行),所以结果会少0x100000*1。所以增加如下语句,让程序等待执行中断后再计算。主程序中P1_2=0;//停止计数
//增加的语句开始
we=100;
while (we) //延时等待中断执行完毕
{
we--;
}
//增加语句结束

kk=TH2;//long*int=long,int*int=int会溢出
//jishi=TL2;
kk=kk*0x1000+TL2*0x10+P1/0x10+ 0x100000*jishu-1;//1秒闸门
// kk=kk*10;
//0x100000-

Displayunlong (kk);
回复 支持 反对

使用道具 举报

     
 楼主| 发表于 2017-10-15 09:50:43 | 显示全部楼层
ygnlhxyzj 发表于 2017-10-15 06:45
感谢cuijl1881840老师精确测试,找到了缺陷,我想毛病也许在这里,当计时器到达一秒时,程序输P1_2=0;// ...

“我想毛病也许在这里,当计时器到达一秒时,程序输P1_2=0;//停止计数而这时计数器2恰好计数溢出归零,而没有来得及执行溢出中断让jishu加1(中断要几个指令周期后才执行),所以结果会少0x100000*1。”这个解释好像还不完整,应该还有计数器2的低8位溢出,高8位加一这个过程要几个指令周期(计数器2自动完成),高8位没来得及加一,主程序已经使用高8位的结果参与计算了,所以最终结果少了4096,也就是0x100*1。
回复 支持 反对

使用道具 举报

     
发表于 2017-10-15 17:11:07 | 显示全部楼层
按照楼主的方法增加一语句进去,重新编译后发现测量22.1184的晶振时显示由原来的22.114***变为现在的22.119***了,但是测量12.288的时钟显示仍然是12.284***
回复 支持 反对

使用道具 举报

     
发表于 2017-10-15 17:11:49 | 显示全部楼层
cuijl1881840 发表于 2017-10-15 17:11
按照楼主的方法增加一语句进去,重新编译后发现测量22.1184的晶振时显示由原来的22.114***变为现在的22.119 ...

                           if( pd==0)
                                {
                                  we=96;
               while (we)  //延时凑够1秒
                                {
                                   we--;
                               }
                                }
                                else
                                {
                                  we=187;
              while (we)  //延时凑够0.1秒
                               {
                                we--;
                               }
                                         pd=1;
                                         pd=1;
                                         pd=1;
                                }
                         

          P1_2=0;//停止计数
                                         we=100;
          while (we) //延时等待中断执行完毕
           {
           we--;
           }
         
          kk=TH2;//long*int=long,int*int=int会溢出
          //jishi=TL2;
          kk=kk*0x1000+TL2*0x10+P1/0x10+ 0x100000*jishu-1;//1秒闸门
                        // kk=kk*10;
                   //0x100000-
         
           Displayunlong (kk);
                
          t2Init();
                InitTimer0();
回复 支持 反对

使用道具 举报

     
发表于 2017-10-15 23:58:58 来自手机 | 显示全部楼层
ygnlhxyzj 发表于 2017-10-15 09:50
“我想毛病也许在这里,当计时器到达一秒时,程序输P1_2=0;//停止计数而这时计数器2恰好计数溢出归零,而 ...

后来又调了214楼的第一个  we值,把原来的96修改为155,测了几个晶振的频率,好像正常了,但是高频档仍需时间去验证。
回复 支持 反对

使用道具 举报

     
发表于 2017-10-16 23:43:56 来自手机 | 显示全部楼层
反复调整214楼第一个原值为96的   WE值,想把频率测试调得更准确些,用台式频率计(1秒闸门)测量一个7.3728M的晶振,实测值为7.3728204,但是用仿制的频率计来测量,WE值调到22的时候,显示为7.373042左右,we值为20的时候,就是临界状态了,显示值在7.368到7.373之间跳动,无法调到7.3728,请问楼主程序还有什么地方可以完善的
回复 支持 反对

使用道具 举报

     
 楼主| 发表于 2017-10-17 05:35:14 | 显示全部楼层
cuijl1881840 发表于 2017-10-16 23:43
反复调整214楼第一个原值为96的   WE值,想把频率测试调得更准确些,用台式频率计(1秒闸门)测量一个7.372 ...

we=96;
while (we) //延时凑够1秒
{
we--;
}
//we取较小的临界值,在这里开始添加多条pd=1;
pd=1;
pd=1;
//在这里结束添加
}
else
回复 支持 反对

使用道具 举报

     
发表于 2017-10-17 11:23:34 | 显示全部楼层
有创意,值得学习
回复 支持 反对

使用道具 举报

     
发表于 2017-10-17 13:05:46 | 显示全部楼层

很好的资料。
回复 支持 反对

使用道具 举报

     
发表于 2017-10-17 21:05:07 | 显示全部楼层
ygnlhxyzj 发表于 2017-10-17 05:35
we=96;
while (we) //延时凑够1秒
{

按照楼主的方法又修改了一下,但是没效果,显示在7.368935到7.373042之间跳动。



if( pd==0)
                                {
                                  we=20;
               while (we)  //延时凑够1秒
                                {
                                   we--;
                               }
                                 pd=1;
                                 pd=1;
                                 pd=1;
                                }
                                else
                                {
                                  we=187;
              while (we)  //延时凑够0.1秒
                               {
                                we--;
                               }
                                         pd=1;
                                         pd=1;
                                         pd=1;
                                }
                         

          P1_2=0;//停止计数
                           we=100;
while (we) //延时等待中断执行完毕
{
we--;
}

                                                 
回复 支持 反对

使用道具 举报

     
发表于 2017-10-17 22:29:39 | 显示全部楼层
cuijl1881840 发表于 2017-10-17 21:05
按照楼主的方法又修改了一下,但是没效果,显示在7.368935到7.373042之间跳动。

现在就差这2百多HZ的误差没法调好,高频档测量几百兆的信号是不会准确的。通过测量1MHZ到20多MHZ的频率,发现频率计的误差是随着频率的增高而出现正偏差的,如1.8432MHZ,显示为1.843260MHZ,误差为60HZ,但是到12.288MHZ的时候,显示为12.288484MHZ,误差又增加了4百多HZ.
回复 支持 反对

使用道具 举报

     
 楼主| 发表于 2017-10-22 18:29:21 | 显示全部楼层
更新了程序,200HZ以下使用周期测量法,精确到0.1HZ。以下是c程序:


#include "at89x52.h"
#define LCM_Data  P2
#define Busy    0x80 //用于检测LCM状态字中的Busy标识
//22.1184M
sbit LCM_RS = 0x0ed;//p45
sbit LCM_E = 0x0ec; //p44
sbit LCM_RW = 0x0ee;//p46


void WriteDataLCM(unsigned char WDLCM);
void WriteCommandLCM(unsigned char WCLCM,BuysC);
unsigned char ReadDataLCM(void);
unsigned char ReadStatusLCM(void);
void LCMInit(void);
void DisplayOneChar(unsigned char X, unsigned char Y, unsigned char DData);
void DisplayListChar(unsigned char X, unsigned char Y, unsigned char code *DData);
void Displayunlong(unsigned long long1);
void Delay5Ms(void);
void Delay400Ms(void);
void t2Init(void); //t2初始化
unsigned char code uctech[] = {"0123456789"};
unsigned char code uctech1[] = {"HZ"};
unsigned char code uctechK[] = {"K"};
unsigned char code uctechM[] = {"M"};  
//void cheshi(unsigned  long ci);
void InitTimer0(void);
unsigned        long kk,jishu ,jishi;
// unsigned        int  jishi ;
// double hh;
unsigned char   weee, pph,zhouqipd;  
// bit pd;
       //22.1184M 1秒闸门
void main(void)
{

// P1_4=1;
// P1_5=1;
// P1_6=1;
// P1_7=1;

  P1_3=0; // P1_2=1; 74hc393 输入允许--------  P1_2=0; 74hc393 输入关
  P1_3=1;   //P1_1=0; P1_1=1; 模拟计数脉冲
  P1_3=0;//P1_3=0; P1_3=1; P1_3=0;74hc393 clear 复位  
  P1_2=0;
//  P3_7=0;
// pd=1;//1秒闸门
//pd=0;//0.1秒闸门

  //we=0;
// pp=0x30; //0.1秒闸门
   
  LCMInit(); //LCM初始化   
  WriteCommandLCM(0x01,1); //显示清屏
  // Displayunlong (1234567898);
   
          InitTimer0();
   while(1)
        {
   
        }
}
/*
void cheshi(unsigned  long ci)
{
  unsigned long i;
for(i=0;i<ci;i++)
{
  P1_1=1;
  P1_1=0;
  }
}
*/
void InitTimer0(void)//Timer0定时器10毫秒
{  
  
   P1_2=0;//停止计数
weee=100;
while(weee)
        {
    weee--;
        }

          kk=TH2;//long*int=long,int*int=int会溢出
          //jishi=TL2;
          kk=kk*0x1000+TL2*0x10+P1/0x10+ 0x100000*jishu-1;//1秒闸门
                        // kk=kk*10;
                   //0x100000-
         
                //----------------------------------
                          zhouqipd=0;
            if( P1_1==1)
         {
            // if ((kk<301)& (kk>0)) //小于1000HZ使用测量周期法
             if  (kk<200)  //小于1000HZ使用测量周期法
              {
                                  
                                    zhouqipd=1;
                                      if (kk==0)
                                                   {
                      Displayunlong(0);
                                                   }                                  
                                    EA=0;
                                         jishi=0;
                                    P1_2=1;//开始计数
                                  while(P1_4==1)//保证p1_4=0
               {
                                        }            //保证p1_4=0
                                  while(P1_4==0)// p1_4由0跳变到1
               {
                                        }            // p1_4由0跳变到1
              

                                  
                                           while(P1_4==1) //开始计时
                                           {
                                            jishi++;
                                           }
                  while(P1_4==0)
                                           {
                                            jishi++;
                                           }         //这里jishi是一个周期的计数
               

                P1_2=0;//停止计数  
                       
                                 
                kk= 520400000/jishi;
                                  
              }
                          //----------------------------------
                         
                        }
           Displayunlong (kk);
          t2Init();
              //  InitTimer0();
//-------------------------------------
  //char ppdd=0;
   pph=0;
    TR0 = 0;//停止定时器0
    jishi=0;
    TMOD = 0x01;
    //TH0 = 0x70; //22.1184M 6T 10ms
    TH0 =0; //25.000M 6T 10ms
   // TL0 = 0x00;
   // TL0 = 0x10;
    TL0 = 0;
    EA = 1;
    ET0 = 1;
    //--------------------------检测低到高跳变
   // P1_2=1;
  // while (ppdd==0)
  //   {
   //   if( P1_2==0)
        //        {
   //    while (P1_2==0)
        //         {
        //         }
    //   ppdd=1;
          //        }
  //   }
//         P1_2=0;
         //-----------------------------
    P1_3=1;  
    P1_3=0;//P1_3=0; P1_3=1; P1_3=0;74hc393 clear 复位
         TR2=1;        //启动定时器2
         TR0 = 1;//启动计数器0
         P1_2=1;//开始计数                  
}
void t2Init(void) //t2初始化
{
     TR2=0;        //停止定时器2
   RCAP2H=0x0;       
        RCAP2L=0x0;        // 自动重装       
        TH2=RCAP2H;
        TL2=RCAP2L;                                        //定时器2赋初值
  T2CON=0x2;  //计数器
  T2MOD=0x0;
  EA=1;  //开总中断
  ET2=1; // 开外定时器2中断
// TR2=1;        //启动定时器2
  jishu=0;
}
void Timer0Interrupt(void) interrupt 1
{
//-----------------------------------------------

if( P3_7==0) // 0.1秒闸门
{
if (jishi==5)
   {
  
    if (pph==0)
     
       {
           TH0 = 0xa4;
           TL0 = 0xf8;  //25000000
         //  TH0 = 0xa4;
         //  TL0 = 0xf8;  //25000000
               pph=1;
       }
          else
       {
         InitTimer0();
       }
                  

    }
   else
    {
     jishi++;//timer0计时次数
    }
}
else
{         //1秒闸门
  if (jishi==62)
   {
  
    if (pph==0)
     
       {  
           TH0 = 0x6e;
           TL0 = 0xa4;  //11.059200显示11.059208
         //  TH0 = 0x6c;
         //  TL0 = 0x88;  //25000006
          //  TH0 = 0x6c;
          // TL0 = 0x89; //24999994
               pph=1;
       }
          else
       {
         InitTimer0();
       }
                  

    }
   else
    {
     jishi++;//timer0计时次数
    }
}

//----------------------------------------------
}
void timer2() interrupt 5
{
        TF2=0;                                        //!!!注意!!! 定时器2必须由软件对溢出标志位清零,硬件不能清零,这里与定时器0和定时器1不同!!!
         jishu++;//timer2计数次数
}
void Displayunlong(unsigned long long1)
  {
      char pp1,i ;
                   P1_1=1;
             if( P1_1==0) //高频
            {   
               long1=long1*128;
               DisplayOneChar(15, 0, 'G');
            }
            else
            {
              DisplayOneChar(15, 0, 'D');      
            }
           // P3_7=1;
            if( P3_7==0) //1秒  0.1秒闸门
            {   long1=long1*10;
                    
                        //         pd=0;
                                         
                                 
                                //        we=131;
                         
                                DisplayOneChar(15, 1, 'k');
                         
                                       
            }
            else
            {
                 
                                 // pd=1;
                         
                                 // we=136;
                                  
                                  DisplayOneChar(15, 1, 'm');
            }

                                jishu=long1;                                         
    // WriteCommandLCM(0x01,1); //显示清屏
  for (i=11;i>=0;i--)
    {  
      pp1=long1 % 10;
                if(i==8)
                {
                 
                          if ( zhouqipd==0)
                                {
                                 DisplayListChar(8, 0, uctechK); //显示K
                                }
                                else
                                {
                DisplayOneChar(8, 0, '.');
                                }
                }
                else
                {
                        if(i==4)
                   {
                    DisplayListChar(4, 0, uctechM);//显示M
                   }
                        else
                        {
           DisplayOneChar(i ,0,uctech[pp1]);//显示数字
           long1=long1/10;
                   }
                }
    }
         DisplayListChar(12, 0, uctech1);

       
         long1=1000000000/jishu ; //显示周期
             if ( zhouqipd==1)
                                     {
                                      long1=long1*1000;
                                    }
                            
         if (jishu==0)
     long1=0;
           for (i=11;i>=0;i--)
    {  
      pp1=long1 % 10;
                if(i==8)
                {
                  DisplayOneChar(8, 1, 'u'); //显示u
                }
                else
                {
                        if(i==4)
                   {
                    DisplayOneChar(4, 1, 'm');//显示m
                   }
                        else
                        {
           DisplayOneChar(i ,1,uctech[pp1]);//显示数字
           long1=long1/10;
                   }
                }
                 DisplayOneChar(12, 1, 'n'); //显示u
                  DisplayOneChar(13, 1, 's'); //显示u
    }
  }
//写数据
void WriteDataLCM(unsigned char WDLCM)
{
ReadStatusLCM(); //检测忙
LCM_Data = WDLCM;
LCM_Data = WDLCM;
LCM_RS = 1;
LCM_RS = 1;
LCM_RW = 0;
LCM_RW = 0;
LCM_E = 0;
LCM_E = 0; //若晶振速度太高可以在这后加小的延时  
//Delay5Ms();
LCM_E = 1;
LCM_E = 1;
LCM_E = 1;
LCM_E = 1;
//Delay5Ms();
  LCM_E = 0;
}

//写指令
void WriteCommandLCM(unsigned char WCLCM,BuysC) //BuysC为0时忽略忙检测
{
if (BuysC) ReadStatusLCM(); //根据需要检测忙
LCM_Data = WCLCM;
LCM_Data = WCLCM;
LCM_RS = 0;
LCM_RS = 0;
LCM_RW = 0;
LCM_RW = 0;
LCM_E = 0;  
LCM_E = 0;  
// Delay5Ms();
LCM_E = 1;
LCM_E = 1;
LCM_E = 1;
LCM_E = 1;
// Delay5Ms();
  LCM_E = 0;
}

//读数据
unsigned char ReadDataLCM(void)
{
LCM_RS = 1;
LCM_RW = 1;
LCM_E = 0;
LCM_E = 0;
LCM_E = 1;
return(LCM_Data);
}

//读状态
unsigned char ReadStatusLCM(void)
{
LCM_Data = 0xFF;
LCM_RS = 0;
LCM_RW = 1;
LCM_E = 0;
LCM_E = 0;
LCM_E = 1;
while (LCM_Data & Busy); //检测忙信号
return(LCM_Data);
}

void LCMInit(void) //LCM初始化
{
  
  Delay400Ms(); //启动等待,等LCM讲入工作状态
  Delay400Ms(); //启动等待,等LCM讲入工作状态
LCM_Data = 0;
WriteCommandLCM(0x38,0); //三次显示模式设置,不检测忙信号
Delay5Ms();
WriteCommandLCM(0x38,0);
Delay5Ms();
WriteCommandLCM(0x38,0);
Delay5Ms();

WriteCommandLCM(0x38,1); //显示模式设置,开始要求每次检测忙信号
WriteCommandLCM(0x08,1); //关闭显示
WriteCommandLCM(0x01,1); //显示清屏
WriteCommandLCM(0x06,1); // 显示光标移动设置
WriteCommandLCM(0x0C,1); // 显示开及光标设置
}

//按指定位置显示一个字符
void DisplayOneChar(unsigned char X, unsigned char Y, unsigned char DData)
{
Y &= 0x1;
X &= 0xF; //限制X不能大于15,Y不能大于1
if (Y) X |= 0x40; //当要显示第二行时地址码+0x40;
X |= 0x80; // 算出指令码
WriteCommandLCM(X, 1); //这里不检测忙信号,发送地址码
WriteDataLCM(DData);
}

//按指定位置显示一串字符
void DisplayListChar(unsigned char X, unsigned char Y, unsigned char code *DData)
{
unsigned char ListLength;

  ListLength = 0;
Y &= 0x1;
X &= 0xF; //限制X不能大于15,Y不能大于1
while (DData[ListLength]>0x19) //若到达字串尾则退出
  {
   if (X <= 0xF) //X坐标应小于0xF
    {
     DisplayOneChar(X, Y, DData[ListLength]); //显示单个字符
     ListLength++;
     X++;
    }
  }
}

//5ms延时
void Delay5Ms(void)
{
unsigned int TempCyc = 5552;
while(TempCyc--);
}

//400ms延时
void Delay400Ms(void)
{
unsigned char TempCycA = 5;
unsigned int TempCycB;
while(TempCycA--)
{
  TempCycB=7269;
  while(TempCycB--);
};
}

51hei.zip

2.22 KB, 下载次数: 252

回复 支持 反对

使用道具 举报

     
 楼主| 发表于 2017-10-22 18:47:06 | 显示全部楼层
一些测试图片。

周期法1HZ

周期法1HZ

周期法5HZ

周期法5HZ

周期法10HZ

周期法10HZ

周期法50HZ

周期法50HZ

周期法100HZ

周期法100HZ

周期法200HZ

周期法200HZ

频率法300HZ

频率法300HZ

周期法153HZ

周期法153HZ

测量市电频率

测量市电频率

50HZ市电

50HZ市电
回复 支持 反对

使用道具 举报

     
 楼主| 发表于 2017-10-22 20:14:26 | 显示全部楼层
再发一些测试图片,信号发生器是22.1184M晶振分频得到

610HZ

610HZ

1016HZ

1016HZ

10907HZ

10907HZ

100538HZ

100538HZ

201076HZ

201076HZ

614400HZ

614400HZ

1005381HZ

1005381HZ

2211840HZ

2211840HZ

5529600HZ

5529600HZ

11059200HZ

11059200HZ
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 加入会员

本版积分规则

小黑屋|手机版|矿石收音机 ( 蒙ICP备05000029号-1 )

蒙公网安备 15040402000005号

GMT+8, 2025-4-30 01:35

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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