• 已解决 73482 个问题
  • 已帮助 5993 位优秀工程师

延时几小时的话怎么做比较好?

xiangku 2017-02-16 浏览量:1072

请问用循环延时还是用定时器比较好?或者有其他的方法!谢谢!

时间会有不准的现象,头好大啊,大很多了

0 0 收起

我来回答

上传资料:
选择文件 文件大小不超过15M(格式支持:doc、ppt、xls、pdf、zip、rar、txt)
最佳答案
  • 程序的话,网上一大堆,用定时器定时即可,主函数中就要做统计。(重点:函数要有时间补偿,我这周跟上周一直在弄时间补偿)
    • 发布于 2017-02-16
    • 举报
    • 评论 0
    • 0
    • 0

其他答案 数量:17

  • 这么长时间我觉得还是专门外围芯片吧,你延时的话积少成多会有较大误差
    • 发布于2017-02-16
    • 举报
    • 评论 0
    • 1
    • 0

  • 还是使用外部的时钟芯片吧,不然的话,每次都有小的误差,总体时间上会有很大的误差的
    • 发布于2017-02-16
    • 举报
    • 评论 0
    • 1
    • 0

  • 建议用定时器循环装载这样

    比如你定时器定时上限是100秒,那么你就让它循环36次触发一小时延时事件,这样比较好

    • 发布于2017-02-16
    • 举报
    • 评论 0
    • 0
    • 0

  • 用定时器做                  
    • 发布于2017-02-16
    • 举报
    • 评论 0
    • 0
    • 0

  • 單片機的話還是推薦用定時器ISR,宣告變數一秒觸發ISR一次時遞增即可,之後進行時/分/秒換算,空檔時間可以設計其他應用

    以上供參考

    • 发布于2017-02-16
    • 举报
    • 评论 0
    • 0
    • 0

  • 延时比较长时间的话,最好使用RTC的Alert功能,设定好时间后发出定时中断来唤醒。不要用循环。
    • 发布于2017-02-16
    • 举报
    • 评论 0
    • 0
    • 0

  • 个人实际项目经验告诉我们,要准,用rtc,设标志,相当准
    • 发布于2017-02-16
    • 举报
    • 评论 0
    • 0
    • 0

  • 延时的确不是一个好方法,它意味着这段时间内什么事情都不能操作了。


    如果还考虑功耗等因素,​一个比较好的方法是使用定时器,这样MCU的负载非常小。很多单片机的定时器允许设置分频系数,这样定时器就有一个很大的动态范围。有些单片机甚至可以将两个定时器级联,将两个8位的定时器组合成16位或者将两个16位组合成32位的。即使不支持级联模式,也可以将一个定时器的输出作为另外一个定时器的输出。

    • 发布于2017-02-16
    • 举报
    • 评论 0
    • 0
    • 0

  • 几个小时 的话,单片机上用什么都无所谓的,都可以实现。关键是什么,是精度,你要多么精确呢?

    使用循环不准,是必然的,使用定时器会准一点,但是其频率是在主频上分频的,其定时误差也是很大的,尤其是在几个小时时,误差可以达到几秒到几十秒吧,还要看你的晶振的精度,以及你程序上的处理。

    所以还是建议用外部的RTC芯片,RX8025、DS1302、DS1307都可以,就是个I2C的通讯。

    • 发布于2017-02-16
    • 举报
    • 评论 0
    • 0
    • 0

  • 肯定用定时器比较好啊,而且最好接上外部晶振,看定时基数,11.0592MHz的晶振的话,貌似可以最小精确到5ms基本无误差,12MHz的晶振的话貌似可以最小精确到1ms基本无误差。

    定时器的详细使用可以参考这个帖子:


    I51开发板 第六讲:定时器之配置篇
    //www.icxbk.com/community/forum.php?mod=viewthread&tid=65517
    (出处: ICKEY BBS)


    里面有详细说明及例程:



    • 发布于2017-02-17
    • 举报
    • 评论 0
    • 0
    • 0

  • void timerinit(void)
    {
    TMCON=0x03; //------ 11 ;Timer0和Tiemr1选择时钟分频,Fosc/4=4Mhz;1/4us
    TMOD=0x11; //0001 0001  ;Timer0和Timer1设置工作方式1:16位定时器
    TH0=(65536-40000)/256; //40000*1/4us=10ms
    TL0=(65536-40000)%256;
    TR0=0;
    ET0=1; //Timer0使能
    TR0=1; //启动Timer0
    TH1 = (65536 - 4000)/256; //4000*1/4us=1ms 用于定时处理
    TL1 = (65536 - 4000)%256;
    TR1 = 0;
    ET1 = 1; //Timer1使能
    TR1 =1; //启动Timer1
    IPT0=1; //T0中断优先权,IPT0=1代表T0中断优先权为高
    }
    void timer0()interrupt 1 //Timer0向量号 1

    //上次无水-->制水output();
        TH0=(65536-40000)/256; //再次装入初值
        TL0=(65536-40000)%256; //10ms
    if(++t0_1000ms==100)
    {
    t0_1000ms=0;
    btimer1s=1;

    if(++t1_2s==2)
    {
      t1_2s=0;
    btimer2s=1;//2s到达,TimeDeal()统计时间用
    }

    if(btimeall==105)//补偿时间计数开始
    {
    timegain++;  
    }

    }
    }
    void TimeDeal(void)
    {
    if(btimer2s)  //2s定时到
    {
    btimer2s=0; //清零
    if(++vJDQ1Tint5>=30)//当vJDQ1Tint5=30时,说明时间到达1min
    {
    vJDQ1Tint5=0;//清零
    ++vJDQ1Runmin1;//加1
    ++timeall;
    }
    //①
    if(vJDQ1Runmin1>=60)//vJDQ1Runmin=120时,说明时间到达2hour
    {
    vJDQ1Runmin1=0; //清零
    ++vJDQ1Runhour1; //加一
    ++vJDQ1Runhourbak1;//加一
    }



    if(timeall>=105)//时间补偿用,105min 16s提前了1min
    {
    btimeall=1;
    if(timegain>=16)//16s<-------------补偿前设置为0,目的测试误差
    {  
    timeall=0;
    btimeall=0;
    vJDQ1Runmin1--;
    }
    }
    }

    }



    这种补偿是我这2周弄得,在主函数总补偿,缺点精度低。想要高精度就给你个想法:往定时器里补偿,因为没空所以我没整这个方案。希望你能理解我的程序

    • 发布于2017-02-17
    • 举报
    • 评论 2
    • 0
    • 0
dos 回复了 dos :因为种种原因,源程序不能给你,上面的程序希望你能理解。105min 16s提前了1min这个是要看你实际误差,可能你的误差是1000min 2s提前2分到时你就要做出相应的修改。 回复
dos 回复了 dos :还有btimer2s=1;这个2s标志位不要像我这样弄,你要把它放在t1定时器弄,10ms检测一次,这样误差就小很多。我这里了放在t0定时器弄,1s检测一次就会有1s左右的误差 回复

  • void timerinit(void)
    {	
    	TMCON=0x03;				//------ 11 ;Timer0和Tiemr1选择时钟分频,Fosc/4=4Mhz;1/4us
    	TMOD=0x11;				//0001 0001  ;Timer0和Timer1设置工作方式1:16位定时器
    	TH0=(65536-40000)/256;	//40000*1/4us=10ms
    	TL0=(65536-40000)%256;
    	TR0=0;
    	ET0=1;					//Timer0使能
    	TR0=1;				//启动Timer0
    	TH1 = (65536 - 4000)/256;	//4000*1/4us=1ms 用于定时处理
    	TL1 = (65536 - 4000)%256;
    	TR1 = 0;
    	ET1 = 1;					//Timer1使能
    	TR1 =1;						//启动Timer1
    	IPT0=1;						//T0中断优先权,IPT0=1代表T0中断优先权为高
    }
    void timer0()interrupt 1	//Timer0向量号 1
    { 
    	 						//上次无水-->制水output();									
        TH0=(65536-40000)/256;	//再次装入初值
        TL0=(65536-40000)%256;	//10ms
    	if(++t0_1000ms==100)
    	{
    		t0_1000ms=0;
    		btimer1s=1;
    
    		 if(++t1_2s==2)
    		 {
    		   	t1_2s=0;
    			btimer2s=1;//2s到达,TimeDeal()统计时间用
    		 }
    
    		 if(btimeall==105)//补偿时间计数开始
    		 {
    		 	timegain++;		 
    		 }
    
    	}
    }
    void TimeDeal(void)
    {
    	if(btimer2s)	  //2s定时到
    	{
    		btimer2s=0;	 //清零
    		if(++vJDQ1Tint5>=30)//当vJDQ1Tint5=30时,说明时间到达1min
    		{
    			vJDQ1Tint5=0;//清零
    			++vJDQ1Runmin1;//加1
    			++timeall;							
    		}
    		//①
    		if(vJDQ1Runmin1>=60)//vJDQ1Runmin=120时,说明时间到达2hour
    		{
    			vJDQ1Runmin1=0;	//清零
    			++vJDQ1Runhour1;	//加一
    			++vJDQ1Runhourbak1;//加一
    		}
    	
    
    
    		if(timeall>=105)//时间补偿用,105min 16s提前了1min
    		{
    			btimeall=1;
    			if(timegain>=16)//16s<-------------补偿前设置为0,目的测试误差
    			{						 
    				timeall=0;
    				btimeall=0;
    				vJDQ1Runmin1--;
    			}	
    		}				
    	}
    }
    • 发布于2017-02-17
    • 举报
    • 评论 0
    • 0
    • 0

相关问题

问题达人换一批

延时几小时的话怎么做比较好?