一乐电子

 找回密码
 请使用微信账号登录和注册会员

QQ登录

只需一步,快速开始

微信扫码登录

手机号码,快捷登录

手机号码,快捷登录

搜索
查看: 5283|回复: 13

[其他综合] 请教:用单片机测频率,使用计数器,读出值不稳。

[复制链接]
发表于 2011-5-9 15:31 | 显示全部楼层 |阅读模式
我用热敏电阻和555做了个震荡电路,输出给单片机的计数器脚(外部计数)
用定时器定1秒,到一秒后读一次计数器里面的值,然后把计数器清零,在计数。
再把读出的值查表换成温度值。

现在的问题是读出的值不稳定,
昨天试的,常温下,7105~7280之间跳动,
这样的精度别说0.1度了,就是正负1度也做不到。
是不是555电路本身输出的频率就不稳定呢?

我看有的资料上面写的是用中断去测量频率周期,
难道测量周期的方法要好些?
 楼主| 发表于 2011-5-9 15:31 | 显示全部楼层
/*******************************************************************/
/*利用热敏电阻特性使555改变振荡频率计算当前的频率,查表出当前温度值*/
/*       */
/*       */
/*       */
/*      */
/*******************************************************************/

#include <AT89X52.H>
#define dula P2_6 //U1锁存位
#define wela P2_7 //U2锁存位
#define uint unsigned int
#define uchar unsigned char
sbit led1=P1^0;
sbit buzz=P2^3;
uint shu;
uint time,pinlv,ID;
uchar code table[]={0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,0x80,0x90};
//共阳0-9的LED笔划
uchar temp,t0,t1,wan,qian,bai,shi,ge;
void init();              //函数声明
void display(uchar aa,uchar wan,uchar qian,uchar bai,uchar shi,uchar ge);

void delay(uint z)     //延时子函数
{
uint x,y;
for(x=z;x>0;x--)
  for(y=110;y>0;y--);
}
void main()          //主函数
{ uint val;
init();
while(1)
{
if(time==50)
{
  val=TH1*256+TL1;       //谁帮我讲一下,这里为啥要*256在加TL1?
   pinlv=val;
  time=0;
  TH1=0;
  TL1=0;
  
ID=pinlv/2;
switch(ID)
   {
  
    case 620:
            shu=330;
            break;   
    case 619:
            shu=320;
            break;   
    case 618:
            shu=310;
            break;   
    case 617:
            shu=300;
            break;   
    case 616:
            shu=290;
            break;   
    case 615:
            shu=280;
            break;   
    case 614:
            shu=278;
            break;   
    case 613:
            shu=277;
            break;
    case 612:
            shu=276;
            break;
    case 611:
   shu=275;
     break;
    case 610:
            shu=274;
            break;
    case 609:
   shu=273;
     break;
    case 608:
            shu=272;
            break;
    case 607:
   shu=271;
   break;
    case 606:
            shu=270;
            break;
    case 605:
   shu=269;
     break;
    case 604:
            shu=268;
            break;
    case 603:
   shu=267;
     break;
    case 602:
            shu=266;
            break;
    case 601:
   shu=265;
   break;
    case 600:
            shu=264;
            break;
    case 599:
            shu=263;
            break;
    case 598:
   shu=262;
    break;
    case 597:
            shu=261;
            break;   
       case 596:
            shu=260;
            break;
    case 595:
            shu=259;
            break;
    case 594:
   shu=258;
    break;
    case 593:
            shu=257;
            break;
   }}
   
   display(0,wan,qian,bai,shi,ge);

}
}
void init()          //初始化函数
{
TMOD = 0x51; //设计数器1  和  0为工作方式1(0101-LED 0001)
TH0=(65536-13333)/256;//0xB1;
TL0=(65536-13333)%256;//0xDF; //设定时值为20000us(20ms)
TH1=0;
TL1=0;//设
EA = 1; //允许CPU中断
ET0 = 1; //定时器0中断打开
ET1 = 1;//计数器1中断打开
TR0 = 1; //启动定时器0
TR1 = 1; //启动计数器1
}
//
void KeyAndDis_Time0(void) interrupt 1
{
TH0=(65536-13333)/256;//0xB1;
TL0=(65536-13333)%256;//0xDF; //设定时值为20000us(20ms)
time++;
}

void display(uchar aa,uchar wan,uchar qian,uchar bai,uchar shi,uchar ge) //显示子函数
{

   wan=shu/10000;
   qian=shu%10000/1000;
   bai=shu%1000/100;
   shi=shu%100/10;
   ge=shu%10;
        dula=1;
  P0=table[aa];
  dula=0;
  P0=0x00;
  wela=1;
  P0=0x01;
  wela=0;
  delay(1);
        dula=1;
  P0=table[wan];
  dula=0;
  P0=0x00;
  wela=1;
  P0=0x02;
  wela=0;
  delay(1);
       dula=1;
  P0=table[qian];
  dula=0;
  P0=0x00;
  wela=1;
  P0=0x04;
  wela=0;
  delay(1);
        dula=1;
  P0=table[bai];
  dula=0;
  P0=0x00;
  wela=1;
  P0=0x08;
  wela=0;
  delay(1);
  dula=1;
  P0=table[shi];
  dula=0;
  P0=0x00;
  wela=1;
  P0=0x10;
  wela=0;
  delay(1);
  dula=1;
  P0=table[ge];
  dula=0;
  P0=0x00;
  wela=1;
  P0=0x20;
  wela=0;
  delay(1);
}
回复

使用道具 举报

发表于 2011-5-9 16:06 | 显示全部楼层
可以用信号发生器给个信号单片机,看它数的准不准。哈~~
不过这里可能不是程序问题,555的问题比较大。
回复

使用道具 举报

 楼主| 发表于 2011-5-9 16:45 | 显示全部楼层
可以用信号发生器给个信号单片机,看它数的准不准。哈~~
不过这里可能不是程序问题,555的问题比较大。
chjj0 发表于 2011-5-9 16:06 [url=https://www.yleee.com.cn/images/common/back.gif]https://www.yleee.com.cn/images/common/back.gif[/url]



    谢谢哈,有空我试一下看看。
回复

使用道具 举报

发表于 2011-5-9 17:00 | 显示全部楼层
本帖最后由 lihongran 于 2011-5-9 22:09 编辑

计数值才7000闪动的值竟在百位,我做的计数值在几万闪动值也是在10以内而已啊~~你这个有很多问题。
最大的问题就是你读取计数值没有在中断里进行,你这样读出来的值是乱糟糟的,想想看一个水杯去接水,虽然水喉的单位时间内的出水量是一定的,但你提取的时间却是不定的,这样每次得到的水肯定是多少不一的。你先改读取计数值在中断里进行再说。
val=TH1*256+TL1;       //谁帮我讲一下,这里为啥要*256在加TL1?
这里是把分开的高低8位的计数值合并成一个16位的数,也就是你读取一次的计数值,这样做执行效率不高,最好改成:val=TH1《8|TL1;
回复

使用道具 举报

发表于 2011-5-9 17:05 | 显示全部楼层
本帖最后由 lihongran 于 2011-5-9 17:42 编辑

你是做频率计还是做温度计?做温度计你不用一秒读取一次计数值啊,这样转换速度也太慢了,改为几十到100mS读一次吧
回复

使用道具 举报

发表于 2011-5-9 21:38 | 显示全部楼层
这个我做过,我测得是T2作为可编程时钟的频率。我个人认为你的问题主要是出在时间上,你的
if(time==50)
{
val=TH1*256+TL1;       //谁帮我讲一下,这里为啥要*256在加TL1?
  pinlv=val;
time=0;LCD,LED,电源,充电器,可调电源,液晶模块,VFD,套件,1602,1604,2402,2004,12864,数控电源,白菜白光,avr,18650电池,LED手电,点阵,创意DIY,单片机制作,电池,秀,淘宝,论坛0 ^. |4 ]7 Q) A3 s/ V
  TH1=0;
TL1=0;

应该放在中断里进行。关于这个问题,建议你用共用体来省去计算,比如一个16位数a,高位位ah,低位位al,按照你的方法是a=ah*256+al,但是用共用体就可以省去不少功夫,例如:union aa{uchar bb[2];uint a;}
aa.b[1]=TL;
aa.b[0]=TH;

val=aa.a;

回复

使用道具 举报

发表于 2011-5-9 21:43 | 显示全部楼层
还有一点,555定时器也存在温漂的,最近我上班时候处理一个小日本的热敏电阻问题,关于热敏电阻,通电时间长了也会有很大误差
回复

使用道具 举报

发表于 2011-5-9 22:05 | 显示全部楼层
为啥不用AD呢?
回复

使用道具 举报

发表于 2011-5-9 22:06 | 显示全部楼层
555肯定是有温漂,而且也不小,楼主的这个百位狂闪绝对不是555温漂引起的,不然要使百位狂闪,那他的环境温度的变化幅度与速度那将有多剧烈,身边的环境不可能有,除非是地狱。
回复

使用道具 举报

本版积分规则

QQ|一淘宝店|手机版|商店|一乐电子 ( 粤ICP备09076165号 ) 公安备案粤公网安备 44522102000183号

GMT+8, 2025-11-5 06:02 , Processed in 0.033910 second(s), 28 queries , Gzip On.

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

快速回复 返回顶部 返回列表