打印
[STC单片机]

单片机输出方波,有些频率值不准确 ,怎么办。

[复制链接]
4082|23
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
1217225072|  楼主 | 2014-5-18 11:47 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
#include<reg52.h>
#include<stdio.h>
#include<string.h>
#include<lcd1602.h>
void lcd_re();
void lcd_d(unsigned char sf[],unsigned char ppp);
#define cry 12000000.0000f
sbit Pt = P1^0;
sbit key1=P3^7;
sbit key2=P3^6;
unsigned int Tin,aaa,Asp=214,a=2,numf=0;
unsigned  int hh;
unsigned int number;
float Tint;
bit m,n,o;
unsigned char table11[15]={0};


void delay(unsigned char x)   //误差 0us
{
    unsigned char aa,bb;
    for(bb=x;bb>0;bb--)
        for(aa=120;aa>0;aa--);
}



void main()
{
       



        TMOD=0x01;
        ET0=1;
        TR0=1;
        EA=1;
        lcd_re();
        key2=1;

        while(1)
        {
                Tint=(65536.0000-cry/24.000/Asp)*1.0000;
                Tin= Tint;
       
                sprintf(table11,"%f",Asp*1.0/1000);
                lcd_d(table11,0);

                sprintf(table11,"%f",Tint*1.0);
                lcd_d(table11,0x08);


                sprintf(table11,"%f",TH0*1.0);
                lcd_d(table11,0x40);
               
                sprintf(table11,"%f",TL0*1.0);
                lcd_d(table11,0x40+0X08);
                if(key1==0)
                        Asp++;       


        }




}

void ASD()interrupt 1
{
        Pt=!Pt;
        a=0;
        TH0=Tin>>8;
        TL0+=Tin;

}


频率(Asp)   实际频率     误差
     59                  59.98           0.02
         60                  59.98           0.02
         61                  59.13           1.87
         64                  63.98            0.02
         65                  62.88            2.12
         74                  73.98            0.02
          75                 72.2               2.8
          1751              1747              4
          1801               1798             3
          1851               1169              682
             1901             961.3           939.7

相关帖子

沙发
dirtwillfly| | 2014-5-18 13:57 | 只看该作者
你用的多少MHz的晶振?有些频率除不尽,肯定有误差的。
不过你这个误差太大了。
程序中要少用delay,延时尽量都用定时器

使用特权

评论回复
板凳
ayb_ice| | 2014-5-18 14:05 | 只看该作者
中断里先赋初值
靠软件实现的很难那么准的,何况还受其它中断影响

使用特权

评论回复
地板
chunyang| | 2014-5-18 18:30 | 只看该作者
尽量提高主频,同时优化程序结构。

使用特权

评论回复
5
1217225072|  楼主 | 2014-5-19 07:36 | 只看该作者
12M晶振   其他值都很准确的    不是除不尽的问题吧   都用的浮点数   误差不能这么大   其他值都还准确的

使用特权

评论回复
6
1217225072|  楼主 | 2014-5-19 07:39 | 只看该作者
就算一个延时不要  也是这样的   
问题应该出在   TL0+=Tin    如果换成   TL0=Tin/256    或者   TL0=Tin&255    越到后面误差越大

使用特权

评论回复
7
ayb_ice| | 2014-5-19 09:19 | 只看该作者
1:
        while(1)
        {
                Tint=(65536.0000-cry/24.000/Asp)*1.0000;
                Tin= Tint;

                {
                        unsigned int reload_Tin = Tin - 3;
                       
                }
...

2:
void ASD()interrupt 1
{
        TL0 += reload_Tin;
        TH0 = reload_Tin>>8;

        Pt=!Pt;
        a=0;
}

这样应该会准点


使用特权

评论回复
8
1217225072|  楼主 | 2014-5-19 11:26 | 只看该作者
这样也不会准的   Tin本来就是无符号整形变量   

使用特权

评论回复
9
1217225072|  楼主 | 2014-5-19 11:28 | 只看该作者
这样写编译都通不过的

使用特权

评论回复
10
cjseng| | 2014-5-19 11:59 | 只看该作者
本帖最后由 cjseng 于 2014-5-19 12:02 编辑

用的浮点数也没用,有的就是除不尽的问题,尽量提高晶振速度,优化程序,可以稍微减少点误差。
就算是1T的单片机,输出的信号周期只能是晶振周期的整数倍,这个没有办法改变的。
举个例子:随你怎么调整,单片机串口只能有几种波特率,不可能有任意波特率。

使用特权

评论回复
11
wh6ic| | 2014-5-19 14:00 | 只看该作者
第一、中断中不应该使用复杂的16Bit无符号运算,应该尽量使用8Bit算法
第二、为什么不用STC的单周期时钟模式?
第三、中断服务程序建议使用汇编完成
第四、TL做了加法,难道它不会产生进位吗?TH必须处理TL的进位    你那几个特别大的就是这个原因
第五、你在做运算时定时器还在跑,这个误差肿么办?

使用特权

评论回复
12
ayb_ice| | 2014-5-19 14:06 | 只看该作者
本帖最后由 ayb_ice 于 2014-5-19 14:07 编辑

本来是个示意性的代码,你说编译不过
修改一下吧



1:
unsigned int reload_Tin;

        while(1)
        {
                Tint=(65536.0000-cry/24.000/Asp)*1.0000;
                Tin= Tint;

                {
                        reload_Tin = Tin + 3;    // 应该是加3,不是减3
                        
                }
...

2:
void ASD()interrupt 1
{
        TL0 += reload_Tin;
        TH0 = reload_Tin>>8;

        Pt=!Pt;
        a=0;
}

这样应该会准点

使用特权

评论回复
13
3htech| | 2014-5-19 16:53 | 只看该作者
ayb_ice 发表于 2014-5-19 14:06
本来是个示意性的代码,你说编译不过
修改一下吧

reload_Tin的值如果过大的话,比如254,255;
当执行TL0+=reload_Tin时,会溢出。从而丢失256个计数。
不知道我这样考虑是否正确。

使用特权

评论回复
评分
参与人数 1威望 +1 收起 理由
1217225072 + 1 赞一个!,,,,,是这样的
14
ayb_ice| | 2014-5-19 16:56 | 只看该作者
3htech 发表于 2014-5-19 16:53
reload_Tin的值如果过大的话,比如254,255;
当执行TL0+=reload_Tin时,会溢出。从而丢失256个计数。
不 ...

加之前判断一下就可以了

使用特权

评论回复
15
1217225072|  楼主 | 2014-5-19 18:29 | 只看该作者
不要说除不尽    误差才多少啊    你也不想一下   提高晶振频率有毛用啊

使用特权

评论回复
16
1217225072|  楼主 | 2014-5-19 18:36 | 只看该作者
3htech 发表于 2014-5-19 16:53
reload_Tin的值如果过大的话,比如254,255;
当执行TL0+=reload_Tin时,会溢出。从而丢失256个计数。
不 ...

说得对  确实设这样的

使用特权

评论回复
17
1217225072|  楼主 | 2014-5-19 18:39 | 只看该作者
艹   评分拼到自己了

使用特权

评论回复
18
1217225072|  楼主 | 2014-5-19 18:40 | 只看该作者
TL0+=reload_Tin    不知道   会不会溢出   但是在哪里加一个判断语句   确实是好了许多    但还是觉得不好

使用特权

评论回复
19
1217225072|  楼主 | 2014-5-19 18:47 | 只看该作者
1898   实际频率只有   1625
1903                               1278
到    1950          都小于    1300
1954            恢复到   1952

使用特权

评论回复
20
ningling_21| | 2014-5-19 20:12 | 只看该作者
想输出准确的频率,还是用专门芯片,或者闭环控制检测到偏差后自动修正...

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

1

主题

11

帖子

0

粉丝