搜索
bottom↓
回复: 15

时间触发的嵌入式系统-word版 边看边抄录

[复制链接]

出0入0汤圆

发表于 2013-10-28 14:00:57 | 显示全部楼层 |阅读模式
本帖最后由 zhongpeng123 于 2013-10-28 14:04 编辑

最近发现这本书非常不错,但全是pdf之类的,整理一下,做成word的。慢慢来,打字和查错很费力的。如果有人已经完成这个工作,我也歇歇,哈哈
目录
前言        3        6
序言        3        6
绪  言        3        8
第1章什么是时间触发的嵌入式系统        3        8
1.1  引言        3        8
1.2  信息系统        3        9
1.3  桌面系统        5        9
1.4  实时系统        5        10
1.5  嵌入式系统        7        10
1.6  事件触发系统        8        10
1.7  时间触发系统        10        10
1.8  小结        11        11
第2章使用模式来设计嵌入式系统        12        11
2.1  引言        12        11
2.2  现有软件设计技术的局限        14        11
2.3  模式        17        11
2.4  时间触发嵌入式系统模式        20        11
2.5  小结        20        11
第1篇硬件基础        25        11
第3章8051系列微控制器        25        11
引言        25        11
标准8051        25        11
精简8051        34        11
扩展8051        38        11
第4章振荡器硬件        44        11
引言        44        11
晶体振荡器        44        11
陶瓷谐振器        52        11
第5章硬件复位        55        11
引言        55        11
阻容复位        55        11
可靠的复位        62        11
第6章存储器问题        66        11
引言        66        11
片内存储器        66        11
片外数据存储器        75        11
片外程序存储器        81        11
第7章直流负载驱动        88        11
引言        88        11
直接LED驱动        88        11
直接负载驱动        93        11
IC缓冲放大器        95        11
BJT(双极结型三极管)驱动器        100        11
IC驱动器        109        11
MOSFET驱动器        113        11
固态继电器驱动(直流)        117        11
第8章交流负载驱动        121        11
引言        121        11
电磁继电器驱动        121        11
固态继电器驱动(交流)        127        11
第2篇软件基础        133        11
第9章基本的软件体系结构        133        11
引言        133        11
超级循环        133        11
项目头文件        138        11
第10章使用端口        142        11
引言        142        11
端口输入/输出        142        11
端口头文件        150        11
第11章延迟        158        11
引言        158        11
硬件延迟        158        11
软件延迟        167        11
第12章看门狗        175        11
引言        175        12
硬件看门狗        176        12
第3篇单处理器系统的时间触发结构        187        12
第13章调度器的介绍        187        12
13.1  引言        187        12
13.2桌面操作系统        187        12
13.3对超级循环结构的评价        188        12
13.4更好的解决方案        190        12
13.5例子:闪烁LED        194        12
13.6在不同的时间间隔执行多个任务        196        12
13.7什么是调度器        198        12
13.8合作式调度和抢占式调度        199        12
13.9抢占式调度器详解        202        12
13.10小结        204        12
13.11进阶阅读        204        12
第14章合作式调度器        206        12
引言        206        12
合作式调度器        206        12
第15章学会以合作的方式思考        240        12
引言        240        12
循环超时        240        12
硬件超时        245        12
第16章  面向任务的设计        255        12
引言        255        12
多级任务        255        12
多状态任务        259        12
第17章混合式调度器        267        12
引言        267        12
混合式调度器        267        12
第4篇用户界面        289        12
第18章通过RS-232与PC通信        289        12
引言        289        12
PC连接(RS-232)        289        12
第19章开关接口        317        12
引言        317        12
开关接口(软件)        318        12
开关接口(硬件)        326        12
通断开关        329        12
多状态开关        335        12
第20章键盘接口        343        12
引言        343        12
键盘接口        343        12
第21章多路复用LED显示        355        12
引言        355        12
多路复用LED显示        355        12
第22章控制LCD显示面板        367        12
引言        367        12
字符型LCD  板        368        12
第5篇使用串行外围模块        389        12
第23章使用I2C外围模块        389        12
引言        389        12
I2C外围模块        389        12
第24章使用SPI外围模块        410        13
引 言        410        13
SPI外围模块        410        13
第6篇  多处理器系统的时间触发体系结构        425        13
第25章共享时钟调度器的介绍        425        13
251 引言        425        13
25.2额外  CPU性能和外围硬件        425        13
25.3模块化设计的优点        426        13
25.4  怎样连接多个处理器        428        13
25.5  为什么增加处理器并不一定能改善可靠性        434        13
25.6小结        436        13
第26章使用外部中断的共享时钟调度器        437        13
引言        437        13
共享时钟中断调度器(时标)        437        13
共享时钟中断调度器(数据)        467        13
第27章使用UART(通用异步收发器)的共享时钟调度器        479        13
引言        479        13
使用UART的共享时钟调度器(本地)        479        13
使用UART的共享时钟调度器(RS-232)        504        13
使用UART的共享时钟调度器(RS-485)        507        13
第28章使用CAN的共享时钟调度器        530        13
引言        530        13
共享时钟CAN调度器        531        13
第29章多处理器系统的设计        557        13
引言        557        13
数据联合        557        13
长任务        560        13
多米诺骨牌任务        563        13
第7篇监视与控制组件        569        13
第30章脉冲频率检测        569        13
引言        569        13
硬件脉冲计数        569        13
软件脉冲计数        575        13
第31章脉冲频率调制        580        13
引言        580        13
硬件脉冲频率调制        580        13
软件脉冲频率调制        585        13
第32章模拟-数字转换器(ADC)的应用        591        13
引言        591        13
单次模数转换        591        13
模数转换前置放大器        606        13
序列模数转换        610        13
A-A滤波器        618        13
电流传感器        625        13
第33章脉冲宽度调制        629        13
引言        629        14
硬件脉宽调制        629        14
脉宽调制信号平滑滤波        637        14
3级脉宽调制        640        14
软件脉宽调制        646        14
第34章数模转换器的应用(DAC)        653        14
引言        653        14
数模转换输出        653        14
数模转换平滑滤波        663        14
数模转换驱动        666        14
第35章进行控制        669        14
引言        669        14
PID控制器        669        14
第8篇特殊的时间触发结构        695        14
第36章减少系统开销        695        14
引言        695        14
255-时标调度器        695        14
单任务调度器        707        14
一年调度器        712        14
第37章提高调度的稳定性        722        14
引言        722        14
稳定调度器        722        14
结    论        731        14
第38章本书试图实现的目标        731        14
38.1  引言        731        14
38.2本书试图实现的目标        731        14
38.3  小结        732        14
第39章收集的参考文献和书目        733        14
39.1  出版书刊一览表        733        14
39.2其他模式        739        14
39.3实时嵌入式系统设计技术        739        14
39.4高可靠性系统设计技术        740        14
39.5 805 1微控制器        741        14
39.6作者的相关著作        741        14
附    录        745        14

阿莫论坛20周年了!感谢大家的支持与爱护!!

知道什么是神吗?其实神本来也是人,只不过神做了人做不到的事情 所以才成了神。 (头文字D, 杜汶泽)

出0入0汤圆

 楼主| 发表于 2013-10-28 14:01:55 | 显示全部楼层
本帖最后由 zhongpeng123 于 2013-10-28 14:07 编辑

        前言        3
    现在你面对着的是一种模式语言。尽管它和我自己的模式主题有相当大的距离,然而从本质上讲,Michael的目标是对的。
    Ward Cunningham和我以前在早期商业化Smalltalk时曾一起工作。Smalltalk从一开始就被设计为一种无缝环境。你可以使用由Smalltalk编写的文字处理软件启动调试程序,修改该程序并继续输入。
    Tektronix的一些最初使用Smalltalk的用户相当古怪。我们经常谈到Ray.这个从一家大化学公司来的老家伙理解Smalltalk并确实使它跳转和运行、处理并显示实验数据。看他的演示是一种乐趣,因为他为自己所完成的工作而骄傲。
    读Ray的程序代码却是另一回事。为了使程序工作,他会做任何事,而无论多么骇人听闻。结果是程序一片混乱,完全不可维护而且只使用了 Smalltalk的一小部分功能。
    我们经常把Ray作为某些软件开发人员的象征——有问题需要解决而不得不设计软件的人。这种功利的态度与我们对软件的“不妥协精神”有着显著区别。在我们看来,力求解决方案的简明而优雅比解决该问题更重要。然而如果我们想影响众人,就不能只追求自己的美感,必须同时设法帮助Ray。
    最后所得到的模式语言是深思熟虑的建议(决不使用你不能亲白关掉的计算机)和老套的日常文档书写注意事项(将源代码中的括号对齐为矩形格式)的古怪的混合物。目的是帮助Ray从Smalltalk当中得到更多功能。但在这方面我们基本上失败了,从那时起我的职业生涯就转为网处漂泊,为写程序的人们提供建泌和辅导。
    这就是为什么我爱读Michael的文稿的原因。它为那些正好有问题要解决,然而又不想成为该解决方案的专家的人答疑解惑。现在我就是Ray。我希望把微控制器聚集到一起用于
解决各种各样的问题(好的,所以我是个书呆子),读过这些模式语言后使我有信心能把它做好。
    这些模式决不只是使我鼻子中有松香的气味,或足手中有绕线枪的感觉,而是举例说明使用模式将比一般的尝试能够完成更多的事情。模式在问题和解决方案之间架起了一座桥梁。将人们的需要和情感与技术连接在一起,并为那些有问题要解决的人们提供新的思路。
    现在就点热烙铁并享受开发的乐趣吧!
    Kent Beck   
    三河研究所   
Merlin,俄勒冈州

出0入264汤圆

发表于 2013-10-28 14:21:44 | 显示全部楼层
没有必要,重点看哪个合作式调度实现就好了。明白原理就好了,不能拘泥于此。
头像被屏蔽

出0入0汤圆

发表于 2013-10-28 14:59:39 | 显示全部楼层
提示: 作者被禁止或删除 内容自动屏蔽

出0入0汤圆

发表于 2013-10-28 17:03:55 | 显示全部楼层
这么做的意义是什么?

出0入0汤圆

 楼主| 发表于 2013-10-29 08:20:08 | 显示全部楼层
呵呵,人生有什么意义。一直在找这方面的内容,终于找到了个正主,忍不住想打印出来,word的话,可以自己调整版式,方便自己阅读。

出0入0汤圆

发表于 2013-10-29 08:24:50 | 显示全部楼层
OCR试试。以前也有这种想法,但自己太懒了。
支持楼主。

出0入0汤圆

发表于 2013-10-29 08:40:49 | 显示全部楼层
LZ想法比较好!支持

出0入0汤圆

发表于 2013-10-29 09:57:11 来自手机 | 显示全部楼层
这个调度器也不是十全十美的,
比方说,某个状态到了,需要停止任务,停不了。
我现在需要一个长时间的任务,又需要实时的,精度1微秒,就无能为力了。

出0入0汤圆

 楼主| 发表于 2013-10-29 13:44:18 | 显示全部楼层
本帖最后由 zhongpeng123 于 2013-10-29 13:48 编辑

        第13章调度器的介绍        187
    本章将介绍对应于许多现代桌面系统中的“Windows”(或其他操作系统),调度器将在嵌入式系统中扮演类似的角色。
        13.1  引言        187
  在前面第1篇和第2篇的基础之上,我们现在能够详细讨论为8051系列微控制器创建时间触发系统的方法。
    为了实现这种系统,将使用调度器。这是一种用于嵌入式系统的非常简单的运行环境。在这个介绍性的章节中,我们将说明什么是调度器以及合作式调度和抢占式调度之间的区别。同时将说明为什么使用合作式调度器将有助于使即便是最小的嵌入式系统也易于开发而且运行得更加可靠。
    首先简要地回顾桌面系统使用操作系统的原因,并说明为什么这样的操作系统不适用于奉书所讨论的嵌入式系统,并以此作为本章其余部分的讨论基础。
        13.2  桌面操作系统        187
  正如在序言里说明的,本书假定读者已经具有台式机应用软件开发的经验。在第1章中已讨论过,在许多信息系统中,桌面/工作站环境和诸如文字处理软件的通用桌面应用程序占主导地位。现代桌面环境的普遍特征是:用户通过高分辨率的图形屏幕加上键盘和鼠标与应用程序交互。操作系统以及相关的程序库为这种复杂的用户界面提供了支持。
    在这样的一个平台上,通常用户所需要的程序(诸如文字处理软件)及全部数据(诸如文字处理软件处理的文件)都在需要时从磁盘实时读取。图13.1显示了这种文字处理软件的典型运行环境。在这里应用和底层硬件被隔离开来。例如,当用户想要将最新的小说保存在磁盘上时,文字处理软件将大多数必要的工作交给操作系统完成。随后,操作系统将许多硬件相关的命令交给BIOS(基本输入,输出系统)。
    操作系统(或BIOS)对于台式PC机来说并不是必不可少的。然而,对于大多数用户来说,个人电脑的主要优点是它的灵活性。换句话说,同样的设备可以运行成千上万不同的程序。
page 188
如果PC没有操作系统,那么这些程序中的每一个都将需要能够独立实现所有的底层功能。这样。其效率将非常低,而且将使系统更加昂贵。周时也很可能将导致错误,因为即使是最小的程序也必须复制许多功能。
    想象一下没有Windows(或UNIX)的世界会是个什么样子,可以加深对这个问题的认识,考虑一个曾经在Pc上广泛使用的早期操作系统-DOS。用过DOS应用程序的读者可能会记得,每个程序都必必须提供合适的打印机驱动程序。如果打印机后来有所变化,通常意味着必须升级PC上的每个应用程序来使用新的硬件。有了Windows后,就不会出现这样的问题,当购买了新打印机时.只需要一个驱动程序。安装了驱动程序之后,计算机上的每个程序都可以直接使用这个新的硬件。
对桌面操作系统的一种看法是:它用来运行多个程序,并且提供这些程序需要的“公共代码”(用于打印、文件存储、图形显示等等)。这减少了相同程序模块的复制,降低了出错的机会,从而使整个系统更加可靠并易于维护。

图13.1运行文字处理软件的桌面计算机系统的BIOS/OS多层结构的原理示意图


图13.2桌面系统中操作系统的作用的原理示意图
        13.3  对超级循环结构的评价        188
现代桌面操作系统的许多特性(诸如图形显示、打印以及磁盘存取)对于嵌入式系统价值不大。嵌入式系统中没有很复杂的图形屏幕、打印机和磁盘。
page 189
  因此,正如在第9章看到的,许多简单的嵌入式系统所使用的软件结构都是一种超级循环。
(源程序清单13.1)的形式。
    /*************** Main.C简单的超级循环应用的结构***********/
    #include "x.h "/*--------------*/
    void main(void)
    {
      //准备任务x
      X_Init();
      while (1)//“死循环”(超级循环)
      {
        x( );    //执行任务
      }
    }
    /*文件结束*/
源程序清单13.1  简单超级循环的部分演示

  源程序清单13.1中展示的超级循环结构的主要优点是:
  (1)简单,因此易于理解;
  (2)几乎不占用系统存储器或CPU资源。
  然而,“没有投入也就没有回报”。超级循环占用很少的存储器和处理器资源是因为它们几乎不为开发人员提供什么功能。尤其是这种结构,它很难在精确的时间间隔执行任务X。正如我们将看到的,这种限制是一个非常大的缺点。
    例如:考虑从一系列不同的嵌入式项目汇集的许多要求(没有特别的前后顺序):
    ●  必须以0.5s间隔测量汽车的当前速度。
    ●  每秒必须刷新显示40次。
    ●  计算出来的新的油门位置必须每隔0.5s输出。
    ●  必须每秒执行20次时间-频率变换。
    ●  如果已经发出警报,则必须在20分钟之后关掉(法律上的要求)。
    ●  当前门被打开时,如果在30s内没有输入正确的口令,则必须发出警报。
    ●  必须每秒采样1000次发动机振动数据。
    ●  必须每秒执行20次频域数据分类。
    ●  必须每200ms扫描一次键盘。
    ●  主机(控制)节点必须每秒与所有其他节点(传感器节点和发出警报节点)通信一次。
page 190
    ●  必须每0.5s计算一次新的油门位置。
    ●  传感器必须每秒采样一次。
    总结这个列表可以发现,许多嵌入式系统必须在某些时刻执行任务。更具体地说,需要执行的任务分为两种:
    ●  周期性任务,(比方说)每l00ms执行一次
    ●  单次任务,(比方说)在50ms的延迟之后执行一次
    利用源程序清单13.1所示的基本结构很难实现上述任务。例如,假设必须每隔200ms起动任务X,而完成该任务需要10ms。源程序清单13.2说明了修改源程序清单13.1中的代码以实现这个要求的一种方法。
    /*--------------------------------------------------------*/
    void main(void)
    (
      Init_System ();
      while(1)  //“死循环”(超级循环)
      {
        x();  //执行任务(耗时10ms;)
        Delay_190ms();   //延迟190ms
      }
    }
源程序清单13.2使用超级循环结构来每隔一段时间执行一次任务
   
  源程序清单13.2中说明的方法通常是难以实际运用的,因为只有当满足以下条件时它才能工作:
  1.知道任务X的精确的运行时间
  2.这个运行时间永不变化
  在实际系统中.很难确定任务的精确运行时间。假设有一个非常简单的任务,不与外界相互作用,而仅仅执行某些内部计算。即使在这种相当有限的情况下,改变编译程序优化设置,或者即使是改变一些表面上不相关的程序部分,也可能改变任务运行的速度。这使得调节定时的过程非常乏味并且易于出错。
  第二种条件更是问题多多。在嵌入式系统中,任务往往需要以复杂的方式与外界相互作用。在这种情况下,任务的运行时间将随着外界行为的变化而变化,而程序员极难控制这种变化。

出0入0汤圆

发表于 2013-10-29 17:09:50 | 显示全部楼层
佩服你啊,这样就能深入学习了

出0入0汤圆

 楼主| 发表于 2013-10-31 13:51:12 | 显示全部楼层
发现老外确实挺不错,电子版至少不是影音的。

出0入0汤圆

 楼主| 发表于 2013-11-1 08:45:32 | 显示全部楼层
太长了。ocr加英文版合着来。

        第15章学会以合作的方式思考        240
        引言        240
    在系统中使用合作式调度器有许多好处,其中之一是它将简化开发过程。然而,要最大限度的受益于调度器,需要学会以合作的方式思考。
    例如:被调度的应用程序和桌面应用程序之间的一个主要区别是需要仔细地考虑定时和任务运行时间的问题。更具体地说,正如在第14章看到的,使用合作式调度器的应用程序的关键要求是:对于所有任务,无论在何种情况下,任务的运行时间Durationtask都必须满足以下条件:
    Durationtask <时标间隔
    本章中的模式用来帮助满足这个条件。该模式将保证,如果任务不能在规定的时段内完成,
就中止该任务。具体地说,这里给出了两个超时模式:
    ●  循环超时
●  硬件超时

        循环超时        240
适用场合
    ●  用8051系列微控制器开发一种嵌入式系统。
    ●  该系统使用调度器构造一种时间触发结构。
问题
    如何保证当系统在等待(诸如AD转换或串行数据传送)硬件操作完成时不会“挂起”?
背景知识
    Philips的8XC552是一种有许多片内模块的扩展8051芯片,它包括一个8通道的10位模数转换器。Philips提供的应用手册(AN93017)描述了如何使用这个微控制器,该应用手册包括下面的代码:


// Wait until AD conversion finishes (checking ADCI) 等待,直到AD转换结束(检查ADCI)
while ((ADCON & ADCI) == 0);
    这样的代码有可能不可靠,因为在某些情况下,可能由于如下的原因导致系统被“挂起”:
    ●  如果模数转换器的初始化不正确,不能确定模数转换将被执行。
    ●  如果模数转换器的输入电压过高,那么可能根本就不运行。
    ●  如果没有正确初始化变量ADCON或ADC1.那么可能不按要求运行。
    当然,这样的问题不只是这个特殊的微控制器或者模数转换器才有。在嵌入式系统中,这样的代码也是常见的。
    如果要求系统很可靠,则必须能够保证没有函数会这样挂起,循环超时提供了一种简单然而有效的方法来提供这样的保证。
解决方案
循环超时很容易创建,其代码结构的基础是软件延迟,创建如下:
unsigned integer Timeout_loop = 0;
...
while (++Timeout_loop);
    这个循环将连续运行直到变量Timeout_loop到达它的最大值65535(假定为16位整数),然后溢出。当溢出发生时,程序将继续。注意,不经过一些模拟研究或样机试验,很难确定这个延迟有多长。然而,可以确信循环虽终确实会超时。
    这样的循环并不是特别有用。然而,如果再次考虑“背景知识”中给出的模数转换器的例子,则可以很容易地扩展这个方法。回想一下那些最初的代码,如下所示:
// Wait until AD conversion finishes (checking ADCI) 等待,直到AD转换结束(检查ADCI)
while ((ADCON & ADCI) == 0);
Here is a modified version of this code, this time incorporating a loop timeout: 这里是这些代码的改进版本,此时加入了一个循环超时:
tWord Timeout_loop = 0;
// Take sample from ADC  从模数转换器读取采样值
// Wait until conversion finishes (checking ADCI) 等待,直到AD转换结束(检查ADCI)
// - simple loop timeout简单的循环超时
while (((ADCON & ADCI) == 0) && (++Timeout_loop != 0));
Note that this alternative implementation is also useful: 注意:下面这个替代方案同样可用:
tWord Timeout_loop = 1;
// Take sample from ADC从模数转换器读取采样值
// Wait until conversion finishes (checking ADCI) 等待,直到AD转换结束(检查ADCI)
// - simple loop timeout简单的循环超时
while (((ADCON & ADCI) == 0) && (Timeout_loop != 0))
{
Timeout_loop++;  // Disable for use in hardware simulator... 在使用硬件模拟器时禁止…
}


第一二种方法的优点是:当该代码运行在硬件模拟器上时,如果需要的话,循环超时可以容易地被注释掉。在两种情况下,现在都能确信循环将小会“永远”继续下去。注意,通过改变加载到循环变量中的韧始值,能够改变循环超时的运行时间。源程序清单15.1中的文件
TimeoutL.H出自CD上与本章有关的目录中。该文件中包括的一组常数非常近似地给出了特定的超时值。
/*------------------------------------------------------------------*-
TimeoutL.H (v1.00)
------------------------------------------------------------------
Simple loop timeout delays for the 8051 family based. 用于基于8051系列芯片的简单的循环超时延迟
* THESE VALUES ARE NOT PRECISE - YOU MUST ADAPT TO YOUR SYSTEM *
*这些值并不精确-必须根据系统修改*
-*------------------------------------------------------------------*/
// ------ Public constants 公用的常数-----------------------------------------
// Vary this value to change the loop duration改变这些值来改变循环的运行时间
// THESE ARE APPROX VALUES FOR VARIOUS TIMEOUT DELAYS
// ON 8051, 12 MHz, 12 Osc / cycle//这些是在12MHz、12振荡周期/指令周期的80 51上各种超时延迟的近似值
// *** MUST BE FINE TUNED FOR YOUR APPLICATION ***必须针对应用做调整
// *** Timings vary with compiler optimization settings ***定时随编译程序优化设置而变
#define LOOP_TIMEOUT_INIT_001ms 65435
#define LOOP_TIMEOUT_INIT_010ms 64535
#define LOOP_TIMEOUT_INIT_500ms 14535
/*------------------------------------------------------------------*-
---- END OF FILE文件结束 ------------------------------------------------
源程序清单15.1  文件TimeoutL.H
    在下面几节里,举一个如何使用这些文件的例子。
硬件资源
    循环超时不使用定时器,占用的CPU和存储器开销几乎可以忽略。
可靠性和安全性
    使用循环超时能够以极小的成本,极大地改善可靠性和安全性。然而在实际系统中,硬件超时通常是一种史好的解决方案。
可移植性
    循环超时将工作在任何平台。然而,应用小同的微控制器和编译器,得到的定时将显著变化。
优缺点小结
         与没有任何形式的超时保护的执行代码相比,这要好得多。


        许多应用程序使用一个定时器用于产生RS232波特率,使用另一个定时器来运行调度器。在许多8051                芯片中,没有更多的定时器可以用来实现硬件超时。在这些情况下,使用循环是实现有效的超时特性的惟一实用方式。
        定时很难计算,定时值不可移植。如果有一个卒闲的定时器可用,硬件超时始终是一种最佳解决方案。
相关的模式和替代解决方案
    正如在“可靠性和安全性”中提到的,硬件超时往往是循环超时的最好的替代方案。此外,硬件看门狗提供了一个替代方案。然而,比较起来该方案相当粗糙.只能检测系统级的错误(而不是任务级的)。
例子:循环超时代码的测试程序
正如已说明的,循环超时必须仔细手动调整以得到精确的延迟值。源程序清单15.2中的程序可用来测试这样的超时代码。

/*------------------------------------------------------------------*-
Main.C
------------------------------------------------------------------
Testing timeout loops. 测试超时循环
-*------------------------------------------------------------------*/
#include "Main.H"
#include "TimeoutL.H"
// Function prototypes函数原型
void Test_1ms(void);
void Test_10ms(void);
void Test_500ms(void);
/*------------------------------------------------------------------*/
void main(void)
{
while(1)
{
Test_1ms();  
  
   
  Test_10ms();  
Test_500ms();  
}
}
/*------------------------------------------------------------------*/
void Test_1ms(void)
{
tWord Timeout_loop = LOOP_TIMEOUT_INIT_001ms;
// Simple loop timeout... 简单的循环超时
while (++Timeout_loop != 0);
}
/*------------------------------------------------------------------*/
void Test_10ms(void)
{
tWord Timeout_loop = LOOP_TIMEOUT_INIT_010ms;
// Simple loop timeout... 简单的循环超时
while (++Timeout_loop != 0);
}
/*------------------------------------------------------------------*/
void Test_500ms(void)
{
tWord Timeout_loop = LOOP_TIMEOUT_INIT_500ms;
// Simple loop timeout... 简单的循环超时
while (++Timeout_loop != 0);
}
/*------------------------------------------------------------------*-
---- END OF FILE文件结束 -------------------------------------------------
-*------------------------------------------------------------------*/


源程序清单15.2测试超时代码

源程序在Keil硬件模拟器中运行。用于测试定时(如图15.1所示)。
    记住:改变编译程序优化设置或者改变即使在表面上与之无关的程序其余部分也可能
改变这些定时,因为这种改变可能会导致编译程序改变可用存储区的使用方式。
  对试验代码进行最终测试时,在超时开始计数的时候将一个端口引脚置为l。并在结
束时清除。使用示波器来测量所得到的延迟。

图15.1使用Keil硬件模拟器测试超时代码
例子:I2C库中的循环超时
本书将在第23章详细讨论I2C总线。简而言之,I2C是一种二线式的串行总线。两根线分

别称为串行数据线(SDA)和串行时钟线(SCL)(如图15.2所示)。当总线空闲时,SCL和SDA都为高。

图15.2 I2C总线
这里讨论在I2C库的一个版本中足如何使用循环超时的。在数据传输的某些阶段,必须“同步时钟”。这意味着需要等待“时钟”线(被一个从机)拉高。一些I2C代码库包括类似以下的代码片段来实现这个功能:
// Synchronize the clock同步时钟
while (_I2C_SCL == 0);   
   当然,由于本模式中介绍的各种原因,这是一种危险的方法。
    下面的代码片段使用1ms超时的循环超时来改进这蝗代码:
#define LOOP_TIMEOUT_INIT_001ms 65435
...
tLong Timeout_loop = LOOP_TIMEOUT_INIT_001ms;  
...
// Try to synchronize the clock试图同步时钟
while ((_I2C_SCL == 0) && (++Timeout_loop));   
if (!Timeout_loop)
{
return 1;  // Error - Timeout condition failed错误:不满足超时条件
}
  有关I2C总线和这个库的详细资料请参阅第23章。
进阶阅读






        硬件超时        245
适用场合
●        使用8051系列微控制器开发一种嵌入式系统。
●        该系统使用调度器构造一种时间触发结构。
问题
    如何生成准确定义的超时特性,以便当某个预期的事件没有发生时,在精确的时间(例如,0.5ms)内响应?
背景知识
相关背景材料参见循环超时。
解决方案
正如在硬件延迟看到的,可以为8051系列创建可移植并易于使用的延迟代码,如下所示:
// Define Timer 0 / Timer 1 reload values for ~1 msec delay定义用于1ms延迟的定时器0/定时器1的重装值
#define PRELOAD_01ms  (65536 - (tWord)(OSC_FREQ / (OSC_PER_INST * 1000)))
#define PRELOAD_01ms_H (PRELOAD_01ms / 256)
#define PRELOAD_01ms_L  (PRELOAD_01ms % 256)
//
...
void Hardware_Delay_T0(const tLong MS)   
{
tLong ms;
// Configure Timer 0 as a 16-bit timer将定时器0配置为16位定时器
TMOD &= 0xF0;  // Clear all T0 bits (T1 left unchanged) 清除所有有关TO的位(Tl不变)
TMOD |= 0x01;  // Set required T0 bits (T1 left unchanged) 设置所需的TD的位(T1不变)
ET0 = 0;  // No interrupts不使用中断
for(ms = 0; ms < MS; ms++)
{                 
// Note - delay value is *approximately* 1 ms per loop注意,每个循环的延迟值“大约”是1ms
// - see Delay_T0.H for details of PRELOAD_values. - PRELOAD_values的详细资料参见Delay_T0.H
TH0 = PRELOAD_01ms_H;  
TL0 = PRELOAD_01ms_L;
TF0 = 0;// clear overflow flag清除溢出标志
TR0 = 1;// start timer 0启动定时器0
while (TF0 == 0);// Loop until Timer 0 overflows (TF0 == 1) 循环直到定时器0溢出(TF0==1)
TR0 = 0;// Stop Timer 0停止定时器0
}
}        

硬件超时对这种方法做了一些简单的改变,从而能够很容易地产生精确的超时延迟。
例如:在循环超时中讨论了从Philips的8XC552微控制器中的模数转换器读的过程。
这里是最初的、有潜在危险的代码:
// Wait until AD conversion finishes (checking ADCI) 等待,直到AD转换结束(检查ADCI)
while ((ADCON & ADCI) == 0);


这里是使用循环超时来解决该问题的一个应用例子:
tWord Timeout_loop = 0;
// Take sample from A-D从模数转换器读取采样值
// Wait until AD conversion finishes (checking ADCI) 等待,直到AD转换结束(检查ADCI)
// - simple loop timeout简单的循环超时
while (((ADCON & ADCI) == 0) && (++Timeout_loop));


    使用循环超时可以显著改善这些代码的可靠性,然而计算超时的运行时间却不容易。
    这里是一个替代方案,以合理的精度提供了l0ms的延迟,适用于整个8051系列(不用修改代码):
// Configure Timer 0 as a 16-bit timer将定时器0配置为16位定时器
TMOD &= 0xF0; // Clear all T0 bits (T1 left unchanged) 清除所有有关T0的位(T1不变)
TMOD |= 0x01; // Set required T0 bits (T1 left unchanged) 设置所需的T0的位(T1不变)
ET0 = 0;  // No interrupts不使用中断
// Simple timeout feature - approx 10 ms简单的超时特性——大约l0ms
TH0 = PRELOAD_10ms_H; // See Timeout.H for PRELOAD details  PRELOAD的详细资料参见Timeout.H
TL0 = PRELOAD_10ms_L;
TF0 = 0;  // Clear flag清除标志
TR0 = 1;  // Start timer启动定时器
while (((ADCON & ADCI) == 0) && !TF0);  
源程序清单15,3中的文件Timeout.H.中给出了各种可移植的PRELOAD宏指令,该文件包含在CD上。
    注意:同样的PRELOAD值可以根据需要用于定时器0或定时器1。
/*------------------------------------------------------------------*-
Timeout.H (v1.00)
------------------------------------------------------------------
Simple timeout delays for the 8051 family based on T0/T1. 用于基于8051系列芯片的T0 /TI的简单超时延迟。
Timer must be correctly configured to use these values: 必须正确配置定时器以使用这些值。
See Chapter 11 for details. 详细资料参见第11章的内容

-*------------------------------------------------------------------*/
// ------ Public constants 公用的常数-----------------------------------------
// Timer T_ values for use in simple (hardware) timeouts用于简单(硬件)超时的定时器T_value值
// - Timers are 16-bit, manual reload ('one shot'). 定时器是16位,手动重装(“单次”)
//
// NOTE: These macros are portable but timings are *approximate*
//       and *must* be checked by hand if accurate timing is required.
//注意,这砦左指令是可移植的,然而定时是“近似的”,如果需要精确定时,必须于动复核
// Define initial Timer 0 / Timer 1 values for ~50 µs delay定义用于50微秒延迟的定时器O/定时器1的初始值
#define T_50micros (65536 - (tWord)((OSC_FREQ / 26000)/(OSC_PER_INST)))   
#define T_50micros_H (T_50micros / 256)
#define T_50micros_L (T_50micros % 256)
// Define initial Timer 0 / Timer 1 values for ~500 µs delay定义用于到5 00微秒延迟的定时器o!定时器l的初始值
#define T_500micros (65536 - (tWord)(OSC_FREQ / (OSC_PER_INST * 2000)))   
#define T_500micros_H (T_500micros / 256)
#define T_500micros_L (T_500micros % 256)
// Define initial Timer 0 / Timer 1 values for ~1 msec delay定义用于1ms延迟的定时器0/定时器1的初始值
#define T_01ms (65536 - (tWord)(OSC_FREQ / (OSC_PER_INST * 1000)))   
#define T_01ms_H (T_01ms / 256)
#define T_01ms_L (T_01ms % 256)
//
// Define initial Timer 0 / Timer 1 values for ~10 msec delay定义用于l0ms延迟的定时器0/定时器l的初始值
#define T_10ms  (65536 - (tWord)(OSC_FREQ / (OSC_PER_INST * 100)))   
#define T_10ms_H (T_10ms / 256)
#define T_10ms_L  (T_10ms % 256)
//
// Define initial Timer 0 / Timer 1 values for ~30 msec delay定义用于30ms延迟的定时器0/定叫器l的初始值
#define T_30ms  (65536 - (tWord)(OSC_FREQ / (OSC_PER_INST * 33)))   
#define T_30ms_H (T_30ms / 256)
#define T_30ms_L (T_30ms % 256)
/*------------------------------------------------------------------*-
---- END OF FILE -文件结束------------------------------------------------
-*------------------------------------------------------------------*/
源程序清单15.3文件Timeout.h
硬件资源
    硬件超时需要使用一个定时器。
可靠性和安全性
    硬件超时是本书所讨论的最可靠的超时结构
可移植性
    和所有基于定时器的模式一样,这些代码可以很容易地移植到8051系列的其他芯片上。
同时,它也可以被移植到其他微控制器上。
优缺点小结

@使用硬件超时可以得到精确的超时延迟。
@系统可用的定时器的数目非常有限。然而,当使用合作式调度器时,任务以合作的方式运行,同一个定时器可以同时用于几个任务。
相关的模式和替代解决方案
    不需要使用任何定时器硬件的替代方案参见循环超时。
    此外,硬件看门狗提供了一个替代方案。然而,比较起来,该方案相当粗糙,只能检测系
统级的错误(而不是任务级的)。


例子:测试硬件超时
源程序清单15.4说明了使用Keil硬件模拟器利用一些硬件超时得到的延迟(参见图15.3)。
/*------------------------------------------------------------------*-
Main.C
------------------------------------------------------------------
Testing timeout loops. 测试超时循环
-*------------------------------------------------------------------*/
#include "Main.H"
#include "TimeoutH.H"
// Function prototypes
void Test_50micros(void);  
void Test_500micros(void);  
void Test_1ms(void);  
void Test_5ms(void);  
void Test_10ms(void);  
void Test_15ms(void);  
void Test_20ms(void);  
void Test_50ms(void);  
// TIMEOUT code variable & TIMEOUT code (dummy here)
#define TIMEOUT 0xFF
tByte Error_code_G;
/*------------------------------------------------------------------*/
void main(void)
{
while(1)
{
Test_50micros();  
Test_500micros();  
Test_1ms();  
Test_5ms();  
Test_10ms();  
Test_15ms();  
Test_20ms();  
Test_50ms();  
}
}
/*------------------------------------------------------------------*/
void Test_50micros(void)
{
// Configure Timer 0 as a 16-bit timer
TMOD &= 0xF0; // Clear all T0 bits (T1 left unchanged)
TMOD |= 0x01; // Set required T0 bits (T1 left unchanged)
ET0 = 0;  // No interrupts
// Simple timeout feature - approx 50 µs
TH0 = T_50micros_H; // See TimeoutH.H for T_ details
TL0 = T_50micros_L;
TF0 = 0; // Clear flag
TR0 = 1; // Start timer
while (!TF0);
TR0 = 0;  
// Normally need to report timeout TIMEOUTs
// (this test is for demo purposes here)
if (TF0 == 1)
{
// Operation timed out
Error_code_G = TIMEOUT;
}
}
/*------------------------------------------------------------------*/
void Test_500micros(void)
{
// Configure Timer 0 as a 16-bit timer
TMOD &= 0xF0; // Clear all T0 bits (T1 left unchanged)
TMOD |= 0x01; // Set required T0 bits (T1 left unchanged)
ET0 = 0;  // No interrupts
// Simple timeout feature - approx 500 µs
TH0 = T_500micros_H; // See TimeoutH.H for T_ details
TL0 = T_500micros_L;
TF0 = 0; // Clear flag
TR0 = 1; // Start timer
while (!TF0);
TR0 = 0;  
// Normally need to report timeout TIMEOUTs
// (this test is for demo purposes here)
if (TF0 == 1)
{
// Operation timed out
Error_code_G = TIMEOUT;
}
}
/*------------------------------------------------------------------*/
void Test_1ms(void)
{
// Configure Timer 0 as a 16-bit timer
TMOD &= 0xF0; // Clear all T0 bits (T1 left unchanged)
TMOD |= 0x01; // Set required T0 bits (T1 left unchanged)
ET0 = 0;  // No interrupts
// Simple timeout feature - approx 1 ms
TH0 = T_01ms_H; // See TimeoutH.H for T_ details
TL0 = T_01ms_L;
TF0 = 0; // Clear flag
TR0 = 1; // Start timer
while (!TF0);
TR0 = 0;  
// Normally need to report timeout TIMEOUTs
// (this test is for demo purposes here)
if (TF0 == 1)
{
// Operation timed out
Error_code_G = TIMEOUT;
}
}
/*------------------------------------------------------------------*/
void Test_5ms(void)
{
// Configure Timer 0 as a 16-bit timer
TMOD &= 0xF0; // Clear all T0 bits (T1 left unchanged)
TMOD |= 0x01; // Set required T0 bits (T1 left unchanged)
ET0 = 0;  // No interrupts
// Simple timeout feature - approx 10 ms
TH0 = T_05ms_H; // See TimeoutH.H for T_ details
TL0 = T_05ms_L;
TF0 = 0; // Clear flag
TR0 = 1; // Start timer
while (!TF0);
TR0 = 0;  
// Normally need to report timeout TIMEOUTs
// (this test is for demo purposes here)
if (TF0 == 1)
{
// Operation timed out
Error_code_G = TIMEOUT;
}
}
/*------------------------------------------------------------------*/
void Test_10ms(void)
{
// Configure Timer 0 as a 16-bit timer
TMOD &= 0xF0; // Clear all T0 bits (T1 left unchanged)
TMOD |= 0x01; // Set required T0 bits (T1 left unchanged)
ET0 = 0;  // No interrupts
// Simple timeout feature - approx 10 ms
TH0 = T_10ms_H; // See TimeoutH.H for T_ details
TL0 = T_10ms_L;
TF0 = 0; // Clear flag
TR0 = 1; // Start timer
while (!TF0);
TR0 = 0;  
// Normally need to report timeout TIMEOUTs
// (this test is for demo purposes here)
if (TF0 == 1)
{
// Operation timed out
Error_code_G = TIMEOUT;
}
}
/*------------------------------------------------------------------*/
void Test_15ms(void)
{
// Configure Timer 0 as a 16-bit timer
TMOD &= 0xF0; // Clear all T0 bits (T1 left unchanged)
TMOD |= 0x01; // Set required T0 bits (T1 left unchanged)
ET0 = 0;  // No interrupts
// Simple timeout feature - approx 10 ms
TH0 = T_15ms_H; // See TimeoutH.H for T_ details
TL0 = T_15ms_L;
TF0 = 0; // Clear flag
TR0 = 1; // Start timer
while (!TF0);
TR0 = 0;  
// Normally need to report timeout TIMEOUTs
// (this test is for demo purposes here)
if (TF0 == 1)
{
// Operation timed out
Error_code_G = TIMEOUT;
}
}
/*------------------------------------------------------------------*/
void Test_20ms(void)
{
// Configure Timer 0 as a 16-bit timer
TMOD &= 0xF0; // Clear all T0 bits (T1 left unchanged)
TMOD |= 0x01; // Set required T0 bits (T1 left unchanged)
ET0 = 0;  // No interrupts
// Simple timeout feature - approx 10 ms
TH0 = T_20ms_H; // See TimeoutH.H for T_ details
TL0 = T_20ms_L;
TF0 = 0; // Clear flag
TR0 = 1; // Start timer
while (!TF0);
TR0 = 0;  
// Normally need to report timeout TIMEOUTs
// (this test is for demo purposes here)
if (TF0 == 1)
{
// Operation timed out
Error_code_G = TIMEOUT;
}
}
/*------------------------------------------------------------------*/
void Test_50ms(void)
{
HARDWARE TIMEOUT 313
// Configure Timer 0 as a 16-bit timer
TMOD &= 0xF0; // Clear all T0 bits (T1 left unchanged)
TMOD |= 0x01; // Set required T0 bits (T1 left unchanged)
ET0 = 0;  // No interrupts
// Simple timeout feature - approx 10 ms
TH0 = T_50ms_H; // See TimeoutH.H for T_ details
TL0 = T_50ms_L;
TF0 = 0; // Clear flag
TR0 = 1; // Start timer
while (!TF0);
TR0 = 0;  
// Normally need to report timeout TIMEOUTs
// (this test is for demo purposes here)
if (TF0 == 1)
{
// Operation timed out
Error_code_G = TIMEOUT;
}
}
/*------------------------------------------------------------------*-
---- END OF FILE -------------------------------------------------
-*------------------------------------------------------------------*/
源程序清单15.4测试硬件超时
例子:产生基于超时的延迟
    可以很容易地扩展“超时”技术,用作硬件延迟的一种替代方案,参见源程序清单15.5。
   void Delay_50micros(void)
{
// Configure Timer 0 as a 16-bit timer
TMOD &= 0xF0; // Clear all T0 bits (T1 left unchanged)
TMOD |= 0x01; // Set required T0 bits (T1 left unchanged)
ET0 = 0;  // No interrupts
// Simple timeout feature - approx 50 µs
TH0 = T_50micros_H; // See TimeoutH.H for T_ details
TL0 = T_50micros_L;
TF0 = 0; // Clear flag
TR0 = 1; // Start timer
while (!TF0);
TR0 = 0;  
}

源程序清单15.5使用硬件超时来实现延迟

图15.3使用Keil硬件模拟器测试硬件超时
Page254
进阶阅读

出0入0汤圆

 楼主| 发表于 2013-11-1 13:35:37 | 显示全部楼层
呵呵,太累了,有谁愿意参加,分章整理。

出0入93汤圆

发表于 2013-11-1 13:37:31 | 显示全部楼层
OCR再校对会省点力气吧

出0入0汤圆

 楼主| 发表于 2013-11-1 13:41:07 | 显示全部楼层
也不行。原版质量太差了,ocr错字漏字还有很多问题,完成一章需要1个小时去校对
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片。注意:要连续压缩2次才能满足要求!!】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-7-23 14:16

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

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