8052计数器为啥不能测在480Khz以上的频率

[复制链接]
2733|3
 楼主| wdliming 发表于 2012-5-15 10:38 | 显示全部楼层 |阅读模式
如题,我写了一个8052计数器,使用定时器和计数器来完成的,具体的代码如下:

  1. /*******http://hi.baidu.com/zhangjiayue123/home************************************
  2. 函数功能:51单片机制作的频率计(当然这个频率计的频率范围是有限制的理论值为2Hz-1MHz)
  3. 编译环境:keil4
  4. 测试环境:科技创新实验室学习板
  5. 整理人:张家越      QQ:435835181
  6. 整理时间:2011-06-22
  7. 设计思想:测频率,其实就是一个定时计数的过程,在一定时间内,检测脉冲的个数,最后用脉冲个数除以时间便可以得到频率
  8. 修改 :  LiMing WangQiDong
  9. 板子 : CCDZ-C board
  10. CPU  :  STC89C52RC
  11. 晶振 : 12MHz
  12. 修改部分:
  13. 1、LED显示部分,改为6位显示
  14. 2、修改delay函数 延时5ms 优化LED显示 改为一个for循环 代码更为简练
  15. 3、删除定时器1的8位重载计数器,
  16. 4、添加定时器2,并设置为16位重载计数器提高量程范围

  17. 在2Hz~999999Hz之间
  18. 信号输入引脚为P1.0(T2)

  19. 版本 :  0.4.1
  20. ********http://hi.baidu.com/zhangjiayue123/home****************************************/
  21. #include <reg52.h>
  22. #include <intrins.h>
  23. #define uchar unsigned char
  24. #define uint unsigned int
  25. sbit dula=P2^6;
  26. sbit wela=P2^7;
  27. uchar seg_du[]=
  28. {
  29. 0x3f, 0x06, 0x5b, 0x4f,0x66,
  30. 0x6d, 0x7d, 0x07,0x7f,0x6f
  31. };  //数码管的段选
  32. uchar dbuf[6]={0,0,0,0,0,0};       //用来装显示数据的空数组
  33. unsigned long count;     //定时1s只之用
  34. unsigned long couL;
  35. unsigned long timer2_cnt;
  36. unsigned long frequency;
  37. void delay(void)       //延时函数用于数码管动态扫描
  38. {
  39. uchar i, j;

  40. for(j=0; j<6; j++)
  41.   for(i=0;i<110;i++)
  42.    ;
  43. }
  44. void display_simplified(void)
  45. {
  46. unsigned int i =0;
  47. for(i=0; i<6; i++)
  48. {
  49.   dula = 1;
  50.   P0 = seg_du[dbuf[5-i]];
  51.   dula = 0;
  52.   
  53.   P0 = 0xff;
  54.   wela = 1;
  55.   P0 = 0xff & ( ~(0x01 << i) );
  56.   wela=0;
  57.   delay();
  58. }
  59. }
  60. void timer0 (void)interrupt 1  //定时器0中断,用与定时计数
  61. {
  62. count++;
  63. if(count == 4000)     //定时1s到,
  64. {
  65.   
  66.   count = 0;       // 将定时标志清零
  67.   TR2 = 0;         //关闭计数器
  68.   couL = TH2*256 + TL2 - 6;        //将小于65536次脉冲的计数加上
  69.   
  70.   frequency = timer2_cnt * 65536 + couL;
  71.    
  72.   dbuf[5]=(frequency)/100000;
  73.   dbuf[4]=(frequency)/10000%10;
  74.   dbuf[3]=(frequency)/1000%10;
  75.   dbuf[2]=(frequency)/100%10;
  76.   dbuf[1]=(frequency)%100/10;
  77.   dbuf[0]=(frequency)%10;       //显示处理函数
  78.    
  79.   timer2_cnt = 0;            //计数器2计数器清零
  80.   TH2 = (0xFFFF-65530)/256;
  81.   TL2 = (0xFFFF-65530)%256;        // 打开计数器中断
  82.   
  83.   TR2=1;                //开启计数器2,使之工作
  84. }
  85. }

  86. //timer 2 interrupt ISR
  87. void timer_2_ISR(void) interrupt 5
  88. {
  89. TF2=0;//!!!注意!!! 定时器2必须由软件对溢出标志位清零,硬件不能清零,这里与定时器0和定时器1不同!!!
  90. timer2_cnt++; //TL2+TH2 = 65536 时,计数器2的  TF2置1,引发中断
  91. /*说明有几个65536溢出的次数,因为大于65536的时候,TH1+TL1 8+8位 2^16=65536的空间就容不下了,就会溢出*/
  92. }
  93. //timer 0 timer mode mode-2:  8 bits-reload
  94. //250us*4000=1s
  95. void timer0_init()  //定时器0初始化
  96. {
  97. TMOD=0x02;    //  设置定时器0,和计数器1的模式
  98. TH0=6;
  99. TL0=6;      //定时器的初值,用于中断一次计时250us
  100. ET0=1;      //开定时器0中断
  101. TR0=1;      //开定时器0
  102. }

  103. //用作计数器:16位重载模式的计数器
  104. void timer2_init(void)
  105. {
  106. RCAP2H=(0xFFFF-65530)/256;
  107. RCAP2L=(0xFFFF-65530)%256; //12MHz晶振下定时50ms,自动重装
  108. TH2=RCAP2H;
  109. TL2=RCAP2L;     //定时器2赋初值

  110. //16bits reload
  111. CP_RL2 = 0;  //reload mode
  112. T2MOD &= 0x00; //T2OE = DCEN = 0;
  113. C_T2 = 1;  //counter mode
  114. EXEN2 = 0;
  115. ET2=1;
  116. TR2=1;    //启动定时器2
  117. }
  118. void main()
  119. {
  120. count=0;
  121. timer0_init();
  122. timer2_init();
  123. EA=1;     //开总中断
  124. while(1)
  125. {
  126.   display_simplified();
  127. }
  128. }



可是试验后,在频率为480KHz左右的信号就测不准了,,我怀疑是不是数据类型的大小不够,于是我把
count;     //定时1s只之用
couL;
timer2_cnt;
都改为long型,可是还是无济于事,
那位大侠能否解释下啊为什么啊?谢谢
delin17 发表于 2012-5-15 11:11 | 显示全部楼层
51晶振12M, 指令频率才1M。你自己算一下,你中断用了多长时间
 楼主| wdliming 发表于 2012-5-15 18:56 | 显示全部楼层
哦,哦买噶,应该是12MHZ的晶振不够用了。。。谢谢啊
lyjian 发表于 2012-5-15 19:00 | 显示全部楼层
和12M晶振没关系
方法有问题而已
您需要登录后才可以回帖 登录 | 注册

本版积分规则

个人签名:我的未来不是梦

76

主题

914

帖子

4

粉丝
快速回复 在线客服 返回列表 返回顶部