单片机频率计

求课程设计--单片机频率计

1.实验任务

  利用51单片机的T0、T1的定时计数器功能,来完成对输入的信号进行频率计数,计数的频率结果通过8位动态数码管显示出来。要求能够对0-250KHZ的信号频率进行准确计数,计数误差不超过±1HZ。

2.电路原理图

    见插图

3.程序设计内容

(1).定时/计数器T0和T1的工作方式设置,由图可知,T0是工作在计数状态下,对输入的频率信号进行计数,但对工作在计数状态下的T0,最大计数值为fOSC/24,由于fOSC=12MHz,因此:T0的最大计数频率为250KHz。对于频率的概念就是在一秒只数脉冲的个数,即为频率值。所以T1工作在定时状态下,每定时1秒中到,就停止T0的计数,而从T0的计数单元中读取计数的数值,然后进行数据处理。送到数码管显示出来。

(2).T1工作在定时状态下,最大定时时间为65ms,达不到1秒的定时,所以采用定时50ms,共定时20次,即可完成1秒的定时功能。

4.C语言源程序

/******************************************************************************

*                      定时器+计数器测频

*

* file: frequency.c

* name: zhzhchang     

* time: 2010.3.17

* V 1.0

* blog:http://blog.csdn.net/zhzht19861011

* Nots: 本程序定义6个数码管,经过实测,在200HZ~50KHZ时结果较准确,误差小于0.4%,

*       50KHZ以上频率未进行测量.据资料表明,可以测量到120KHZ,本程序未证明.

*********************************************************************************/

#include<reg52.h>

 

bit int_flag; //定时器0 1S到标志位

unsigned char volatile int_count;   //定时器0中断次数

unsigned char volatile T1count;    //定时器1中断次数

unsigned char code dofly[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};// 显示段码值0123456789

unsigned long sum;    //1S内脉冲总个数

unsigned char led[6];   //LED显示缓存

 

///////////////软件延时/////////////

void delay(unsigned int cnt) 

{

 while(--cnt);

}

///定时器0初始化

void init_t0(void)

{

 TMOD=(TMOD&0xF0)||0x01;   //定时器0工作于方式1

 TH0=(65536-50000)/256;   //定时50ms

 TL0=(65535-50000)%256;

}

// 定时器1初始化

void init_t1(void)

{

 TMOD=(TMOD&0x0F)|0x50;   //timer 1 for count

 TH1 =0x00;

 TL1 =0x00;

}

//显示

void disp(void)

{

 unsigned char i;

 for(i=0;i<6;i++)

 {

  P0=dofly[(led[i])];//取显示数据

     P2=5-i;  //取段码

     delay(100); //扫描间隙延时,根据单片机调整,延时1ms即可

 }

}

///////////////////////////////////////////////////////

void main (void)

{

 EA=1;      //开总中断

 init_t0();    //初始化定时器

 init_t1();   

 TR0=1;     //定时器开始工作

 TR1=1;

 ET0=1;   //开T0中断

   

 while(1)

{

 if(int_flag==1)

 {

  int_flag=0;

  sum=TL1+TH1*256+T1count*65536;   //计算1秒内的脉冲个数

  //以下将数据格式化,转成LED可显示的BCD码

  led[0]=sum%10; //最低位

  sum=sum/10;

  led[1]=sum%10; //第二位

  sum=sum/10;

  led[2]=sum%10;

  sum=sum/10;

  led[3]=sum%10;

  sum=sum/10;

  led[4]=sum%10;

  led[5]=sum/10;

  int_count=0x00;

  T1count=0;

  TH1=0x00;

  TL1=0x00;

  TR1=1;

 }

 disp();

}

}

//定时器0中断服务程序

void int_t0(void) interrupt 1

{

 TH0=(65535-50000)/256;

 TL0=(65535-50000)%256;

 int_count++;

 if(int_count==20)

 {

  TR1=0;

  int_flag=1;

  int_count=0x00;

 }

}

//定时器1中断服务程序

void int_t1(void) interrupt 3 

  T1count++; 

}   

别说你的设计要求用汇编啊!!!

不过既然是课程设计,我这个只是给你参考,你自己一定要弄懂,变成自己的。我实测过,程序没问题,但用到你的硬件上可能需要改一下,因为你的硬件数码管不一定和我的硬件接法一样,但整体思路我都给你了。

温馨提示:答案为网友推荐,仅供参考