13802|9

66

帖子

0

TA的资源

一粒金砂(中级)

楼主
 

关于定时器延时程序的疑问 [复制链接]

大家好,我想针对这个定时器延时程序问几个问题:
#define  f   3686400  //系统时钟为3.6864MHz
void t0_wait_ms(unsigned char ms)
{
   TCON &=~ 0x30;
   TMOD &=~ 0x0F;
   TMOD |= 0x01;
   CKCON |= 0x04;                                     //定时器0采用16位模式,选择系统时钟
   while(ms)
   {
      TR0 = 0;                                             //关闭定时器0
      TH0 = -(f / 1000 >> 8);
      TL0 = -(f / 1000 );
      TF0 = 0;                                             //清中断标志位
      TR0 = 1;                                             //打开定时器0,开始计时
      while(!TF0);                                        //等待定时器溢出置位
      ms--;
   }
   TR0 = 0;
}
恩,其中红色的两句话我琢磨了半天都不是很明白,我的理解是这样的:
现在这个程序的效果是,每一ms定时器溢出一次,若要延时4ms则要循环4次,也就是说进阶单位为1ms。那么我们需要算出定时器高位寄存器TH0和低位寄存器TL0的初值,填入其中以保证定时器每1ms溢出一次。这个初值怎么算?我是这样想的,首先要算出延时1ms需要计的脉冲个数,T=1/(f/1000)ms, 故脉冲个数=1ms/T,将T带入得:脉冲个数=f/1000;定时器为16位的,故最多可以计数65536个,则65536-脉冲个数=计数器初值;将计数器初值转化为16进制数,高位赋给TH0,低位赋给TL0。

程序中的这两句话我不明白的地方有三点:
1、f/1000=3686.4,这不是一个整数,怎么进行移位呢?是计算机自行变成3686了吗?
2、负号“-”怎么理解?这是最糊涂的地方...
3、f / 1000 >> 8我可以理解一点,但TL0 = -(f / 1000 )就不理解了,可能归根到底还是那个负号没明白
恩,谢谢哈,基础实在是不太好嘿嘿~~希望大家多多给予批评指正
此帖出自单片机论坛

最新回复

7实,俺没玩过51单片机,只是从你的例子中,给定时器的赋值是负数推测出计数器应该是每个时钟做+1运算的。这是用硬件计时的一般手法。 搭硬件嘛....有加法器电路,不过现在实际很少用了,因为用一块可编程逻辑芯片能把好多杂碎电路(甚至CPU核)都囊括进去,于是加法器电路也变成了语言描述。 用VHDL语言写的51的核可在网上免费当漏得,不过内容太多,俺没读过,关于定时器的计数过程,搅得它应该是这么写的吧: process(CLK) begin  if (CLK'event and (CLK = '1')) then   if (TCNT /= 0) {    if (TCNT = 65535) {    -- 16位全1,下一步就要溢出     TF0   详情 回复 发表于 2008-8-5 09:14
点赞 关注
 

回复
举报

228

帖子

0

TA的资源

一粒金砂(中级)

沙发
 

连蒙带猜...

1、TH0、TL0在头文件里都是被定义成整数的,所以有小数点也当没看见。:D
2、定时器的计数寄存器一定是正计数(increment),溢出置标志位,所以“负x”就等于“再加上x时溢出”,正合适。(题外话:假如计数寄存器是倒计数的话,那么设置时负号就不要了。)
3、别看到负数害怕,只要想想那个特殊的-1就清楚了:-1的16位二进制是FFFF,再加1就是0——溢出!
此帖出自单片机论坛
 
 

回复

66

帖子

0

TA的资源

一粒金砂(中级)

板凳
 

基本上明白了,谢谢啊

谢谢你啊嘿~
第一个问题明白了
定时器的计数寄存器一定是正计数(increment),溢出置标志位,所以“负x”就等于“再加上x时溢出”,正合适。(题外话:假如计数寄存器是倒计数的话,那么设置时负号就不要了。)说得太好了,佩服!:D

具体计算机是怎样处理计算的,还需要学习呀,好像在《计算机系统结构》里面提到了一点,看的不是很明白~~恩,继续Fighting
此帖出自单片机论坛
 
 
 

回复

66

帖子

0

TA的资源

一粒金砂(中级)

4
 

又有了一点理解

对于这两句话又有了一些理解,不知道对不对:
1、可以将TH0 = -(计数脉冲个数>>8)理解为TH0 = 0 -(计数脉冲个数>>8),而十六进制的0 = 255 + 1 = (-1)+ 1,也就是说可以把十六进制的0理解为256个计数脉冲个数,这样就很容易明白这个式子了。
2、或者可以将TH0 = -(计数脉冲个数>>8)当作负数进行运算,即取正数(计数脉冲个数>>8)的补码,这样就可以得到正确的数据了。补码补码,就是互补的码啊。比如,-2 + 2 =  0 =  65534  +  2。不知道是不是可以这样理解?

另外,可以把这个延时程序改成每0.5ms、2ms==溢出一次。只要把f/1000改成f/2000或者f/500==就可以了,这样可以分别应用于需要更短的延时,或者需要延时稍长的时间,增加步进值从而减少循环次数,是不是可以节省时间呢?但是也不知道有没有必要这样做。反正这是思考的结果吧。
此帖出自单片机论坛
 
 
 

回复

228

帖子

0

TA的资源

一粒金砂(中级)

5
 

想得对,奖赏一根红萝卜

关于1和2:数学上怎么理解都可以,各人可按自己容易记的方式去记忆。硬件上的实现办法是,对计数器每个时钟处理一次,不看符号位:
 if (计数器≠0) {
  if (计数器=1) {
   置溢出;
  }
  计数器 = 计数器 - 1;
 }

关于定时器的定时长短和循环次数的关系,想到这一步非常重要!定时器设得越短,定时分辨率就越高,但软件开销就越大。
在顶楼的例子里怎么做都无所谓,但在实际应用中定时操作通常是以中断方式进行的,设计者应尽量减小软件开销,这是玩嵌入式的人必须具备的素质。
此帖出自单片机论坛
 
 
 

回复

66

帖子

0

TA的资源

一粒金砂(中级)

6
 

回复 5楼仙猫 的帖子

“定时器设得越短,定时分辨率就越高,但软件开销就越大。”
软件开销是一个什么样的概念?(抱歉啊,没有找到满意的描述)
在这个具体例子中的软件开销就越大,是不是指,为了达到高的分辨率使得循环次数增多了?

“在实际应用中定时操作通常是以中断方式进行的,设计者应尽量减小软件开销”
没想明白这两句话的关系,嘿嘿嘿~~~

if (计数器≠0) {
 if (计数器=1) {
  置溢出;
 }
 计数器 = 计数器 - 1;
}
怎么是每个时钟对计数器减1呢?这里的计数器指的是什么呢?是给计数器中的寄存器所赋的值吗?
谢谢你~
此帖出自单片机论坛
 
 
 

回复

228

帖子

0

TA的资源

一粒金砂(中级)

7
 

扫瑞,上面可能是俺没说清楚

1、软件开销是指软件为处理一件事花费的时间。
  假如为获得10ms的定时,设置硬件定时器的溢出周期为0.1ms,那么循环100次得到10ms;如设置溢出周期为1ms的话,那么只要循环10次就行了。软件的负担,或者说软件开销是前种方法的1/10。
  节省软件开销在这个简单的程序里看不出好处来,但如果不是循环,而是改用中断计数的话,好处就大了去了。比方说CPU具有20万次运算/秒的能力,处理一次中断需运算10次,而你设置中断周期为0.1ms的话,那么CPU在1秒钟内必须付出10万次运算的代价去处理中断——一半的能力被占用掉了!假如把中断的次数减小到1/10,这下轻松了吧?

2、俺写的那几句 if 语句是指硬件处理。写错了,该写成寄存器+1,以符合你的51CPU,这里表示一下汗颜.... :L
此帖出自单片机论坛
 
 
 

回复

66

帖子

0

TA的资源

一粒金砂(中级)

8
 

么4,太感谢啦

表达的很清楚呀,让俺又明白了不少捏~~谢谢你!

“俺写的那几句 if 语句是指硬件处理。写错了,该写成寄存器+1,以符合你的51CPU”
为什么要这么说呢?
嘿嘿,那硬件是怎么处理的呢?天,晕了~~
此帖出自单片机论坛
 
 
 

回复

228

帖子

0

TA的资源

一粒金砂(中级)

9
 
7实,俺没玩过51单片机,只是从你的例子中,给定时器的赋值是负数推测出计数器应该是每个时钟做+1运算的。这是用硬件计时的一般手法。
搭硬件嘛....有加法器电路,不过现在实际很少用了,因为用一块可编程逻辑芯片能把好多杂碎电路(甚至CPU核)都囊括进去,于是加法器电路也变成了语言描述。
用VHDL语言写的51的核可在网上免费当漏得,不过内容太多,俺没读过,关于定时器的计数过程,搅得它应该是这么写的吧:

process(CLK)
begin
 if (CLK'event and (CLK = '1')) then
  if (TCNT /= 0) {
   if (TCNT = 65535) {    -- 16位全1,下一步就要溢出
    TF0 <= '1';       -- 溢出时TF0置1
   }
   TCNT <= TCNT + 1;
  }
 end if;
end process;

玩过C语言的应差不多能看懂这段文字,不过暂时似没必要在这上花太多功夫。等真要设计硬件时会发现,它跟做软件是何等相似。:D

[ 本帖最后由 仙猫 于 2008-8-5 09:19 编辑 ]
此帖出自单片机论坛
 
 
 

回复

66

帖子

0

TA的资源

一粒金砂(中级)

10
 

哈哈~

谢谢你呀!
这段程序,我确实只能凑合着连蒙带猜能看明白~
关于可编程逻辑芯片,虽然听说过也有段时间了,但是从来也没望文生过生义...:L 上周末在聊天的过程中才知道CPLD大概是啥子意思...呵呵没关系,慢慢来咯,做事要分主次嘛~这毕竟不是我现在的主要任务~~
还是要向你表示感谢哈哈~~
此帖出自单片机论坛
 
 
 

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

随便看看
查找数据手册?

EEWorld Datasheet 技术支持

相关文章 更多>>
关闭
站长推荐上一条 1/7 下一条

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

About Us 关于我们 客户服务 联系方式 器件索引 网站地图 最新更新 手机版

站点相关: 国产芯 安防电子 汽车电子 手机便携 工业控制 家用电子 医疗电子 测试测量 网络通信 物联网

北京市海淀区中关村大街18号B座15层1530室 电话:(010)82350740 邮编:100190

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2025 EEWORLD.com.cn, Inc. All rights reserved
快速回复 返回顶部 返回列表