天天看点

基于51单片机的数字频率计

1.简介

数字频率计是现代科研生产中不可或缺的测量仪器,它以十进制数显示被测频率,基本功能是测量正弦信号,方波信号,及其它各种单位时间内变化的物理量。  

本系统采用AT89C52单片机智能控制,结合外围电子电路,设计的频率计性能稳定。在软件设计上采用了单片机的C语言设计,通过单片机内部定时/计数器同时动作,在测量频率时将测频率和测周期相结合,提高了频率计的测量准确性。      

测量结果在LCD1602上输出显示,结果精确到整数位。频率计的软件设计,系统软件设计简单明了,适用于测量频率从1~99999Hz的脉冲信号。

2.硬件设计

基于51单片机的数字频率计

数字频率计的硬件原理比较简单,就不仔细介绍了。其主要以下部分组成:

  1. 单片机最小系统
  2. LCD1602显示屏电路
  3. 频率信号输入端子
  4. 系统电源

3.软件设计

(1)LCD1602驱动程序

#define CHECK_BUSY

sbit RS = P2^2;   //定义端口 
sbit RW = P2^3;
sbit EN = P2^4;

#define RS_CLR RS=0 
#define RS_SET RS=1

#define RW_CLR RW=0 
#define RW_SET RW=1 

#define EN_CLR EN=0
#define EN_SET EN=1

#define DataPort P0

/*------------------------------------------------
              判忙函数
------------------------------------------------*/
 bit LCD_Check_Busy(void) 
 { 
#ifdef CHECK_BUSY
 DataPort= 0xFF; 
 RS_CLR; 
 RW_SET; 
 EN_CLR; 
 _nop_(); 
 EN_SET;
 return (bit)(DataPort & 0x80);
#else
 return 0;
#endif
 }
/*------------------------------------------------
              写入命令函数
------------------------------------------------*/
 void LCD_Write_Com(unsigned char com) 
 {  
 while(LCD_Check_Busy()); //忙则等待
 RS_CLR; 
 RW_CLR; 
 EN_SET; 
 DataPort= com; 
 _nop_(); 
 EN_CLR;
 }
/*------------------------------------------------
              写入数据函数
------------------------------------------------*/
 void LCD_Write_Data(unsigned char Data) 
 { 
 while(LCD_Check_Busy()); //忙则等待
 RS_SET; 
 RW_CLR; 
 EN_SET; 
 DataPort= Data; 
 _nop_();
 EN_CLR;
 }

/*------------------------------------------------
                清屏函数
------------------------------------------------*/
 void LCD_Clear(void) 
 { 
 LCD_Write_Com(0x01); 
 DelayMs(5);
 }
/*------------------------------------------------
              写入字符串函数
------------------------------------------------*/
 void LCD_Write_String(unsigned char x,unsigned char y,unsigned char *s) 
 {     
       
 while (*s) 
 	{     
 LCD_Write_Char(x,y,*s);     
 s ++;  x++;   
 	}
 }
/*------------------------------------------------
              写入字符函数
------------------------------------------------*/
void LCD_Write_Char(unsigned char x,unsigned char y,unsigned char Data) 
 {     
 if (y == 0) 
 	{     
 	LCD_Write_Com(0x80 + x);     
 	}    
 else 
 	{     
 	LCD_Write_Com(0xC0 + x);     
 	}        
 LCD_Write_Data( Data);  
 }
/*------------------------------------------------
              初始化函数
------------------------------------------------*/
 void LCD_Init(void) 
 {
   LCD_Write_Com(0x38);    /*显示模式设置*/ 
   DelayMs(5); 
   LCD_Write_Com(0x38); 
   DelayMs(5); 
   LCD_Write_Com(0x38); 
   DelayMs(5); 
   LCD_Write_Com(0x38);  
   LCD_Write_Com(0x08);    /*显示关闭*/ 
   LCD_Write_Com(0x01);    /*显示清屏*/ 
   LCD_Write_Com(0x06);    /*显示光标移动设置*/ 
   DelayMs(5); 
   LCD_Write_Com(0x0C);    /*显示开及光标设置*/
   }

           

(2)外部频率信号处理程序

外部频率信号输入到单片机的外部计数器INT0(P3.2),计数器对每个脉冲进行计数,并采用内部定时器定时1秒钟,然后统计一秒钟内计数器的数值即可得出外部信号的频率大小

sbit LED=P1^2;    //定义LED端口
bit OVERFLOWFLAG;
bit TIMERFLAG;
/*------------------------------------------------
                    定时器0初始化子程序
					本程序用于计数
------------------------------------------------*/
void Init_Timer0(void)
{
 TMOD |= 0x01 | 0x04;	  //使用模式1,16位计数器,使用"|"符号可以在使用多个定时器时不受影响		     
 TH0=0x00;	      //给定初值
 TL0=0x00;         
 EA=1;            //总中断打开
 ET0=1;           //定时器中断打开
 TR0=1;           //定时器开关打开
}
/*------------------------------------------------
                    定时器1初始化子程序
					本程序用于定时
------------------------------------------------*/
void Init_Timer1(void)
{
 TMOD |= 0x10;	  //使用模式1,16位定时器,使用"|"符号可以在使用多个定时器时不受影响 
 TH1=HIGH;	      //给定初值,这里使用定时器最大值从0开始计数一直到65535溢出
 TL1=LOW;
 EA=1;            //总中断打开
 ET1=1;           //定时器中断打开
 TR1=1;           //定时器开关打开
}
/*------------------------------------------------
                 定时器0中断子程序
------------------------------------------------*/
void Timer0_isr(void) interrupt 1
{
 TH0=00;	      //重新给定初值
 TL0=00; 

 OVERFLOWFLAG=1;  //溢出标志

}
/*------------------------------------------------
                 定时器1中断子程序
------------------------------------------------*/
void Timer1_isr(void) interrupt 3
{
 static unsigned char i;
 TH1=HIGH;		 //重新赋值10ms
 TL1=LOW;

 i++;
 if(i==10)       //100ms 计数时间单位,得出100ms脉冲个数 x10就是1s中脉冲个数,即为频率 Hz 
   {
   i=0;
   TR0=0;        //2个定时器关闭
   TR1=0;
   TIMERFLAG=1;  //标志位清零
   TH1=HIGH;	 //重新赋值
   TL1=LOW;
   }
}
           

(3)主程序

/*------------------------------------------------
                    主程序
------------------------------------------------*/
main()
{
 unsigned  long int a;
 char temp[16];      //定义字符显示缓冲数组
 Init_Timer0();      //初始化定时器0
 Init_Timer1();      //初始化定时器1
 LCD_Init();         //初始化液晶屏
 DelayMs(10);        //延时用于稳定,可以去掉
 LCD_Clear();        //清屏
 LCD_Write_String(0,0,"Frequency Meter");//写入第一行信息,主循环中不再更改此信息,所以在while之前写入
 while(1)
 {
  if(OVERFLOWFLAG)//检测溢出标志,如果溢出表明频率过高,显示溢出信息
    {
	 OVERFLOWFLAG=0;//标志清零
     LCD_Write_String(0,1,"overflow >655KHz");
	}
  if(TIMERFLAG)      //定时100ms到,做数据处理
    {
	 a=TL0+TH0*256;//读取计数值
	 a=a*10;     //扩大到实际值
     sprintf(temp,"FREQ:%08.0f Hz",(float)a);
     LCD_Write_String(0,1,temp);//显示到液晶第二行
	 TR0=1;                     //2个定时器打开
	 TR1=1;
	 TH0=0;                     //保证计数器初值为0
	 TL0=0;
	 TIMERFLAG=0;               //打开计时计数标志
	 
	}
  }
}

           

源码+电路图 下载:关注公众号,首页回复“频率计”获取资料

基于51单片机的数字频率计

继续阅读