OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 4603|回复: 5

STC89C52做的频率计,测量结果不对,求助!!

[复制链接]

3

主题

7

帖子

0

精华

新手上路

积分
32
金钱
32
注册时间
2019-5-7
在线时间
7 小时
发表于 2019-5-15 10:59:38 | 显示全部楼层 |阅读模式
这个里面我用了两块板子,一块作为信号发生部分,一块作为检测部分。
信号发生部分代码如下:
#include <reg52.h>

sbit out = P2^7;

sbit led5 = P1^4;
sbit led6 = P1^5;
sbit led7 = P1^6;

sbit key1 = P3^3;
sbit key2 = P3^4;

sbit led_s1 = P1^0;
sbit led_s2 = P1^1;
sbit led_s3 = P1^2;
sbit led_s4 = P1^3;

unsigned int cnt = 0;
unsigned int ctl_freq = 100;

//共阳极数码管真值表
unsigned char code buf[10] = {
                0xc0,0xf9,0xa4,0xb0,0x99,
                0x92,0x82,0xf8,0x80,0x90
};

void delay_10ms(void)   //误差 -0.000000000023us
{
    unsigned char a,b;
    for(b=249;b>0;b--)
        for(a=17;a>0;a--);
}

void delay_100us(void)   //误差 -0.217013888889us
{
    unsigned char a,b;
        for(b=1;b>0;b--)
        for(a=43;a>0;a--);
}

/*****************************************
名称:数码管显示函数
功能:显示获取的温湿度值
参数:   
    @ temp: 高两位显示的值
    @ humi: 低两位显示的值
******************************************/
void show(unsigned int y)
{
    char one = y%10;
    char ten = y/10%10;
    char hun = y/100%10;
    char ths = y/1000%10;

        led_s1 = 0;
    led_s2 = 1;
    led_s3 = 1;
    led_s4 = 1;
    P0 = buf[one];
    delay_100us();
    P0 = 0xff;

    led_s1 = 1;
    led_s2 = 0;
    led_s3 = 1;
    led_s4 = 1;
    P0 = buf[ten];
     delay_100us();
    P0 = 0xff;

    led_s1 = 1;
    led_s2 = 1;
    led_s3 = 0;
    led_s4 = 1;
    P0 = buf[hun];
    delay_100us();
    P0 = 0xff;

    led_s1 = 1;
    led_s2 = 1;
    led_s3 = 1;
    led_s4 = 0;
    P0 = buf[ths];
    delay_100us();
    P0 = 0xff;

}

int main(void)
{

    TMOD = 0x01;
    TH0  = 0xff;
    TL0  = 0xfb;
    TR0 = 1;
    ET0 = 1;
        EA  = 1;

    while(1)
    {

                show(ctl_freq);

                if(0 == key1)
                {
                        delay_10ms();
                        if(0 == key1)
                        {
                                while(!key1);

                                if(ctl_freq<1000)
                                        ctl_freq++;
                        }
                }

                if(0 == key2)
                {
                        delay_10ms();
                        if(0 == key2)
                        {
                                while(!key2);

                                if(ctl_freq>1)
                                        ctl_freq--;
                        }
                }

       

    }
}

  //5us触发
void timer_interrupt1(void) interrupt 1
{
        cnt++;

        TH0  = 0xff;
       TL0  = 0xfb;
          
        if(cnt >= ctl_freq)
        {
                out = ~out;
                cnt = 0;
        }          
}
ctl_freq初值为100,即500us的高电平,500us的低电平,两者相互转换。周期为1ms,频率为1000Hz,但是用示波器测出来频率为150Hz,这是第一个问题。

检测部分主函数代码如下:
void  main()
{

        timer0_init();
        timer1_init();

    delay(10);                 //延时

    lcd_init();                //初始化LCD  
                   
    show_lcd();

     while(1)
         {
                 if(cnt_timer == 50)
            {
                TR1 = 0;
                        ET1 = 0;
                        TR0 = 0;
                        ET0 = 0;

                freq = (cnt_x*65536+TL1+TH1*256);
                TL1 = 0;
                TH1 = 0;
                cnt_timer = 0;
                cnt_x = 0;
                
                        del_data();
                        show_lcd();

                        TR1 = 1;
                        ET1 = 1;
                        TR0 = 1;
                        ET0 = 1;
            }

}
定时器中断代码如下:
void timer_interrupt1(void) interrupt 3
{
        cnt_x++;
        TL1 = 0x00;
        TH1 = 0x00;
}

void timer_interrupt0(void) interrupt 1
{
        cnt_timer++;
        TL0 = 0xb8;
        TH0 = 0x00;
}

此时检测部分测出来的频率为533Hz,与计算的结果和示波器的结果都不一样。
1557888883319.jpg
正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

0

主题

55

帖子

0

精华

初级会员

Rank: 2

积分
157
金钱
157
注册时间
2019-5-4
在线时间
42 小时
发表于 2019-5-17 08:26:59 | 显示全部楼层
你的这个程序都没注释,别人来看你的程序浪费很多时间的,因为你写的不规范,特别是定时器中断,两个interrup 1的中断标号,基本功没有
回复 支持 反对

使用道具 举报

0

主题

55

帖子

0

精华

初级会员

Rank: 2

积分
157
金钱
157
注册时间
2019-5-4
在线时间
42 小时
发表于 2019-5-17 08:30:54 | 显示全部楼层
另外还有要记住的是,小的定时中断,那么必须先关闭定时器,等相关的确认OK再开启,即:\
void Timer0_Interrupt (void) interrupt 1 //5US中断
{
   EA= 0;//先关闭,防止中断再一次开启
   TH0= XX;
   TL0 = XX;//如果是自动重装的,则根据情况,一般不用再加
   相关的语句,而且不要多;
   EA = 1

}
回复 支持 反对

使用道具 举报

3

主题

7

帖子

0

精华

新手上路

积分
32
金钱
32
注册时间
2019-5-7
在线时间
7 小时
 楼主| 发表于 2019-5-17 11:16:47 | 显示全部楼层
gujp0575 发表于 2019-5-17 08:26
你的这个程序都没注释,别人来看你的程序浪费很多时间的,因为你写的不规范,特别是定时器中断,两个interr ...

代码是两个,一个是波形发生端,一个是检测端,都用到了定时器0,注释的话确实写的很少,感谢提醒。
回复 支持 反对

使用道具 举报

3

主题

7

帖子

0

精华

新手上路

积分
32
金钱
32
注册时间
2019-5-7
在线时间
7 小时
 楼主| 发表于 2019-5-17 11:17:12 | 显示全部楼层
gujp0575 发表于 2019-5-17 08:30
另外还有要记住的是,小的定时中断,那么必须先关闭定时器,等相关的确认OK再开启,即:\
void Timer0_Inte ...

感谢感谢,我试一试
回复 支持 反对

使用道具 举报

0

主题

6

帖子

0

精华

新手上路

积分
32
金钱
32
注册时间
2019-5-29
在线时间
13 小时
发表于 2019-5-29 15:28:17 | 显示全部楼层
我最近也在做这个 可以提供一些程序参考一下嘛 学校的课题设计
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2024-11-23 13:33

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

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