找回密碼
 立即注冊(cè)

QQ登錄

只需一步,快速開始

搜索
查看: 12240|回復(fù): 5
收起左側(cè)

單片機(jī)頻率計(jì)數(shù)器(程序)

[復(fù)制鏈接]
ID:71259 發(fā)表于 2014-12-30 15:46 | 顯示全部樓層 |閱讀模式
本帖最后由 daming 于 2014-12-30 15:47 編輯

該程序能實(shí)現(xiàn)測(cè)量10至3MHZ的TTL信號(hào)頻率,液晶顯示4為有效數(shù)字,同時(shí)能夠測(cè)量脈沖占空比,精度在0.5%左右...
需要硬件支持:C8051F360單片機(jī),鍵盤,液晶顯示器
main()
{
    int xdata flag1=0;
       float  sum1=0,sum2=0;
       float xdata sum3[10];
       int i;
       Init_device();
       LCD_REST();
       LCD_INIT();
       f=0;
       f1=0;
  while(1)
{
    if(flag)
   {
        if(f>=10&&f<=99)   額,不得不說,取11個(gè)數(shù)求平均值確實(shí)不好,讀數(shù)不能穩(wěn)定的說....
{
             sum2=(jishu[0]+jishu[1]+jishu[2]+jishu[3]+jishu[4]+jishu[5]+jishu[6]+jishu[7]+jishu[8]+jishu[9]+jishu[10])/11;
             get_flow(sum2);
             LCD_HZ(0x80,TAB_WORD);
             LCD_HZ(0x90,F_DISPLOW);
          flag=0;
            }
          else if(f>=100&&f<= 999)
       {
               get_flowhigh();
               LCD_HZ(0x80,TAB_WORD);
               LCD_HZ(0x90,F_DISPLOWHIGH);
               flag=0;
       }
          else if (f>=1000&&f<=9999)
          {
             get_high();
                LCD_HZ(0x80,TAB_WORD);
                LCD_HZ(0x90,F_DISPHIGH);
                flag=0;
          }
          else if(f>=10000&&f<=99999)
          {
             get_highone();
                LCD_HZ(0x80,TAB_WORD);
                LCD_HZ(0x90,F_DISPHIGHONE);
                flag=0;
          }
          else if(f>=100000&&f<=999999)
       {
           get_highone();
           LCD_HZ(0x80,TAB_WORD);
           LCD_HZ(0x90,F_DISPHIGHONE);         內(nèi)部數(shù)據(jù)存儲(chǔ)器只有128位,為節(jié)約空間與上個(gè)數(shù)組存在同一空間
                                                                                   (內(nèi)部數(shù)據(jù)存儲(chǔ)器空間用完的說...)
           flag=0;
              }
              else
              {
              get_highthree();
              LCD_HZ(0x80,TAB_WORD);
              LCD_HZ(0x90,F_DISPHIGHTHREE);
              flag=0;
              }
     }
       if((key_num&0xf0)==0)
        {   
               TR0=0;
                ET1=1;
                TMOD=0x10;
                TCON=0x40;
                for(i=0;i<10;i++)
                {
                 while(CHUFA==0);
                 TH1=0;
            TL1=0;
                  f1=0;
                     TR0=0;
                 while(CHUFA==1);
               while(CHUFA==0);
                 TR1=1;
                while(CHUFA==1);
              TR1=0;
                m=f1*65536+256*TH1+TL1;
                while(CHUFA==0);
                  TH1=0;
                TL1=0;
                f1=0;
                TR1=0;
                while(CHUFA==1);
                TR1=1;
                while(CHUFA==0);
                TR1=0;
                f=f1*65536+256*TH1+TL1;
          key_num=0xf0;
          sum1=m;
          sum2=m+f;
          sum1=sum1/sum2;
          sum3[ i]=sum1;
          }
          sum2=0;
          for(i=0;i<10;i++)
          {
            sum2=sum2+sum3[ i];
          }
          sum2=sum2/10;
             if(sum2>=0.1&&sum2<=0.40)
              {
                sum2=sum2-0.07;
                }
               else if(sum2>0.40&&sum2<=0.44)
                {
                sum2=sum2-0.04;
                }                                                                    占空比程序設(shè)計(jì),本想用個(gè)中斷來著,試驗(yàn)不成功簡單的算了
                                                                                      由于每次運(yùn)行指令要耗費(fèi)時(shí)間,精度不高,故加個(gè)實(shí)測(cè)校準(zhǔn)程序
                                                                                      O(∩_∩)O哈哈~測(cè)評(píng)時(shí)能達(dá)到0.5%的精度,踩狗屎運(yùn)了...
                else if(sum2>0.44&&sum2<=0.55)
                {
                 sum2=sum2-0.02;
                }                                                            
                else if(sum2>0.55&&sum2<=0.63)
                {
                sum2=sum2+0.03;
                }
                else sum2=sum2+0.07;
          get_f(sum2);
          LCD_HZ(0x88,TAB_WORD1);
          LCD_HZ(0x98,F_DISP);
          flag1=1;
        }
        if(flag1==1)                                        讓程序能范圍繼續(xù)測(cè)量頻率
        {
            TMOD=0x51;                          
           CKCON=0;         
           TCON=0x50;
              flag1=0;
       }
}
}

相關(guān)帖子

回復(fù)

使用道具 舉報(bào)

ID:71259 發(fā)表于 2014-12-30 15:47 | 顯示全部樓層
頻率計(jì)數(shù)器就(3.ASCII液晶輸出函數(shù)):
void get_f(float s1)

{

   int term;

   term=(int)(s1*10000);

F_DISP[0]=term/1000%10+0x30;

F_DISP[1]=term/100%10+0x30;

F_DISP[2]=0x2E;

F_DISP[3]=term/10%10+0x30;

F_DISP[4]=term%10+0x30;             占空比(原值一般為0.****)

}

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

void  get_flow(float s1)

{  int term;

   term=(int)(s1*100);



F_DISPLOW[0]=term/1000%10+0x30;

F_DISPLOW[1]=term/100%10+0x30;

F_DISPLOW[2]=0x2E;

F_DISPLOW[3]=term/10%10+0x30;

F_DISPLOW[4]=term%10+0x30;              頻率讀數(shù)輸出顯示(10——99HZ)

}

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

void  get_flowhigh(void)

{

  

  

   F_DISPLOWHIGH[0]=f/100%10+0x30;

   F_DISPLOWHIGH[1]=f/10%10+0x30;

   F_DISPLOWHIGH[2]=f%10+0x30;

   F_DISPLOWHIGH[3]=0x2E;

   F_DISPLOWHIGH[4]=0x30;                     頻率讀書輸出顯示(100——999HZ)以下類推...

}

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

void  get_high(void)

{

  

   F_DISPHIGH[0]=f/1000%10+0x30;

   F_DISPHIGH[1]=f/100%10+0x30;

   F_DISPHIGH[2]=f/10%10+0x30;

   F_DISPHIGH[3]=f%10+0x30;

   }

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

  void get_highone(void)

  {

    if(f>=10000&&f<=99999)

       {

   F_DISPHIGHONE[0]=f/10000%10+0x30;

   F_DISPHIGHONE[1]=f/1000%10+0x30;

   F_DISPHIGHONE[2]=0x2E;

   F_DISPHIGHONE[3]=f/100%10+0x30;

   F_DISPHIGHONE[4]=f/10%10+0x30;

   }

   else

    {   F_DISPHIGHONE[0]=f/100000%10+0x30;

       F_DISPHIGHONE[1]=f/10000%10+0x30;

       F_DISPHIGHONE[2]=f/1000%10+0x30;

       F_DISPHIGHONE[3]=0x2E;

       F_DISPHIGHONE[4]=f/100%10+0x30;

       }

   }

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





       void get_highthree(void)

   {

       F_DISPHIGHTHREE[0]=f/1000000%10+0x30;

       F_DISPHIGHTHREE[1]=0x2E;

       F_DISPHIGHTHREE[2]=f/100000%10+0x30;

       F_DISPHIGHTHREE[3]=f/10000%10+0x30;

       F_DISPHIGHTHREE[4]=f/1000%10+0x30;

       }
回復(fù)

使用道具 舉報(bào)

ID:71259 發(fā)表于 2014-12-30 15:48 | 顯示全部樓層
頻率計(jì)數(shù)器(2.初始化及中斷):
void PCA_INIT(void)

{

       PCA0CN=0X40;                         //允許PCA計(jì)數(shù)器、定時(shí)器

       PCA0MD=0;                               //禁止看門狗定時(shí)器

}

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

void INT_INIT(void)

{

       EX0=1;                                      //INIT0,鍵盤

       PX0=0;                                      //INT0為低優(yōu)先級(jí)

       ET0=1;                                      //T0

       ET1=1;                                    //T1

       ET2=0;                                      //T2

       EIE1=0X0;                                 //0X08,允許ADC中斷

       ES0=0;                                       //uart

       EA=1;

}

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



void Init_device(void)

{

       OSC_INIT();

       IO_INIT();

       XRAM_INIT();

       SMB_INIT();

       UART_INIT();

       DAC_INIT();

       ADC_INIT();

       INT0_INIT();

       TIMER_INIT();

       PCA_INIT();

       INT_INIT();

}

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

void LCD_REST(void)

{

       int i;

       LCD_RST=0;

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

       LCD_RST=1;

}

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

void LCD_WC(unsigned char command)                          //LCD寫命令

{

       while(RCOMADDR&0X80);

       WCOMADDR=command;

}

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

void LCD_INIT(void)                                                 //LCD初始化

{

       LCD_WC(0X30);                                                    //設(shè)為基本命令集

       LCD_WC(0X01);

       LCD_WC(0X02);                                                    //將DDRAM填滿20H,并設(shè)定DDRAM地址計(jì)數(shù)器為0

       LCD_WC(0X0C);                                                   //開整體顯示

}

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



void LCD_WD(unsigned char d)                               //LCD寫數(shù)據(jù)

{

       while(RCOMADDR&0X80);

       WDATADDR=d;

}

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

void LCD_HZ(unsigned char x,unsigned char temp[])                      //顯示一行字符

{

   int i=0;

   LCD_WC(x);                                                                                    //x代表位置,=0x80對(duì)應(yīng)左上角

   while(temp[i]!=0)

        {

              LCD_WD(temp[i]);

              i++;

       }

}

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

void LCD_BYTE(unsigned char x,unsigned char temp)                           //顯示一行字符

{

   LCD_WC(x);                                                                                    //x代表位置,=0x80對(duì)應(yīng)左上角

   LCD_WD(temp);

}

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

void LCD_CLR(void)                                                     //LCD清屏

{

        LCD_WC(0X01);

}

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

void KEY_INIT0(void) interrupt 0

{

  key_num=KEYCS&0x0f;

}

//*****T0中斷服務(wù)***************************************

void  TT0_INT0(void) interrupt 1

{

    int j=0;

       TL0=0x66;                                        //0Xb0;

       TH0=0x3d;                                        //0X3c;每單位0.5微秒*50000*40

擦,難道上次精度不夠是因?yàn)閰?shù)還沒改正確?

      fp--;

        if(fp) return;

        TR1=0;

              fp=T_C;                      //1s

        f=65536*f1+256*TH1+TL1;

              if(n==0)

              {

              jishu[n%11]=f;

              }

              else

              {

              if(abs(jishu[n%11-1]-f)>=10)

              {

                for(j=0;j<=10;j++)

                {

                  jishu[j]=f;

                }

           }

                else

                     {

                          jishu[n%11]=f;

                         }

              }



              n++;

        flag=1;

  TH1=0;

        TL1=0;

        f1=0;

              TR1=1;

     }

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

void TT1_INT1(void ) interrupt 3

{

f1++;      定時(shí)器中斷3,當(dāng)計(jì)數(shù)器有溢出時(shí)會(huì)引發(fā)中斷

}
回復(fù)

使用道具 舉報(bào)

ID:71259 發(fā)表于 2014-12-30 15:49 | 顯示全部樓層
頻率計(jì)數(shù)器(1.液晶初始及鍵盤等):
#define WDATADDR XBYTE[0XC009]                            //LCD寫數(shù)據(jù)地址

#define RDATADDR XBYTE[0XC00B]                            //LCD讀數(shù)據(jù)地址

#define WCOMADDR XBYTE[0XC008]                          //LCD寫命令地址

#define RCOMADDR XBYTE[0XC00A]                           //LCD讀命令地址

#define KEYCS      XBYTE[0XC00C]                      //鍵盤片選地址

#define T_C    40

sbit LCD_RST=P3^0;

sbit CHUFA=P0^6;

unsigned char code TAB_WORD[]={"Frequency="};

unsigned char code TAB_WORD1[]={"DUTY="};

unsigned char    F_DISP[]={"00000%"};

unsigned char   F_DISPLOW[]={"00000HZ    "};

unsigned char   F_DISPLOWHIGH[]={"00000HZ   "}  ;

unsigned char  F_DISPHIGH[]={"0000HZ     "} ;

unsigned char  F_DISPHIGHONE[]={"00000*1kHZ"};

unsigned char  F_DISPHIGHTHREE[]={"00000*1MHZ"};  

unsigned char   jishu[11]={ 0,0,0,0,0,0,0,0,0,0,0};        低頻采用堆棧求平均值方法,但貌似最終對(duì)數(shù)不能穩(wěn)定,難道是因?yàn)槿?1個(gè)數(shù)不好?

unsigned long n=0;

unsigned long m=0;

unsigned char fp;

unsigned long f;

unsigned char f1;

bit flag=0;

unsigned char key_num=0xff;                                  //存鍵號(hào)

void OSC_INIT (void)

{

       SFRPAGE=0X0F;

       OSCICL=OSCICL+4;

       OSCICN=0XC3;

       CLKSEL=0X30;

       SFRPAGE=0;

}

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

void IO_INIT(void)

{

       SFRPAGE=0X0F;

       P0MDIN=0Xe7;

       P0MDOUT=0X83;

       P0SKIP=0XF9;

       P1MDIN=0XFF;

       P1MDOUT=0XFF;

       P1SKIP=0XFF;

       P2MDIN=0XFE;

       P2MDOUT=0XFF;

       P2SKIP=0XFF;

       P3MDIN=0XFF;

       P3MDOUT=0XFF;

       P3SKIP=0XF9;                   //0xfd,增加P3.2作T1輸入

       P4MDOUT=0XFF;

       XBR0=0X09;

       XBR1=0Xe0;                       //0xc0,增加T1

       SFRPAGE=0X0;

}

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

void XRAM_INIT(void)

{

       SFRPAGE=0X0F;

       EMI0CF=0X07;

       SFRPAGE=0;

}

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

void SMB_INIT(void)

{

       SMB0CF=0XC1;

}

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

void UART_INIT(void)

{

             SCON0=0X0;

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

void DAC_INIT(void)

{

       IDA0CN=0XF2;

}

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

void ADC_INIT(void)

{

       REF0CN=0;                         //VDD為基準(zhǔn)

       AMX0P=0X08;                           //正端接P20

       AMX0N=0X1F;                          //負(fù)端接GND

       ADC0CF=0X2C;                  //左對(duì)齊,轉(zhuǎn)換時(shí)鐘2MHZ

       ADC0CN=0X80;                  //寫ADOBUSY啟動(dòng)AD

}

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

void INT0_INIT(void)

{

       IT01CF=0X05;                           //P0.5為INT0

       IT0=1;                                       //下降沿觸發(fā)

}

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

void TIMER_INIT(void)

{

       TMOD=0x51;                             //T0、T1方式1,T1計(jì)數(shù)方式

       CKCON=0;                                //系統(tǒng)時(shí)鐘12分頻

       TL0=0x66;                                

       TH0=0x3e;                        

       TL1=0X0;

       TH1=0X0;                                  //計(jì)數(shù)器清0

       fp=T_C;

       TMR2CN=0X04;                        //16位自動(dòng)重裝

       TMR2RLL=0XF0;                       //10MS

       TMR2RLH=0XD8;

       TMR3CN=0X0C;                        //雙8位自動(dòng)重裝入,系統(tǒng)時(shí)鐘1/12

       TMR3RLL=0XE0;                       //定時(shí)100us

       TMR3RLH=0XFF;

       TR0=1;

       TR1=1;

}
回復(fù)

使用道具 舉報(bào)

ID:71326 發(fā)表于 2014-12-30 15:59 | 顯示全部樓層
好 非常好
回復(fù)

使用道具 舉報(bào)

ID:890642 發(fā)表于 2023-12-13 22:17 來自手機(jī) | 顯示全部樓層
daming 發(fā)表于 2014-12-30 15:49
頻率計(jì)數(shù)器(1.液晶初始及鍵盤等):
#define WDATADDR XBYTE[0XC009]                            //LCD寫 ...

夠詳細(xì),值得學(xué)習(xí)
回復(fù)

使用道具 舉報(bào)

本版積分規(guī)則

手機(jī)版|小黑屋|51黑電子論壇 |51黑電子論壇6群 QQ 管理員QQ:125739409;技術(shù)交流QQ群281945664

Powered by 單片機(jī)教程網(wǎng)

快速回復(fù) 返回頂部 返回列表