如题,我写了一个8052计数器,使用定时器和计数器来完成的,具体的代码如下:
-
- /*******http://hi.baidu.com/zhangjiayue123/home************************************
- 函数功能:51单片机制作的频率计(当然这个频率计的频率范围是有限制的理论值为2Hz-1MHz)
- 编译环境:keil4
- 测试环境:科技创新实验室学习板
- 整理人:张家越 QQ:435835181
- 整理时间:2011-06-22
- 设计思想:测频率,其实就是一个定时计数的过程,在一定时间内,检测脉冲的个数,最后用脉冲个数除以时间便可以得到频率
- 修改 : LiMing WangQiDong
- 板子 : CCDZ-C board
- CPU : STC89C52RC
- 晶振 : 12MHz
- 修改部分:
- 1、LED显示部分,改为6位显示
- 2、修改delay函数 延时5ms 优化LED显示 改为一个for循环 代码更为简练
- 3、删除定时器1的8位重载计数器,
- 4、添加定时器2,并设置为16位重载计数器提高量程范围
- 在2Hz~999999Hz之间
- 信号输入引脚为P1.0(T2)
-
- 版本 : 0.4.1
- ********http://hi.baidu.com/zhangjiayue123/home****************************************/
- #include <reg52.h>
- #include <intrins.h>
- #define uchar unsigned char
- #define uint unsigned int
- sbit dula=P2^6;
- sbit wela=P2^7;
- uchar seg_du[]=
- {
- 0x3f, 0x06, 0x5b, 0x4f,0x66,
- 0x6d, 0x7d, 0x07,0x7f,0x6f
- }; //数码管的段选
- uchar dbuf[6]={0,0,0,0,0,0}; //用来装显示数据的空数组
- unsigned long count; //定时1s只之用
- unsigned long couL;
- unsigned long timer2_cnt;
- unsigned long frequency;
- void delay(void) //延时函数用于数码管动态扫描
- {
- uchar i, j;
-
- for(j=0; j<6; j++)
- for(i=0;i<110;i++)
- ;
- }
- void display_simplified(void)
- {
- unsigned int i =0;
- for(i=0; i<6; i++)
- {
- dula = 1;
- P0 = seg_du[dbuf[5-i]];
- dula = 0;
-
- P0 = 0xff;
- wela = 1;
- P0 = 0xff & ( ~(0x01 << i) );
- wela=0;
- delay();
- }
- }
- void timer0 (void)interrupt 1 //定时器0中断,用与定时计数
- {
- count++;
- if(count == 4000) //定时1s到,
- {
-
- count = 0; // 将定时标志清零
- TR2 = 0; //关闭计数器
- couL = TH2*256 + TL2 - 6; //将小于65536次脉冲的计数加上
-
- frequency = timer2_cnt * 65536 + couL;
-
- dbuf[5]=(frequency)/100000;
- dbuf[4]=(frequency)/10000%10;
- dbuf[3]=(frequency)/1000%10;
- dbuf[2]=(frequency)/100%10;
- dbuf[1]=(frequency)%100/10;
- dbuf[0]=(frequency)%10; //显示处理函数
-
- timer2_cnt = 0; //计数器2计数器清零
- TH2 = (0xFFFF-65530)/256;
- TL2 = (0xFFFF-65530)%256; // 打开计数器中断
-
- TR2=1; //开启计数器2,使之工作
- }
- }
- //timer 2 interrupt ISR
- void timer_2_ISR(void) interrupt 5
- {
- TF2=0;//!!!注意!!! 定时器2必须由软件对溢出标志位清零,硬件不能清零,这里与定时器0和定时器1不同!!!
- timer2_cnt++; //TL2+TH2 = 65536 时,计数器2的 TF2置1,引发中断
- /*说明有几个65536溢出的次数,因为大于65536的时候,TH1+TL1 8+8位 2^16=65536的空间就容不下了,就会溢出*/
- }
- //timer 0 timer mode mode-2: 8 bits-reload
- //250us*4000=1s
- void timer0_init() //定时器0初始化
- {
- TMOD=0x02; // 设置定时器0,和计数器1的模式
- TH0=6;
- TL0=6; //定时器的初值,用于中断一次计时250us
- ET0=1; //开定时器0中断
- TR0=1; //开定时器0
- }
- //用作计数器:16位重载模式的计数器
- void timer2_init(void)
- {
- RCAP2H=(0xFFFF-65530)/256;
- RCAP2L=(0xFFFF-65530)%256; //12MHz晶振下定时50ms,自动重装
- TH2=RCAP2H;
- TL2=RCAP2L; //定时器2赋初值
-
- //16bits reload
- CP_RL2 = 0; //reload mode
- T2MOD &= 0x00; //T2OE = DCEN = 0;
- C_T2 = 1; //counter mode
- EXEN2 = 0;
- ET2=1;
- TR2=1; //启动定时器2
- }
- void main()
- {
- count=0;
- timer0_init();
- timer2_init();
- EA=1; //开总中断
- while(1)
- {
- display_simplified();
- }
- }
-
-
可是试验后,在频率为480KHz左右的信号就测不准了,,我怀疑是不是数据类型的大小不够,于是我把
count; //定时1s只之用
couL;
timer2_cnt;
都改为long型,可是还是无济于事,
那位大侠能否解释下啊为什么啊?谢谢
|