STC单片机频率计数显示

发布于:2024-05-07 ⋅ 阅读:(29) ⋅ 点赞:(0)

2014 4 6

/*主函数:

功能描述:  利用AT89S51单片机的T0、T1的定时计数器功能,来完成对输入的信号进行

            频率计数,计数的频率结果通过8位动态数码管显示出来。要求能够对0-250KHZ

                的信号频率进行准确计数,计数误差不超过±hz

程序设计内容: 

                1)定时/计数器T0和T1的工作方式设置,由图可知,T0是工作在计数状态下,

                对输入的频率信号进行计数,当T/C工作在定时器时,计数脉冲来自外部脉冲

                输入管脚T0(P3。4)或T1(P3。5),当T0或T1产生负跳变时计数器加1。识别

                管脚的负跳变需要两个机器周期,即24个振荡周期。所以,以T0或T1脚输入的

                可计数外部脉冲的最高频率为1/24Fosc。但对工作在计数状态下的T0,

                最大计数值为fOSC/24,由于fOSC=12MHz 因此:T0的最大计数频率为500KHz?

                高于此频率将出错。

                对于频率的概念就是在一秒只数脉冲的个数,即为频率值

                所以T1工作在定时状态下,每定时1秒钟到,就停止T0的计数,

                而从T0的计数单元中读取计数的数值,然后进行数据处理。

                送到数码管显示出来。 

                2)T1工作在定时状态下,最大定时时间为65ms,达不到1秒的定时,

*/

//;==================================================================================

//;主程序开始

//;==================================================================================

#include<reg52.h>

#include<absacc.h>

#include <intrins.h>

#define uint unsigned int

#define uchar unsigned char

extern const uchar NoDisp=0;        //无显示

extern const uchar NoCur=1;        //有显示无光标

extern const uchar CurNoFlash=2;    //有光标但不闪烁

extern const uchar CurFlash=3;        //有光标且闪烁

extern void LcdPos(uchar,uchar);    //确定光标位置

extern void LcdWd(uchar);            //写字符

extern void LcdWc(uchar);            //送控制字(检测忙信号)

extern void LcdWcn(uchar );        //送控制字子程序(不检测忙信号)

extern void mDelay(uchar );        //延时,毫秒数由j决定

extern void WaitIdle(void);            //正常读写操作之前检测LCD控制器状态

extern void RstLcd(void);        //复位LCD控制器

extern void WriteChar(uchar c,uchar xPos,uchar yPos);//在指定的行与列显示指定的字符,xpos:行,ypos:列,c:待显示字符

extern void WriteString(uchar *s,uchar xPos,uchar yPos);

extern void SetCur(uchar Para);    //设置光标

extern void ClrLcd(void);    //清屏命令

extern void WaitIdle(void);  //    正常读写操作之前检测LCD控制器状态

extern void mDelay(uchar j);

#include <reg52.h>

#include <intrins.h>

#define uint unsigned int

#define uchar unsigned char

sbit    RS=P3^5;

sbit    RW=P3^6;

sbit    EN=P3^7;

#define DPORT    P2

unsigned char code table1[]={0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39};//0123456789

//unsigned char code table2[]={0x41,0x42,0x43,0x44,0x45,0x46};//abcdef

uchar *s="   CYMOMETER   ";

uchar *s1="FREQ:        Hz ";

 uchar T0count;        //从T0的计数单元中读取计数的数值

uchar timecount;       //

bit flag;                     //标志位

unsigned long x;

uchar xPos,yPos;

uchar i;

 void LcdPos(uchar,uchar);    //确定光标位置

void LcdWd(uchar);            //写字符

void LcdWc(uchar);            //送控制字(检测忙信号)

void LcdWcn(uchar );        //送控制字子程序(不检测忙信号)

void mDelay(uchar );        //延时,毫秒数由j决定

void WaitIdle();            //正常读写操作之前检测LCD控制器状态

//在指定的行与列显示指定的字符,xpos:行,ypos:列,c:待显示字符

void WriteChar(uchar c,uchar xPos,uchar yPos)

{    

    LcdPos(xPos,yPos);

    LcdWd(c);

}

void WriteString(uchar *s,uchar xPos,uchar yPos)

{    uchar i;

    if(*s==0)        //遇到字符串结束

        return;    

    for(i=0;;i++)

    {    

        if(*(s+i)==0)

            break;

        WriteChar(*(s+i),xPos,yPos);

        xPos++;

        if(xPos>=15)    //如果XPOS中的值未到15(可显示的最多位)

            break;

    }

}

void SetCur(uchar Para)    //设置光标

{    mDelay(2);

    switch(Para)

    {    case 0:

        {    LcdWc(0x08);    //关显示

            break;

        }

        case 1:

        {    LcdWc(0x0c);    //开显示但无光标

            break;

        }

        case 2:

        {    LcdWc(0x0e);    //开显示有光标但不闪烁

            break;

        }

        case 3:

        {    LcdWc(0x0f);    //开显示有光标且闪烁

            break;

        }

        default:

            break;

    }

}

void ClrLcd()    //清屏命令

{    LcdWc(0x01);

}            

//    正常读写操作之前检测LCD控制器状态

void WaitIdle()

{    uchar tmp;

    RS=0;

    RW=1;

    EN=1;

    _nop_();

    for(;;)

    {    tmp=DPORT;    

        tmp&=0x80;

        if(    tmp==0)

            break;

    }

    EN=0;

}

void LcdWd(uchar c)        //写字符子程序

{    WaitIdle();

    RS=1;    

    RW=0;

    DPORT=c;            //将待写数据送到数据端口

    EN=1;

    _nop_();

    _nop_();

    EN=0;

}

void LcdWc(uchar c)        //送控制字子程序(检测忙信号)

{    WaitIdle();    

    LcdWcn(c);

}

void LcdWcn(uchar c)    //送控制字子程序(不检测忙信号)

{    RS=0;

    RW=0;

    DPORT=c;

    EN=1;

    _nop_();

    EN=0;

}

void LcdPos(uchar xPos,uchar yPos)    //设置第(xPos,yPos)个字符的DDRAM地址

{    unsigned char tmp;

    xPos&=0x0f;        //x位置范围是0~15

    yPos&=0x01;        //y位置范围是0~1

    if(yPos==0)        //显示第一行

        tmp=xPos;

    else

        tmp=xPos+0x40;

    tmp|=0x80;

    LcdWc(tmp);

}

void RstLcd()        //复位LCD控制器

{    mDelay(15);        //如果使用12M或以下晶振,此数值不必改,如用24M晶振,须用30

    LcdWc(0x38);    //显示模式设置

    LcdWc(0x08);    //显示关闭

    LcdWc(0x01);    //显示清屏

    LcdWc(0x06);    //显示光标移动位置

    LcdWc(0x0c);    //显示开及光标设置

}    

void mDelay(uchar j)    //延时,毫秒数由j决定

{   uint i=0;

    for(;j>0;j--)

    {  for(i=0;i<124;i++)

        {;}

    }

}

void main(void)

{

    RstLcd();        //初始化LCD

    ClrLcd();        //清屏

    SetCur(1);    //开光标显示、闪烁

    WriteString(s,0,0);

    WriteString(s1,0,1);

    

    

    TMOD=0x15;                 //T0工作为16位计数器(方式1),T1工作方式为16位定时器

    TH0=0;                     //计数为65536                     

    TL0=0;                     //

    TH1=(65536-4000)/256;     //定时器采用定时4ms.  初值为4000

    TL1=(65536-4000)%256;

    TR1=1;                    //TR1=1,控制开关闭合,计数脉冲进入T1计数器,启动定时

    TR0=1;                    //TR0=1,控制开关闭合,计数脉冲进入T1计数器,启动计数

    ET0=1;                    //定时器0开中断

    ET1=1;                    //定时器1开中断

    EA=1;                     //CPU开中断

while(1)

{    

    if(flag==1)                    //

    {

        flag=0;                        //清标志位

        x=T0count*65536+TH0*256+TL0;   //取得时间宽度参数

//LCD显示部分代码

//    ;==================================================================================

 LcdPos(15,1);

    WriteChar(table1[x%10],11,1);

    WriteChar(table1[(x/10)%10],10,1);    

    WriteChar(table1[(x/100)%10],9,1);    

    WriteChar(table1[(x/1000)%10],8,1);    

    WriteChar(table1[(x/10000)%10],7,1);    

    WriteChar(table1[(x/100000)%10],6,1);    

  

//;==================================================================================

    timecount=0;

    T0count=0;

    TH0=0;

    TL0=0;

    TR0=1;         //TR0=1,控制开关闭合,计数脉冲进入T1计数器,启动计数

    }

}

}

//;==================================================================================

void t0() interrupt 1 using 0      //T0中断服务

{

    T0count++;                      //对P3.4口的脉冲进行计数

}

//;==================================================================================

void t1(void) interrupt 3 using 0       //T1中断服务

{

    TH1=(65536-4000)/256;               //计数初值重装载

    TL1=(65536-4000)%256;

    timecount++;

    if(timecount==250)

    {

        TR0=0;

        timecount=0;

        flag=1;                              // 置标志

    }