找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 3903|回复: 5
收起左侧

带origin校正的精确度很高的频率计仿真及源程序

[复制链接]
ID:137190 发表于 2016-9-9 00:23 | 显示全部楼层 |阅读模式
带origin校正的频率计的仿真原理图:
0.png


下面是数字频率计的误差分析:
0.png

误差数据:
0.png

高精度频率计源程序:
  1. #include<reg52.h>
  2. #include<intrins.h>

  3. sbit RS=P2^6;
  4. sbit RW=P2^5;
  5. sbit E=P2^7;
  6. #define LCD_data  P0                                       
  7. uchar   code  table1[10]={"f=      Hz"};

  8. uchar code f_table[88]={13,14,15,16,17,        18,        19,        20,        21,        22,        23,        24,        25,        26,        27,        28,        29,        30,        31,        32,        33,        34,        35,        36,        37,        38,        39,        40,        41,        42,        43,        44,        45,        46,        47,        48,        49,        50,        51,        52,        53,        54,        55,        56,        57,        58,        59,        60,        61,        62,        63,        64,        65,        66,        67,        68,        69,        70,        71,        72,        73,        74,        75,        76,        77,        78,        79,        80,        81,        82,        83,        84,        85,        86,        87,        88,        89,        90,        91,        92,        93,        94,        95,        96,        97,        98,        99,        100};
  9. uchar code f_correct[88]={9,10,        11,        12,        12,        12,        13,        14,        15,        16,        17,        18,        18,        18,        19,        20,        21,        21,        22,        23,        24,        25,        25,        26,        26,        27,        28,        29,        29,        30,        30,        31,        32,        33,        33,        34,        35,        35,        36,        37,        38,        38,        39,        40,        41,        41,        42,        42,        43,        44,        45,        45,        46,        47,        48,        49,        49,        50,        51,        51,        52,        53,        54,        54,        55,        55,        56,        57,        57,        58,        59,        60,        60,        62,        62,        63,        64,        64,        65,        66,        66,        67,        67,        68,        69,        70,        71,        71,};

  10. uchar a6,a5,a4,a3,a2,a1;
  11. uchar flag;
  12. unsigned long cnt;
  13. uchar f_cnt;


  14. /********************************/

  15. void delay_us(); //18us
  16. void delay_ms(uint);
  17. void lcd_init();
  18. void lcd_write_com(uchar com);
  19. void lcd_write_dat(uchar dat);
  20. void lcd_init();
  21. void lcd_display(uchar add,uchar dat);
  22. /***********************************/

  23. void delay_us()
  24. {
  25.         uchar x;
  26.         for(x=0;x<5;x++);
  27. }

  28. void delay_ms(uint z)
  29. {
  30.         uint x,y;
  31.         for(x=0;x<z;x++)
  32.                 for(y=0;y<123;y++);
  33. }
  34. void lcd_write_com(uchar com)
  35. {
  36.   E=0;
  37.   RS=0;
  38.   RW=0;
  39.   delay_us();
  40.   LCD_data=com;
  41.   E=1;           //高脉冲写入数据
  42.   delay_us();
  43.   E=0;
  44. }
  45. void lcd_write_dat(uchar dat)
  46. {
  47.   E=0;
  48.   RS=1;
  49.   RW=0;
  50.   delay_us();
  51.   LCD_data=dat;
  52.   E=1;           //高脉冲写入数据
  53.   delay_us();
  54.   E=0;
  55. }
  56. void lcd_init()                  //lcd初始化
  57. {
  58.         delay_ms(15);
  59.         lcd_write_com(0x38);
  60.         delay_ms(10);
  61.         lcd_write_com(0x0c);
  62.         lcd_write_com(0x06);
  63.         lcd_write_com(0x01);
  64.         delay_ms(2);
  65.         
  66.         
  67. }
  68. void timer_init(void)  //定时器初始化
  69. {
  70.                 TMOD=0X51;
  71.     PT0=1;     /*中断优先*/
  72.         TH0=0x3c;
  73.         TL0=0xb0;
  74.         TH1=0;
  75.         TL1=0;
  76.         ET0=1;
  77.         ET1=1;
  78.         TR0=1;
  79.         TR1=1;
  80.         EA=1;        
  81. }
  82. void lcd_display(uchar add,uchar dat)           //lcd显示(地址,数据)
  83. {

  84.         lcd_write_com(add);
  85.         
  86.         lcd_write_dat(dat);
  87.         delay_us();

  88. }
  89. void real_display(void)
  90. {
  91.         lcd_display(0x80,table1[0]);
  92.                         lcd_display(0x80+1,table1[1]);
  93.                         if(a6)
  94.                           lcd_display(0x80+2,0x30+a6);
  95.                         else
  96.                         lcd_display(0x80+2,' ');


  97.                         if(a6||a5)
  98.                         lcd_display(0x80+3,0x30+a5);
  99.                         else
  100.                                  lcd_display(0x80+3,' ');


  101.                         if(a6||a5||a4)
  102.                         lcd_display(0x80+4,0x30+a4);        
  103.                         else
  104.                    lcd_display(0x80+4,' ');


  105.                         if(a6||a5||a4||a3)
  106.                         lcd_display(0x80+5,0x30+a3);        
  107.                         else
  108.                     lcd_display(0x80+5,' ');


  109.                         if(a6||a5||a4||a3||a2)
  110.                         lcd_display(0x80+6,0x30+a2);
  111.                         else
  112.                         lcd_display(0x80+6,' ');

  113.                         
  114.                         lcd_display(0x80+7,0x30+a1);
  115.                
  116.                         lcd_display(0x80+8,table1[8]);
  117.                         lcd_display(0x80+9,table1[9]);
  118. }

  119. void correct(void)                        //误差修正函数
  120. {
  121.         uchar i,k;
  122.         unsigned long wucha;
  123.         if(cnt<100000)                   //100KHz以内的修正
  124.         {
  125.                 if(cnt>980&&cnt<2100)     cnt-=1;
  126.                 if(cnt>=2100&&cnt<3900)   cnt-=2;
  127.                 if(cnt>=3900&&cnt<4800)   cnt-=3;
  128.                 if(cnt>=4800&&cnt<5700)   cnt-=4;
  129.                 if(cnt>=5700&&cnt<8000)   cnt-=5;
  130.                 if(cnt>=8000&&cnt<9100)          cnt-=6;
  131.                 if(cnt>=9100&&cnt<10900)  cnt-=7;
  132.                 if(cnt>=10900&&cnt<11900) cnt-=8;
  133.                 if(cnt>=11900&&cnt<13000) cnt-=9;
  134.                 if(cnt>=13000&&cnt<=100000)
  135.                 {
  136.                         k=cnt/1000;
  137.                         for(i=0;i<88;i++)
  138.                         {
  139.                                 if(k==f_table[i])
  140.                                 {
  141.                                         cnt-=f_correct[i];
  142.                                 }
  143.                         }
  144.                 }
  145.                
  146.                
  147.         }
  148.         if(cnt>100000)         
  149.         {
  150.                 wucha=(cnt/1000)*73065/100000;
  151.                 cnt-=wucha;
  152.         }
  153. }

  154. void main()
  155. {

  156.     timer_init();
  157.         lcd_init();
  158.         while(1)
  159.         {               
  160.                    if(flag==1)
  161.                    {
  162.                         real_display();
  163.                         flag=0;
  164.                         }
  165.                
  166.         
  167.         }
  168.         
  169. }
  170. void timer0() interrupt 1
  171. {
  172.         uchar timer0;
  173.         
  174.         TH0=0x3c;          //50ms
  175.         TL0=0xb0;
  176.         timer0++;
  177.         if(timer0==20)
  178.         {
  179.                 TR1=0;          //关闭的计数器
  180.                 EA=0;
  181.                 cnt=TL1+TH1*256+f_cnt*65536;
  182.                 correct();
  183.                 timer0=0;
  184.         
  185.                 a6=cnt%10000000/100000;
  186.                 a5=cnt%100000/10000;
  187.                 a4=cnt%10000/1000;
  188.                 a3=cnt%1000/100;
  189.                 a2=cnt%100/10;
  190.                 a1=cnt%10;  
  191.                 flag=1;
  192.              TH1=0;
  193.                 TL1=0;
  194.                 TH0=0x3c;
  195.              TL0=0xb0;
  196.                 cnt=0;
  197.                 f_cnt=0;
  198.                 EA=1;
  199.                 TR1=1;           //打开计数器
  200.         
  201.         
  202.         }
  203.         

  204. }        

  205. void int1() interrupt 3
  206. {
  207.          f_cnt++;
  208. }
复制代码
0.png

下载:
频率计.zip (878.8 KB, 下载次数: 27)
回复

使用道具 举报

ID:150693 发表于 2017-4-6 11:54 | 显示全部楼层
谢谢楼主的分享,51黑有你更精彩
回复

使用道具 举报

ID:194701 发表于 2017-5-1 09:03 | 显示全部楼层
谢谢楼主的分享
回复

使用道具 举报

ID:345426 发表于 2019-6-15 13:00 | 显示全部楼层
谢谢楼主的分享
回复

使用道具 举报

ID:150257 发表于 2019-6-15 20:09 | 显示全部楼层
感谢大佬分享
回复

使用道具 举报

ID:573825 发表于 2019-6-28 01:23 | 显示全部楼层
谢谢谢谢
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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