at8frequencycounting.txt

来自「利用AT89S51单片机的T0、T1的定时计数器功能」· 文本 代码 · 共 299 行

TXT
299
字号
单片机C51数字频率计程序
/************************************************** 
//头文件部分,文件名:plj.h 
/************************************************** 
#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); 
/************************************************** 
/************************************************** 


//液晶1602子程序,文件名:1602.c 
/************************************************** 
;连线图: 
;        DB0---DPROT.0  DB4---DPROT.4    RS-------------P2.0
;        DB1---DPROT.1  DB5---DPROT.5    RW-------------P2.1
;        DB2---DPROT.2  DB6---DPROT.6    E--------------P2.2
;        DB3---DPROT.3  DB7---DPROT.7    VLCD接10K可调电阻到GND* 
;        需要11根单片机口线        
;80C51的晶振频率为12MHz 
;液晶显示程序 
;**************************************************/ 
#include <reg52.h> 
#include <intrins.h> 
#define uint unsigned int 
#define uchar unsigned char 

sbit    RS    =    P2^0; 
sbit    RW    =    P2^1; 
sbit    EN =    P2^2; 
     
#define DPORT    P0 

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++) 
        {;} 
    } 
} 


//主函数: 
/*================================================================================== 
公司名称:   河海大学电气工程学院                                                * 
模块名  :   AT89C52单片机系统,全国电子设计大赛                                 * 
创建人  :   南东亮    日期:2007。7。28                                         * 
修改人  :                                                                       * 
功能描述:  利用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秒的定时, 
                所以采用定时50ms,共定时20次,即可完成1秒的定时功能。  
                                                                          * 
//;*其他说明:   产品为设计阶段                                                  *                                     
                                                                                 */ 
//;================================================================================== 

//;主程序开始 
//;================================================================================== 

#include "plj.h" 

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 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;                              // 置标志 
    }     
}  
参考链接:http://www.picavr.com/news/2008-07/7642.htm

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?