找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

搜索
查看: 995|回復: 1
收起左側

51單片機測量頻率-帶修正測量精度

[復制鏈接]
ID:1143113 發(fā)表于 2025-1-16 16:35 | 顯示全部樓層 |閱讀模式
51單片機定時器測量脈沖信號的頻率并使用數(shù)碼管顯示。
附件提供完整可行的源碼。

  1. #include "reg52.h"
  2. #define uint unsigned int
  3. #define SMG_A_DP_PORT        P0          // 使用宏定義數(shù)碼管段碼口

  4. unsigned long int fre;       //存儲頻率計算結果
  5. unsigned char time;          //存儲計時時間
  6. unsigned int count;          //計數(shù)器0中斷計數(shù)


  7. typedef unsigned int u16;  // 對系統(tǒng)默認數(shù)據(jù)類型進行重定義
  8. typedef unsigned char u8;


  9. //共陰極數(shù)碼管,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. //定義按鍵狀態(tài)
  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. * 函 數(shù) 聲明
  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. * 函 數(shù) 名       : delay_10us
  40. * 函數(shù)功能       : 延遲ten_us*10微秒
  41. * 輸    入       : ten_us
  42. * 輸    出       : 無
  43. *******************************************************************************/
  44. void delay_10us(u16 ten_us)
  45. {
  46.         while(ten_us--);
  47. }

  48. /*******************************************************************************
  49. * 函 數(shù) 名       : key_scan
  50. * 函數(shù)功能       : 按鍵掃描并消抖
  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時,重置按鍵狀態(tài)
  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. * 函 數(shù) 名       : timer_init
  82. * 函數(shù)功能      : 定時器0,1,2中斷配置函數(shù)
  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的自動重裝載值,用于產(chǎn)生62.5ms的定時
  100.         RCAP2L=(65536-62500)%256; //TH2和TL2將會在中斷產(chǎn)生時自動使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. * 函 數(shù) 名       : smg_display
  111. * 函數(shù)功能      : 動態(tài)數(shù)碼管顯示
  112. * 輸    入       : dat:要顯示的數(shù)據(jù)
  113.                                    pos: 從數(shù)碼管左邊第pos位開始顯示
  114. * 輸    出       : 無
  115. *******************************************************************************/
  116. void smg_display(u8 dat[],u8 pos)                //數(shù)碼管顯示
  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];//傳送段選數(shù)據(jù)
  135.                 delay_10us(100);//延時一段時間,等待顯示穩(wěn)定
  136.                 SMG_A_DP_PORT=0x00;//消隱
  137.         }
  138.        
  139. }

  140. /*******************************************************************************
  141. * 函 數(shù) 名       : main
  142. * 函數(shù)功能      : 主函數(shù)
  143. * 輸    入       : 無
  144. * 輸    出       : 無
  145. *******************************************************************************/
  146. void main()                        //主函數(shù)
  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. 函數(shù)功能:定時器2中斷函數(shù)
  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(單個中斷的頻率計數(shù))×count(頻率數(shù))+TL0(不滿一次中斷的頻率計數(shù))
  199.            fre=fre/1.084;       //機器周期修正
  200.            flag= 1;         

  201.            TL0=0;                 //清零計數(shù)器0計數(shù)
  202.            TH0=0;          
  203.          
  204.            TL1=0;
  205.            TH1=0;
  206.          
  207.            count=0;               //清零計數(shù)器0計數(shù)
  208.          
  209.            EA=1;                  //開中斷     
  210.          
  211.         }
  212. }

  213. /*******************************************************************************
  214. 函數(shù)功能:定時器0中斷函數(shù)
  215. 中斷條件: 8位計數(shù)器0溢出=》256個外部脈沖
  216. *******************************************************************************/
  217. void timer0(void) interrupt 1                           
  218. {
  219.         count++;
  220. }
復制代碼


回復

使用道具 舉報

ID:102702 發(fā)表于 2025-1-19 00:45 | 顯示全部樓層
樓主有做實物測試過嗎?
回復

使用道具 舉報

您需要登錄后才可以回帖 登錄 | 立即注冊

本版積分規(guī)則

手機版|小黑屋|51黑電子論壇 |51黑電子論壇6群 QQ 管理員QQ:125739409;技術交流QQ群281945664

Powered by 單片機教程網(wǎng)

快速回復 返回頂部 返回列表