. . . .
第2字节为尾数的高字节;第3字节为尾数的低字节。待测信号周期的3个字节定点数通过截取高16位、设置数符和计算阶码转换为上述格式的浮点数。然后浮点数算术运算对其进行处理,获得用浮点数格式表达的信号频率值。再通过浮点数到BCD码转换模块把用浮点数格式表达的信号频率值变换成本频率计的显示格式,送到显示模块显示待测信号的频率值。完成显示后,频率计都开始下一次信号的频率测量。
系统软件设计采用模块化设计方法。整个系统由初始化模块、显示模块和信号频率频率测量模块等各种功能模块组成。上电后,进入系统初始化模块,系统软件开始运行。在执行过程中,根据运行流程分别调用各个功能模块完成频率测量、量程自动切换、周期测量和测量结果显示。
五、附录
程序:
动态数码管显示程序
说明: 驱动四位一体数码管动态显示数字,可方便的移植到其它程序中。 例如:1、硬件改为三位一体或二位一体数码管,只需修改Display_Scan()函数COM个数。
2、本例中,采用了共阴数码管,如果用在共阳数码管,只需修改相应段码表。
本程序使用P0口作为段码数据发送端,P2.0-P2.3作为数码管扫描选通,
使用P0口时,因单片机部没有上拉电阻,所以要外接上拉电阻(参考阻值470欧姆).
(C)电子科技大学 测控技术与仪器 编写:郭世忠 2008/03/16 */
// STC89C52RC
// +---------------+
. . . . .
. . . .
// | |
// | | Digital Number
// | | _______________________ // | | | __ __ __ __ | // | P0.0--P0.7|===>| | | | | | | | | |
// | (a,b...g,h)| | |--| |--| |--| |--| | 4位共阴数码管
// | | | |__|.|__|.|__|.|__|.| // | | ----------------------- // | | | | | | // | | | | | | // | P2.6(COM3)|--------+ | | | // | | | | | // | P2.5(COM2)|-------------+ | | // | | | | // | P2.4(COM1)|------------------+ | // | | | // | P2.7(COM0)|-----------------------+ // +---------------+
#include
//=======================================================================
void DisplayNumber(unsigned int Num);
//=======================================================================
/*宏定义,数码管a-g各段对应的比特,更换硬件只用改动以下8行*/ #define a 0x04 // AAAA #define b 0x01 // F B #define c 0x10 // F B #define d 0x40 // GGGG #define e 0x80 // E C #define f 0x02 // E C
#define g 0x08 // DDDD H #define h 0x20
/*用宏定义自动生成段码表,很好的写法,值得学习*/ /*更换硬件无需重写段码表*/
unsigned char code LED_table[]={ a+b+c+d+e+f, //\b+c, //\a+b+d+e+g, //\a+b+c+d+g, //\b+c+f+g, //\
. . . . .
. . . .
a+c+d+f+g, //\a+c+d+e+f+g, //\a+b+c, //\a+b+c+d+e+f+g, //\a+b+c+d+f+g, //\b+c+e+f+g, //\a+f+e+g, //\d+e+f, //\g, //\0x00 //black };
#undef a #undef b #undef c #undef d #undef e #undef f #undef g
#define black 14 /* 空白 */
unsigned char DisBuff[4]; //定义显示缓冲数组 unsigned char COM;
// 定义通信端口
//===========================================================================
sbit COM0=P2^7;
sbit COM1=P2^4; //对应口线由硬件确定 sbit COM2=P2^5; sbit COM3=P2^6;
/****************************************************************************
* 名 称:DisplayNumber()
* 功 能:在数码管上显示数据。 * 入口参数:Num:显示数值 (0~9999) * 出口参数:无
* 例: DisplayNumber(1234); 显示结果: 1234
****************************************************************************/
void DisplayNumber(unsigned int Num) //显示程序 {
unsigned char i;
EA=0; //禁止总中断 for(i=0;i<4;i++) {
DisBuff[i]=Num; //拆分数字
. . . . .
. . . .
Num/=10; }
for(i=3;i>=0;i--) //循环4次 {
if (DisBuff[i]==0) DisBuff[i]=black; //消隐无效\ else break; //例如将 0123 改成 123,仅显示有效数字 }
EA=1; //总中断允许 }
/****************************************************************************
* 名 称:Display_Scan() * 功 能:数码管选通扫描。 * 入口参数:无 * 出口参数:无
****************************************************************************/
void Display_Scan() {
if(COM>3) COM=0;
COM0=1;COM1=1;COM2=1;COM3=1; //将COM0-COM3置1,全暗 switch(COM) {
case 0: P0=LED_table[DisBuff[0]]; COM0=0; break; //分别选通COM0-COM3 低电平有效
case 1: P0=LED_table[DisBuff[1]]; COM1=0; break; case 2: P0=LED_table[DisBuff[2]]; COM2=0; break;
case 3: P0=LED_table[DisBuff[3]]; COM3=0; break;
} // 与0x20位或,恰好点亮小数点位段 COM++; }
#include
unsigned int T0count; unsigned int Freq;
void Timer_Init() {
TMOD=0x01; //T0:16位定时器模式 //T2CON=0x02; //T2:16位计数器 TH0=(65536-1500)/256; //1.5ms
. . . . .
. . . .
TL0=(65536-1500)%6; TR0=1; //启动T0定时 TR2=1; //启动T2计数
ET0=1; //开启中断 EA=1; }
void MeasureFreq(void) interrupt 1 {
TH0=0xd9;//(65536-10000)/256; //10ms TL0=0x09;//(65536-10000)%6; Display_Scan(); T0count++;
if(T0count>99) //计满1s 10ms *100 = 1s {
TR0=0; //关闭T0定时 TR2=0; //关闭T2计数 T0count=0;
Freq=((unsigned int)TH2<<8)+TL2; //读取1秒钟T2所计P1^0脉冲个数(即频率),典型值6600Hz
TH2=0; //T2计数器清零 TL2=0;
TR0=1; //启动T0定时 TR2=1; //启动T2计数 } }
#include
unsigned int Time;
void SleepDelay() {
PCON|=0x01; //Sleep }
/****************************************************************** 主函数
*******************************************************************/ void main() {
Timer_Init(); //定时器T0、T2初始化 while(1) {
SleepDelay(); //休眠10ms T0中断每10ms唤醒一次
. . . . .