找回密码
 立即注册

QQ登录

只需一步,快速开始

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

单片机数字频率计单周期实现 2015电赛F题答案

[复制链接]
跳转到指定楼层
楼主
电路原理图如下:


单片机源程序如下:
  1. #include<reg51.h>      
  2. #define uint unsigned int
  3. #define uchar unsigned char
  4. //单周期定闸门时间测量尽量降低误差
  5. //后续待实现:实现多周期定闸门时间测量以降低误差

  6. static bit end= 0;        //周期开始结束标志,为减少中断服务工作量定义为全局变量
  7. uchar m=0;         //保存定时器清零次数
  8. uchar u=0;
  9. uint xL,xH=0;                //剩余计数次数
  10. unsigned long t0,c;                //分别保存被测信号的周期和频率
  11. uchar a[]={'F',':','w','a','i','t','.','.','.','.','.','H','z'};          //频率数据结果保存

  12. sbit lcdrw=P1^6;
  13. sbit lcdrs=P1^7;
  14. sbit lcden=P2^4;

  15. void delay(uint s)//延时1MS
  16. {
  17.   uint r,g;
  18.    for(r=s;r>0;r--)
  19.      for(g=10;g>0;g--); //原值为110,我改为了10,做实际产品时可能要改回去
  20. }

  21. /////////////////LCD1602的设置//////////////////
  22. void write_com(uchar com) // 写指令
  23. {  
  24.    lcdrs=0;                //低电平0时选择指令寄存器
  25.    P0=com;
  26.    delay(5);
  27.    lcden=1;                //高电平(1)时读取信息
  28.    delay(5);
  29.    lcden=0;                //负跳变时执行指令
  30. }
  31. void write_data(uchar date) // 写数据
  32. {  
  33.    lcdrs=1;                 //高电平1时选择数据寄存器
  34.    P0=date;
  35.    delay(5);   //高电平(1)时读取信息
  36.    lcden=1;
  37.    delay(5);
  38.    lcden=0;           //负跳变时执行指令
  39. }
  40. void initlcd()//初始化LCD1602
  41. {
  42.   lcdrw=0;        //低电平(0)时进行写操作
  43.   lcden=0;          //负跳变时执行指令
  44.   write_com(0x38);//显示模式设置
  45.   write_com(0x0c); //显示开,开游标,不闪烁  
  46.   write_com(0x06); // 字符时整体不移动  
  47. }
  48. ////////////LCD1602设置///////////////////////

  49. ///////////定时计数器外部中断设置//////////////
  50. void CTINT0_init()                 //定时计数器0和外部中断0初始化
  51. {       
  52.         TMOD = 0x1;             //T0工作在模式1,定时方式FHP
  53.         TH0=0;                         //定时计数器初值清零
  54.         TL0=0;
  55.         EA=1;                                  //开总中断
  56.         ET0=1;                         //开Timer0中断
  57.         EX0=1;                                  //开外部中断0
  58.         IT0=1;                                  //设置外部中断方式为下降沿触发
  59. }
  60. ///////////定时计数器外部中断设置//////////////

  61. ////////////////中断服务函数//////////////////
  62. void ITC0() interrupt 0   //外部中断0服务程序
  63. {       
  64.         if(end)         //FHP被测信号一个周期结束做三件事情:1、记录周期相关数据;2、定时计数器清零并停止;3、告知下次中断为周期开始
  65.         {
  66.                 u=m;                                  //读定时计数器0溢出次数
  67.                 TR0=0;        //停止计时器
  68.                 xH=TH0;                  //读定时计数器0当前值
  69.                 xL=TL0;
  70.                 end = 0;                //设置下次中断为周期开始
  71.         }
  72.         else        //FHP被测信号一个周期开始做一件事情:启动计时器
  73.         {
  74.                 TH0=TL0=0;                         //定时计数器初值清零
  75.                 TR0=1;        //启动计时器
  76.                 m=0;                                  //溢出次数清零
  77.                 end = 1;        //                //设置下次中断为周期结束
  78.         }
  79. }
  80. void TIME0() interrupt 1  //定时计数器0溢出中断服务程序
  81. {
  82.         m++;                                  //溢出次数加1
  83. }
  84. ////////////////中断服务函数//////////////////

  85. void main()
  86. {
  87.         uchar i;
  88.         CTINT0_init();                  //定时计数器外部中断初始化       
  89.         initlcd();                          //液晶显示初始化       
  90.         while(1)
  91.         {                               
  92.                         t0=u*65536 + xH*256 + xL;                                   //计算周期
  93.                         c=1000000000/t0;                           //计算频率,保存的是频率扩大了1000倍的值
  94.                         //计算结果逐位保存,首先是小数点后三位
  95.                         a[10]=c%10+'0';
  96.                         a[9]=(c/10)%10+'0';
  97.                         a[8]=(c/100)%10+'0';
  98.                         c /= 1000;//下面是整数部分
  99.                         a[6]=c%10+'0';
  100.                         a[5]=(c/10)%10+'0';
  101.                         a[4]=(c/100)%10+'0';
  102.                         a[3]=(c/1000)%10+'0';
  103.                         a[2]=(c/10000)%10+'0';
  104.                         write_com(0x80);
  105.                         for(i=0;i<=12;i++)
  106.                         {  
  107.                                 write_data(a[i]);
  108.                                 delay(2);                //现在延时只有0.2ms,实际做产品时可能要加长
  109.                         }         
  110.          }
  111. }
复制代码

所有资料51hei提供下载:
数字频率计单周期实现.rar (563.21 KB, 下载次数: 87)


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

使用道具 举报

沙发
ID:1004677 发表于 2022-2-11 17:46 | 只看该作者
这个看原理图就知道不行了啊
回复

使用道具 举报

板凳
ID:121859 发表于 2022-5-10 10:38 | 只看该作者
嗯,测低频还是可以的,中高频就有些吃力了。
回复

使用道具 举报

地板
ID:1012735 发表于 2022-5-10 16:36 | 只看该作者
简单的事搞复杂了!
回复

使用道具 举报

5#
ID:1117165 发表于 2024-4-18 14:14 | 只看该作者
这样连RS  RW  E不会亮的 直接连
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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