找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 564|回复: 12
收起左侧

单片机中断定时为什么会晚?

[复制链接]
ID:1095802 发表于 2023-11-6 14:40 | 显示全部楼层 |阅读模式
11.0592的晶振定时10ms不是没有误差吗,为什么写的钟表一天会慢几分钟,是因为中断程序运行时间过久,中断时间到了前一个中断还未出去而延迟吗
单片机源程序如下:
#include <reg52.h>
#include <intrins.h>
#define Fosc 11.0592 //晶振频率
#define FTime 10000  //中断定时以us计
void main(void)
{
while(1);
}
void T0_Init(void)
{
        TMOD|=0x01;
        EA=1;
        ET0=1;
        TR0=1;
        TH0=(65536-FTime*Fosc/12)/256;
        TL0=(char)(65536-FTime*Fosc/12)%256;
}
void T0_Timer(void) interrupt 1
{
        TH0=(65536-FTime*Fosc/12)/256;
        TL0=(char)(65536-FTime*Fosc/12)%256;
}


回复

使用道具 举报

ID:712097 发表于 2023-11-6 16:13 | 显示全部楼层
单片机精度没那么高,精度要求高的时钟应用,用专门的时钟芯片如DS1302,PCF8563,DS3231等。
回复

使用道具 举报

ID:883242 发表于 2023-11-6 16:24 | 显示全部楼层
chxelc 发表于 2023-11-6 16:13
单片机精度没那么高,精度要求高的时钟应用,用专门的时钟芯片如DS1302,PCF8563,DS3231等。

单片机内部RC振荡器稳定性不行,但是11MHz AT-cut quartz精度要比DS1302、PCF8563用的fork quartz好太多了,这些RTC芯片优点在于功耗低,掉电依然可以用电池来运行,他们的精度根本不行,在高频晶体面前就是个笑话。楼主如果用的是高频晶体,可以修改软件。当然DS3231属于TCXO,精度最高。
回复

使用道具 举报

ID:220661 发表于 2023-11-6 16:27 | 显示全部楼层
11.0592晶体做定时器生成1ms没有误差?记错了吧,那是做串口波特率没有误差,你用12M晶体试试吧?
回复

使用道具 举报

ID:213173 发表于 2023-11-6 17:15 | 显示全部楼层
这种时钟想要提高精度需要采取一点措施。改换12M或24M高品质晶振,定时器采用自动重装模式,定时中断周期尽可能短,建议不超过100uS。添加修正系数补偿误差。采取以上措施后可以将日误差控制在1秒左右。
回复

使用道具 举报

ID:1095802 发表于 2023-11-6 23:13 | 显示全部楼层
gongnn 发表于 2023-11-6 16:27
11.0592晶体做定时器生成1ms没有误差?记错了吧,那是做串口波特率没有误差,你用12M晶体试试吧?

10ms写错了,程序里是10000us
回复

使用道具 举报

ID:277550 发表于 2023-11-7 09:51 | 显示全部楼层

DS3231 还可以,只是比较贵
回复

使用道具 举报

ID:485350 发表于 2023-11-29 11:51 | 显示全部楼层
晶振误差多少,中断跳转,定时时间重载这些考虑进去没
回复

使用道具 举报

ID:57657 发表于 2023-11-29 13:20 | 显示全部楼层
仿真误差大是程序有问题,实物误差与晶振精度有关,定时器要设置成自动重载模式。
回复

使用道具 举报

ID:397054 发表于 2023-11-29 14:47 | 显示全部楼层
这是中断模式1的工作机理引起的——从中断申请的发出,到CPU响应,再到计算赋值完毕(主要是向TL赋值完毕),这是有时间的,这段时间远不为0,每个中断都插入了这样一段时间所以就慢了,这绝不是精度问题,因为1天要慢好几分钟的。尤其是你在中断程序里还进行了计算,这也很消耗时间,并且还把对TL的赋值放在了TH后,更增加了延时。解决这一问题的常规手法是在对TL赋值前读出它的值,加在新值上赋给TL,并再加上2-5个修正值(可由实验确定),因为赋值也要消耗时间的并且C是怎么编译的我们也不知道。另一个更好的办法是,调整中断周期,使TL=0,这样在中断程序中可以不给TL赋值,只给TH赋值,使得计数不间断,类似于中断模式2,也就没有了延时的产生。11.0592的晶振可以直接做到这点的,比如TH=180(即B4H),在中断程序中删掉TL的赋值语句,这样的中断计20次就是1秒。12兆的晶体做不到这点——算术问题,当然非要这么做也可以,增加了程序的复杂性。
回复

使用道具 举报

ID:397054 发表于 2023-11-29 15:02 | 显示全部楼层
实际上你的这个程序已经满足了上贴的条件,即TL=0,所以在中断程序中直接删除赋值语句【TL0=(char)(65536-FTime*Fosc/12)%256;】即可,其他哪里都不用变,这个几分钟的误差即可彻底消除,非常简单的事。再有的误差那就是元器件的精度引起的了,远不会超过1秒/天。那些说什么时钟芯片的,都是想当然。
回复

使用道具 举报

ID:57657 发表于 2023-11-29 15:02 | 显示全部楼层
鹈鹕 发表于 2023-11-29 14:47
这是中断模式1的工作机理引起的——从中断申请的发出,到CPU响应,再到计算赋值完毕(主要是向TL赋值完毕) ...

定时器设置为自动重载初值模式,这段时间就为0,你设置10ms的定时器,定时器中断内停留不得超过10ms
回复

使用道具 举报

ID:1073939 发表于 2023-11-29 17:20 | 显示全部楼层
void T0_Timer(void) interrupt 1
{
        TH0=(65536-FTime*Fosc/12)/256;
        //TL0=(char)(65536-FTime*Fosc/12)%256;
}

代码改成这样能显著提高走时精度。楼主这行画蛇添足。
在早期没有自动重装模式的单片机,想要走时准确,只能使用类似11.0592的晶振,这样TL0的重装值为0,也算间接实现了自动重装。
回复

使用道具 举报

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

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

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