找回密码
 立即注册

QQ登录

只需一步,快速开始

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

我做的单片机频率计 MB506+BF998

[复制链接]
跳转到指定楼层
楼主

  1. /********************************************************
  2. 项  目:51单片机频率计
  3. 单片机:STC89c52RC                        
  4. 元  件:24MHZ晶振、1602液晶、MB506超高频分频器、
  5.         74HC393二进制脉冲计数器、BF998双删极场效应管、
  6.                 74HC14施密特触发器。
  7. 设计思路:参考网上“diy频率计”帖子重新整理编程。利
  8.                 用T0做定时器、T2做计数器,在一秒内T2计数脉冲
  9.                 数计算频率
  10.                 测试信号频率32MHZ到2.4GHZ时,开关拨到高频位置,
  11.             信号经MB506放大分频再输入到BF998放大——74HC14整
  12.                 形——74HC393计数后由Q1Q2Q3Q4送到单片机的P14 P15
  13.                 P16 P17脚,其中Q4也送到单片机的P1.0脚,从
  14.                 而记录Q4的脉冲个数,计算出信号频率。                    
  15.                      测试信号频率低于32MHZ时,开关拨到低频位置,
  16.                 被测试信号不经过MB506直接到BF998放大,后面同上         
  17. 编  程:
  18. ********************************************************/

  19. #include<at89x52.h>

  20. #define uchar unsigned char
  21. #define uint unsigned int
  22. unsigned char code table[]="f=    M   K   Hz"; //兆hz 千hz
  23. unsigned char code table1[]="T=    m   u   ns";//微妙 纳秒 皮秒
  24. unsigned char code table2[]="0123456789";

  25. sbit lcdrs=P2^7;
  26. sbit lcdrw=P2^6;
  27. sbit lcden=P2^5;         
  28. sbit LS393_MR=P1^3;
  29. sbit k200Hz=P2^0;
  30. sbit GP=P2^1;
  31. sbit k=P1^2;        

  32. unsigned int jishu,i;
  33. unsigned long f=0,T,irtime;
  34. bit a=0;   //标志位,为1表示本次测试结束,可进行下次测试


  35. /****************以下延时函数******************/

  36. void yanshi500us(uint x)
  37. {
  38.         uint y;
  39.         
  40.         for(x;x>0;x--)
  41.                 for(y=122;y>0;y--);        
  42. }
  43. void delay1s(void)   //误差 0us
  44. {
  45.     unsigned char a,b,c,n;
  46.     for(c=167;c>0;c--)
  47.         for(b=39;b>0;b--)
  48.             for(a=152;a>0;a--);
  49.     for(n=1;n>0;n--);
  50. }

  51. //================以下是LCD操作=========================

  52. void read_busy() /*LCD1602 忙等待*/
  53. {
  54.     lcdrs = 0;
  55.     lcdrw = 1;
  56.     lcden = 1;
  57.     P0 = 0xff;
  58.     while (P0&0x80);
  59.     lcden = 0;

  60. }

  61. void lcdrw_com(unsigned char com) //写命令
  62. {
  63.         read_busy();
  64.         lcdrw=0;
  65.         lcdrs=0;
  66.         P0=com;
  67.         yanshi500us(1);
  68.         lcden=1;
  69.         yanshi500us(1);
  70.         lcden=0;
  71. //        lcdrs=1;
  72.         yanshi500us(10);        
  73. }

  74. void lcdrw_dat(unsigned char dat) //写数据
  75. {
  76.         read_busy();
  77.         lcdrw=0;
  78.         lcdrs=1;
  79.         P0=dat;
  80.         yanshi500us(1);
  81.         lcden=1;   
  82.         yanshi500us(2);
  83.         lcden=0;
  84. //        lcdrs=1;
  85.         yanshi500us(10);        
  86. }
  87. void write_lcd(uchar COM,uchar dat)//向LCD写一个字
  88. {
  89.         lcdrw_com(COM);
  90.         lcdrw_dat(dat);
  91.         
  92. }
  93.                                          
  94. void lcdinit()
  95. {
  96.         yanshi500us(30);
  97.         lcdrw_com(0x38);   //设置16*2屏显,5*7点阵,8位数据接口
  98.         yanshi500us(10);
  99.         lcdrw_com(0x38);
  100.         yanshi500us(10);
  101.         lcdrw_com(0x38);
  102.         yanshi500us(10);
  103.         lcdrw_com(0x08);   //关闭显示
  104.         lcdrw_com(0x01);   //清屏
  105.         lcdrw_com(0x06);   //读写一个字符后指针加一光标加一
  106.         lcdrw_com(0x0c);   //开显示,显示光标,光标闪烁
  107.         
  108.                 for(i=0;i<17;i++)
  109.         {
  110.                 lcdrw_dat(table[i]); //写第一行数据f=    M   K   HZ

  111.         }        
  112.         
  113.         lcdrw_com(0x80+0x40);         //第二行起始位

  114.         for(i=0;i<16;i++)
  115.         {
  116.                 lcdrw_dat(table1[i]); //写第二行数据T=    u   n   ps

  117.         }
  118.          
  119. }                        


  120. /*******************定时器0中断服务函数**********************/

  121. void tim0_isr (void) interrupt 1 using 1//定时器0中断服务函数
  122. {
  123.         unsigned int fl;
  124.         float ff; //用于计算带小数点的频率
  125.         irtime++;          //用于计数2个下降沿之间的时间

  126.         if(k200Hz==0)
  127.         {
  128.                 if(jishu==2)
  129.                 {
  130.                         TR0=0;
  131.                         TR2=0;
  132.                         ff=4000000.00/((irtime)*25); //精确到小数点后两位
  133.                         f=ff*100; //使000.00类型的小数变为00000整数,
  134.                                           //从而容易分解个十百整数及小数点后两位小数
  135.                 //        f=4*f;                 

  136.          
  137.                         if(irtime==0)
  138.                         {
  139.                                 f=0;T=0;
  140.                         }
  141.                         else
  142.                                 T=(1000000000/ff);        //周期ns
  143.                         a=1;
  144.                         delay1s();                        
  145.                 }
  146.         }                  
  147.         else
  148.         {                                
  149.                 if(irtime==20000)        //计时够2秒
  150.                 {
  151.                         fl=P1>>4; //少于16个脉冲的脉冲数
  152.                         TR2=0;    //关计数器2
  153.                         TR0=0;    //关定时器0
  154.                         irtime=0;
  155.                         
  156.                         fl=P1>>4; //少于16个脉冲的脉冲数
  157.                         f=((jishu*65536+(TH2*256+TL2))*16+fl)/2;//2秒内总脉冲数即频率
  158.                         if(GP==0)
  159.                         {
  160.                                 f=2*f*64;
  161.                         }
  162.                         else
  163.                                 f=2*f;

  164.                         if(f==0)
  165.                                 T=0;
  166.                         else                        //下载时使用6T模式
  167.                                 T=1000000000/f;        //周期ns
  168.                         a=1;                          
  169.                 }
  170.         }
  171. }



  172. void TIM0init(void)//定时器0初始化
  173. {
  174.         TMOD=0x02;//定时器0工作方式2,8位初值自动重装,TH0是重装值,TL0是初值         
  175.           ET0=1;    //开中断
  176.                
  177.         if(k200Hz==0)
  178.         {
  179.                 TH0=0xce;//初始值
  180.                   TL0=0xce;//自动重装值,定时25um        
  181.                 TR2=1;         //开计数器2
  182.                 TR0=0;   //关定时器0
  183.         }
  184.         else
  185.         {
  186.                 TH0=0x38;//初始值
  187.                   TL0=0x38;//自动重装值,定时100um
  188.                 TR2=1;         //开计数器2
  189.                 TR0=1;   //开定时器0               
  190.         }               
  191. }

  192.                           
  193. /*******************T2计数器初始化***********************/

  194. void t2Init(void) //t2初始化
  195. {
  196.       TR2=0;          //停止计数器2         
  197.           T2CON=0x2;  //计数器
  198.           T2MOD=0x00;
  199.          
  200.           if(k200Hz==0)
  201.           {
  202.                    RCAP2H=0xff;        
  203.                    RCAP2L=0xfe; // 自动重装,接收1个脉冲中断
  204.           }
  205.           else
  206.           {
  207.                   RCAP2H=0x0;        
  208.                   RCAP2L=0x0; // 自动重装,接收65536个脉冲中断        
  209.           }
  210.           TH2=RCAP2H;
  211.           TL2=RCAP2L; //定时器2赋初值
  212.           EA=1;  //开总中断
  213.           ET2=1; // 开外定时器2中断

  214. }



  215. /*********************T2计数器***************************/

  216. void timer2() interrupt 5
  217. {
  218.          TF2=0;        //!!!注意!!! 定时器2必须由软件对溢出标志位清零,硬件不能清零,这里与定时器0和定时器1不同!!!
  219.          jishu++;//T2中断次数,如果k200Hz=0,来一个脉冲中断一次,否则65536个脉冲中断一次
  220.          if(k200Hz==0)
  221.          {
  222.                  if(jishu==1) //收到第一个脉冲时开启计时器
  223.                 {
  224.                         TR0=1;
  225.                 }
  226.          }
  227. }


  228. /*****************74LS393 复位*******************/

  229. void  LS393_rest()
  230. {

  231.         LS393_MR=0;
  232.         LS393_MR=1;
  233.         LS393_MR=0;        
  234. }


  235. void main()
  236. {        
  237.         yanshi500us(100);
  238.         lcdinit();
  239.         t2Init();
  240.         TIM0init();
  241.         
  242.         yanshi500us(100);
  243.         LS393_rest();
  244.         while(1)
  245.         {        
  246.                 if(k200Hz==0)
  247.                 {
  248.                         write_lcd(0x80+9,'z');
  249.                         write_lcd(0x80+8,'H');
  250.                         write_lcd(0x80+5,'.');
  251.                         write_lcd(0x80+10,' ');
  252.                         write_lcd(0x80+14,' ');
  253.                         write_lcd(0x80+15,' ');
  254.         
  255.                     write_lcd(0x80+2,table2[f%100000/10000]);
  256.                         write_lcd(0x80+3,table2[f%10000/1000]);
  257.                         write_lcd(0x80+4,table2[f%1000/100]);
  258.                         write_lcd(0x80+6,table2[f%100/10]);
  259.                         write_lcd(0x80+7,table2[f%10]);
  260.                         delay1s();
  261.                                 
  262.                 }
  263.                 /********************以下显示频率*********************/
  264.                 else
  265.                 {
  266.                         write_lcd(0x80+2,table2[f/1000000000]);
  267.                         write_lcd(0x80+3,table2[f%1000000000/100000000]);
  268.                         write_lcd(0x80+4,table2[f%100000000/10000000]);
  269.                         write_lcd(0x80+5,table2[f%10000000/1000000]);
  270.                         write_lcd(0x80+7,table2[f%1000000/100000]);
  271.                         write_lcd(0x80+8,table2[f%100000/10000]);
  272.                         write_lcd(0x80+9,table2[f%10000/1000]);
  273.                         write_lcd(0x80+11,table2[f%1000/100]);
  274.                         write_lcd(0x80+12,table2[f%100/10]);
  275.                         write_lcd(0x80+13,table2[f%10]);
  276.                 }
  277.         /**********************以下显示周期***************************/

  278.             write_lcd(0x80+0x40+2,table2[T/1000000000]);
  279.                 write_lcd(0x80+0x40+3,table2[T%1000000000/100000000]);
  280.                 write_lcd(0x80+0x40+4,table2[T%100000000/10000000]);
  281.                 write_lcd(0x80+0x40+5,table2[T%10000000/1000000]);
  282.                 write_lcd(0x80+0x40+7,table2[T%1000000/100000]);
  283.                 write_lcd(0x80+0x40+8,table2[T%100000/10000]);
  284.                 write_lcd(0x80+0x40+9,table2[T%10000/1000]);
  285.                 write_lcd(0x80+0x40+11,table2[T%1000/100]);
  286.                 write_lcd(0x80+0x40+12,table2[T%100/10]);
  287.                 write_lcd(0x80+0x40+13,table2[T%10]);
  288.                 if(a==1)
  289.                 {
  290.                         a=0;
  291.                         jishu=0;
  292.                         irtime=0;
  293.                         t2Init();                                                                                
  294.                         LS393_rest();
  295.                         TIM0init();                                   
  296.                 }                                                                                       
  297.         }        
  298. }                                                           
复制代码


评分

参与人数 1黑币 +50 收起 理由
admin + 50 共享资料的黑币奖励!

查看全部评分

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

使用道具 举报

沙发
ID:78901 发表于 2023-5-25 20:06 | 只看该作者
为何不做成等精度频率计呢
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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