1、UML嵌入式系统开发实例讲义名称:UML嵌入式系统开发实例本讲义内容包括: 1. 录音程式(Recorder) - p.22. 单晶片嵌入式软体介面设计 - p.2- 以8051控制四位数七节LED灯为例本文引自 高焕堂所着的 “物件导向ANSI-C” 和 “物件导向Keil C51”两书UML嵌入式系统开发实例之二如何实现嵌入式介面设计- 以四位数七节LED灯为例- 情 境:LED显示灯控制- 建 模:SysML/UML- 语 言:物件导向Keil C51- CPU:8051- 平 台:无OS单晶片介面用途:从硬体的PnP谈起硬体埠(Port)就是介面 8051硬体的埠(Port)其实就是介
2、面,透过介面可以连接到LED、蜂鸣器、及键盘(Keyboard)等等。如下图: 硬体的介面有了像P0、P1等介面,个8051单晶片就可以随时与LED显示器分合自如,也就俗称的PnP(Plug and Play)。日常生活中的介面上述的介面观念并不是电脑硬体才有。在一般生活上已经存在非常久远了。例如:例如家中墙壁上的插头介面:日常生活中的插头/插座介面 上图里,X 、Y 、Z牌的电器皆提供双脚插头。而A 、B 皆为双孔插座。透过介面能带来许多方便,例如Z 可插在A 上,也可将Z 拔出来换插在B上X 可随时插到A 或B。所以共可有XA、XB、YA、YB、ZA、ZB六种搭配,极具弹性。 X 、Y 、
3、Z 三者具有共同介面。A 、B 具有共同介面。双方介面能相容合作,就创造出极大弹性了。插头与插座两个族群能各自发展,只要介面一致,就能相辅相成。例如电器业者可以推出更多种的电器,则电器体系就会无限成长了,如下图所示。 插头体系之扩充 由于Ym、Yn及K 与X 、Y 、Z 的介面是一致的,都提供双脚插头。所以皆可买回家插在A 或B 牌插座上。同理,插座族群亦能扩充如下图所示: 插座体系之扩充 这两族群在独立成长的过程中,其介面维持不变,保持其相容性。所以新型电器如Ym,可插在新型的C电脑桌之插座上。当然,新旧也仍可搭配,如X 可插在D餐桌之插座上,以上是带给消费者之利益;此外,也带给生产者好处:
4、电器设计者(如声宝家电)不必考虑到插座背后的电源构造(及其可能之变化),只要介面一致(两脚插头搭配双孔插座)就行了。另一方面,插座背后电源结构之设计者(如水电设计师)也不必费心去了解电器之构造,只要提供一致介面(两脚插头搭配双孔插座)就行了。因此,消费者、电器制造者、及水电设计师三方皆获得益处。如此,系统不只追求一时的连结,更要追求持久的和谐与成长。为了达成这个目标,系统的新陈代谢必须顺畅,也就是,系统内之物件必须能随时迅速汰旧换新、分合自如(即PnP)。汽车轮盘就是介面 为了实现PnP,我们必须进行介面设计,就如同汽车的轮胎能随时抽换(PnP),其依赖标准的轮盘(即介面)设计。也是因为能随时
5、抽换轮胎(即分合自如),所以汽车能持久保持整体的和谐。PnP(即分合自如)是目的,而介面是手段。介面设计之优劣关系到PnP之效果。例如上述的汽车轮胎坏了,只要从介面(如轮盘)卸下坏轮胎,换上新轮胎就让汽车恢复了。轮盘介面之存在价值就在于:汽车的部份(如轮胎)受损了,只要PnP、迅速换上新轮胎,就不牵累了整部汽车,避免汽车瘫痪。 就轮胎的角度而言,汽车是轮胎的Client,它正使用轮胎,接受轮胎的服务。当NISSAN汽车能以一视同仁的态度来对待不同厂牌的轮胎(如固特异轮胎、南港轮胎)时,也就是不同厂牌的轮胎,只要合乎轮盘介面,就能PnP到汽车上,这就是多形性了。所以多形性与PnP的涵意是一致,都
6、意味着:做好介面设计,促进物件之分合自如,让系统不会因某部份改变而造成瘫痪,反而新陈代谢顺畅、生生不息。介面代表一个空间 轮盘介面,代表一个虚的空间,凡是符合此介面的物件(包括未来可能会出现的新品牌轮胎),皆属于该空间的元素。此空间内的元件会生生不息、推陈出新、更新版本,就是所有过去、现在、未来的多形性物件的集合,就是此空间。这个空间是跨时间的,也是跨空间的。透过介面空间容纳更多别人未来的元件,不但整合了别人的元件,也整合别人源源不绝的设计智慧,让自己成长更快。此外,也整合别人过去、现在、未来所设计的产品。如此,一方面让自己的系统生生不息;另一方面让别人的物件拥有更多用途和历练、品质更加精美;
7、回过头来,更促进我们系统的品质与生命力,构成Win-Win-Win . 的繁荣景象。因之,介面是系统分析与设计的关键、是追求系统品质的尚方宝剑。软体介面 在8051硬体组件里含有嵌入式软体,如下图: 图 嵌入式软体的角色如果软体也有埠可连结硬体埠时,如下图: 软体物件的介面LED物件的data_port连接到8051硬体组件P0时,其关系就相当于硬体组件P0连接到LED显示器之关系。基于这个相对应关系可得到效果: 你已经理解:8051硬体组件很容易将LED显示器PnP掉。 同理可知道:LED软体物件很容易将8051硬体组件PnP掉。当我们从8051硬体组件PnP掉LED显示器时,意味着:805
8、1硬体组件(如同车体)的重用(Reuse);而不是LED显示器(如同轮胎)的重用。许多人误解为介面设计是在追求小物件的重用,其实是不对的。想一想,当您的台灯灯管坏了,把坏灯管拔掉,换上新灯管,结果是:重用了整个台灯,而不是重用灯管。在想一想,一部Benz轿车轮胎坏掉了,把坏轮胎抽换掉,整部汽车恢复完好,所以重用整部汽车了。当然,轮胎也有其重用之价值,只是其价值不高;反而重用整部汽车的价值非常高。为了让您更深刻体会这个真谛,兹举Steven Vogel在他的书- 猫掌与弹弓 里所说的:对人类来说,.系统功能要达到整齐划一,通常得凭藉建造过程的持续一贯,零件(物件)要能够彼此互换也需要高度的一贯性
9、。自然界确正好相反,不仅对于零件互相交换毫无兴趣,甚至还积极反对它。(例如免疫系统排斥心脏移植)。所以,介面设计之意义,并非要不断重用它来获利;而是追求能低成本换掉坏元件,然后装上新元件;就等于重用整个系统里的其它好物件,以及该新物件。所以: 轮胎(物件)是要换掉的,不要想去Reuse轮胎,其价值很低。 换掉坏轮胎,等于再生(Renew)一部汽车,等于重用整部汽车的其它好物件,价值极大。 换掉坏轮胎,而装上新轮胎,等于使用(Use or Reuse)未来所有潜在可用的物件。积极换掉旧物件,等于积极重用未来潜在的新元件。重用既有元件是有意义,但是价值不高,若因之而必须调整整个系统的其他好物件(即
10、牵一发动全身),就得不偿失了!最后,请您看看世界知名软体专家Cheesman & Daniels的书- UML Components: A Simple Process for Specifying Component_Based Software里所说的:“This may surprise some people. Many think the primary objective of components is reuse. They want to design something once and use it over and over again in different con
11、texts, thereby realizing large productivity gains, taking advantage of best-in-class solutions, the consequent improved quality, and so forth. These are admirable objectives, but the main driver today is that things keep changing, and often - as with business-to-business electronic commerce - there
12、is no longer any hope that centralized control can not be exerted. In such an environment one of the primary objectives of a component is that it must be easily replaceable . ”(这可能会让您很惊讶!许多人认为元件的主要目标是重用元件。其希望只要设计一次元件,就能一再地在不同场合里反覆使用它,因而提高人员产能,运用最好的解决方案,然后改善品质等等。但是,今天问题的根源在于一切事情都快速变迁 - 尤其是跨企业的电子商务 -
13、中央集权机制已无用武之地。在此环境里,软体元件设计的首要目标就是:能轻易把它换掉。)能以极低的成本换掉坏元件,就能带给软体系统弹性、灵活及生命力,其元件的新陈代谢极为顺畅。元件(物件)就如同壁虎的尾巴,当壁虎的尾巴被猫咬住时,会立即断尾逃生。壁虎迅速干净例落地丢弃旧物件,重用没有被咬住的身体,再生出新尾巴(物件),恢复(Renew)成一只活生生的完整壁虎。如果壁虎不能轻易弃尾(抛弃物件)逃生,这个已经不能正常运作的尾巴(坏物件)就会拖累整只壁虎。软体介面的范例之一分析与设计现在我们使用Keil C来逐步实作上图15-7的软体介面。从下图可知LED类别需要定义两个埠,如下图: 图15-8 规划L
14、ED物件的介面以LW_OOPC定义LED类别如下:CLASS(LED) void (*data_port)(char); void (*scan_port)(char); ;接下来,设计两个channel(可呈现为物件或函数)。例如,static void channel_0(char y) P0 = y;static void channel_1(char x) P1 = x;其中,channel_0已经连接到P0,而channel_1已经连接到P1。现在就拿channel_0连接到LED物件的data_port。同时也拿channel_1连接到LED物件的scan_port上。其指令写法为
15、: LED *t; t-data_port = channel_0; t-scan_port = channel_1;于是就将LED物件与8051硬体组件连接起来了,如下图: 图15-9 以channel连接软体物件与硬体组件分析与设计上述图15-8和15-9都不是UML标准图示,兹以StarUML工具绘制UML的组合结构图(Composite-Structure Diagram)如下:图15-10 UML的组合结构图以Keil C实作软体介面首先撰写LED类别的定义:/* EX15-led.h */#ifndef LED_H#define LED_HCLASS(LED) void (*dat
16、a_port)(char); void (*scan_port)(char); void (*run)(LED*);#endif 定义了data_port和scan_port两个函数来实现LED物件对外的埠。接着定义一般软体内部函数run()来处理物件内部的事务。如下述程式码:/* EX15-led.c */#include #include lw_oopc_kc.h#include ex15-led.hvoid g_delay(unsigned long ms) long i, j; for(i=0; ims; i+) for(j=0; jdata_port = channel_0; t-s
17、can_port = channel_1; /* - */ P0 = 0xf0; ch = SEGTAB0; sc = SCANLINE0; t-scan_port(0xff); t-data_port(ch); t-scan_port(sc); g_delay(20000); /* - */ ch = SEGTAB9; sc = SCANLINE1; t-scan_port(0xff); t-data_port(ch); t-scan_port(sc); g_delay(20000);CTOR(LED) FUNCTION_SETTING(run, run)END_CTOR 执行run()函数
18、里的指令: t-data_port = channel_0; t-scan_port = channel_1; 就把channel_0()和channel_1()连接到LED物件的两个埠上。接下来的指令: ch = SEGTAB0; /取得0这个数字的data_code sc = SCANLINE0; /取得显示在第0个位置的scan_code t-scan_port(0xff); /清除 t-data_port(ch); /送出data_code到P0 t-scan_port(sc); /送出scan_code 到P1于是LED显示器的第1位数出现0。再来的指令: ch = SEGTAB9;
19、 /取得9这个数字的data_code sc = SCANLINE1; /取得显示在第1个位置的scan_code t-scan_port(0xff); /清除 t-data_port(ch); /送出data_code到P0 t-scan_port(sc); /送出scan_code 到P1于是LED显示器的第2位数出现9。 最后撰写main()函数:/* EX15-ap-1.c */#include #include lw_oopc_kc.h#include ex15-led.hextern void* LEDNew();char xdata MemPool1024;void main (void) LED *led; init_mempool(MemPool,sizeof(MemPool); /* - */ led = LEDNew(); led-run(led);
copyright@ 2008-2022 冰豆网网站版权所有
经营许可证编号:鄂ICP备2022015515号-1