找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 970|回复: 1
收起左侧

51单片机测量频率-带修正测量精度

[复制链接]
ID:1143113 发表于 2025-1-16 16:35 | 显示全部楼层 |阅读模式
51单片机定时器测量脉冲信号的频率并使用数码管显示。
附件提供完整可行的源码。

  1. #include "reg52.h"
  2. #define uint unsigned int
  3. #define SMG_A_DP_PORT        P0          // 使用宏定义数码管段码口

  4. unsigned long int fre;       //存储频率计算结果
  5. unsigned char time;          //存储计时时间
  6. unsigned int count;          //计数器0中断计数


  7. typedef unsigned int u16;  // 对系统默认数据类型进行重定义
  8. typedef unsigned char u8;


  9. //共阴极数码管,0-9段码表
  10. unsigned char code Duan[]={0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F};

  11. //定义锁存器控制位
  12. sbit LSC=P2^4;
  13. sbit LSB=P2^3;
  14. sbit LSA=P2^2;

  15. unsigned char flag=0;         //标志位,用于控制计时器
  16. u16 dangwei=1;                                  //定时器的分档位,初始为1


  17. #ifndef _key_H
  18. #define _key_H


  19. //定义独立按键控制脚
  20. sbit KEY1=P3^1;
  21. sbit KEY2=P3^0;
  22. sbit KEY3=P3^2;
  23. sbit KEY4=P3^3;

  24. //定义按键状态
  25. #define KEY1_PRESS        1
  26. #define KEY2_PRESS        2
  27. #define KEY3_PRESS        3
  28. #define KEY4_PRESS        4
  29. #define KEY_UNPRESS        0

  30. #endif
  31. /*******************************************************************************
  32. * 函 数 声明
  33. *******************************************************************************/
  34. u8 key_scan(u8 mode);
  35. void timer_init(void);
  36. void smg_display(u8 dat[],u8 pos);
  37. void delay_10us(u16 ten_us);

  38. /*******************************************************************************
  39. * 函 数 名       : delay_10us
  40. * 函数功能       : 延迟ten_us*10微秒
  41. * 输    入       : ten_us
  42. * 输    出       : 无
  43. *******************************************************************************/
  44. void delay_10us(u16 ten_us)
  45. {
  46.         while(ten_us--);
  47. }

  48. /*******************************************************************************
  49. * 函 数 名       : key_scan
  50. * 函数功能       : 按键扫描并消抖
  51. * 输    入       : mode 按键操作
  52. * 输    出       : key 按键值
  53. *******************************************************************************/
  54. u8 key_scan(u8 mode)
  55. {
  56.         static u8 key=1;
  57.         if(mode)
  58.         {
  59.                 key=1;
  60.         }//模式为1时,重置按键状态
  61.         if(key==1&&(KEY1==0||KEY2==0||KEY3==0||KEY4==0))//任意按键按下
  62.         {
  63.                 delay_10us(1000);//消抖
  64.                 key=0;
  65.                 if(KEY1==0)
  66.                         return KEY1_PRESS;
  67.                 else if(KEY2==0)
  68.                         return KEY2_PRESS;
  69.                 else if(KEY3==0)
  70.                         return KEY3_PRESS;
  71.                 else if(KEY4==0)
  72.                         return KEY4_PRESS;       
  73.         }
  74.         else if(KEY1==1&&KEY2==1&&KEY3==1&&KEY4==1)        //无按键按下
  75.         {
  76.                 key=1;                       
  77.         }
  78.         return KEY_UNPRESS;       
  79. }

  80. /*******************************************************************************
  81. * 函 数 名       : timer_init
  82. * 函数功能      : 定时器0,1,2中断配置函数
  83. * 输    入       : 无
  84. * 输    出       : 无
  85. *******************************************************************************/

  86. void timer_init(void)      //定时器初始化
  87. {
  88.         TMOD=0xEE;        //定时器0和定时器1工作模式方式2,自动重装载
  89.         TH0=0;                    //定时器0重装载值高位
  90.         TL0=0;         
  91.         TR0=1;                    //启动定时器0
  92.         ET0=1;                    //使能定时器0中断,
  93.        
  94.         TH1=0;                    //定时器1重装载值高位         
  95.         TL1=0;         
  96.         TR1=1;                    //启动定时器1   
  97.         ET1=1;                    //使能定时器1中断   
  98.          
  99.         RCAP2H=(65536-62500)/256; //定时器2的自动重装载值,用于产生62.5ms的定时
  100.         RCAP2L=(65536-62500)%256; //TH2和TL2将会在中断产生时自动使TH2=RCAP2H,TL2=RCAP2L。
  101.          
  102.         TH2=RCAP2H;                         //定时器2的定时
  103.         TL2=RCAP2L;
  104.          
  105.         ET2=1;                    //使能定时器2中断  
  106.         TR2=1;                    //定时器2开始计时
  107.         EA=1;                     //使能全局中断
  108. }

  109. /*******************************************************************************
  110. * 函 数 名       : smg_display
  111. * 函数功能      : 动态数码管显示
  112. * 输    入       : dat:要显示的数据
  113.                                    pos: 从数码管左边第pos位开始显示
  114. * 输    出       : 无
  115. *******************************************************************************/
  116. void smg_display(u8 dat[],u8 pos)                //数码管显示
  117. {
  118.        
  119.         u8 i=0;
  120.         u8 pos_temp=pos-1;

  121.         for(i=pos_temp;i<8;i++)
  122.         {
  123.                    switch(i)//位选
  124.                 {
  125.                         case 0: LSC=1;LSB=1;LSA=1;break;
  126.                         case 1: LSC=1;LSB=1;LSA=0;break;
  127.                         case 2: LSC=1;LSB=0;LSA=1;break;
  128.                         case 3: LSC=1;LSB=0;LSA=0;break;
  129.                         case 4: LSC=0;LSB=1;LSA=1;break;
  130.                         case 5: LSC=0;LSB=1;LSA=0;break;
  131.                         case 6: LSC=0;LSB=0;LSA=1;break;
  132.                         case 7: LSC=0;LSB=0;LSA=0;break;
  133.                 }
  134.                 SMG_A_DP_PORT=dat[i-pos_temp];//传送段选数据
  135.                 delay_10us(100);//延时一段时间,等待显示稳定
  136.                 SMG_A_DP_PORT=0x00;//消隐
  137.         }
  138.        
  139. }

  140. /*******************************************************************************
  141. * 函 数 名       : main
  142. * 函数功能      : 主函数
  143. * 输    入       : 无
  144. * 输    出       : 无
  145. *******************************************************************************/
  146. void main()                        //主函数
  147. {
  148.         u8 key=0;
  149.         u8 time_buf[8];
  150.         fre=0;
  151.        
  152.         timer_init();             //定时器初始化
  153.         while(1)
  154.                 {
  155.                 key=key_scan(0);   //扫描按键
  156.                 if(key==KEY1_PRESS)//开始和停止计时
  157.                 {
  158.                         dangwei=1;
  159.                         timer_init();
  160.                 }       
  161.                 else if(key==KEY2_PRESS)//清除计时
  162.                 {
  163.                         dangwei=2;
  164.                         timer_init();
  165.        
  166.                 }
  167.                 else if(key==KEY3_PRESS)//清除计时
  168.                 {
  169.                         dangwei=5;
  170.                         timer_init();       
  171.                 }
  172.                 time_buf[0]=Duan[dangwei];
  173.                 time_buf[1]=Duan[fre/1000000%10];
  174.                 time_buf[2]=Duan[fre/100000%10];
  175.                 time_buf[3]=Duan[fre/10000%10];
  176.                 time_buf[4]=Duan[fre/1000%10];
  177.                 time_buf[5]=Duan[fre/100%10];
  178.                 time_buf[6]=Duan[fre/10%10];
  179.                 time_buf[7]=Duan[fre%10];
  180.                 smg_display(time_buf,1);//显示
  181.                        
  182.                 }
  183. }

  184. /*******************************************************************************
  185. 函数功能:定时器2中断函数
  186. 中断条件:定时器2溢出=》定时器2定时62.5ms
  187. *******************************************************************************/
  188. void timer2(void) interrupt 5                 //定时器2中断(62.5ms)
  189. {
  190.         time++;
  191.         TF2=0;                    //定时器2的中断标志位TF2不能够由硬件清零,所以要在中断服务程序中将其清零
  192.          
  193.         if (time==16*dangwei)             //定时时间到
  194.         {
  195.            time=0;                //计时清0
  196.            EA=0;                  //关中断  
  197.            flag = 0;
  198.            fre = ((long)count*256+TL0)/dangwei ;  //计算频率=256(单个中断的频率计数)×count(频率数)+TL0(不满一次中断的频率计数)
  199.            fre=fre/1.084;       //机器周期修正
  200.            flag= 1;         

  201.            TL0=0;                 //清零计数器0计数
  202.            TH0=0;          
  203.          
  204.            TL1=0;
  205.            TH1=0;
  206.          
  207.            count=0;               //清零计数器0计数
  208.          
  209.            EA=1;                  //开中断     
  210.          
  211.         }
  212. }

  213. /*******************************************************************************
  214. 函数功能:定时器0中断函数
  215. 中断条件: 8位计数器0溢出=》256个外部脉冲
  216. *******************************************************************************/
  217. void timer0(void) interrupt 1                           
  218. {
  219.         count++;
  220. }
复制代码


回复

使用道具 举报

ID:102702 发表于 2025-1-19 00:45 | 显示全部楼层
楼主有做实物测试过吗?
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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