我们知道,这样一个程序,需要两个部分。 1. LED的亮灭控制; 2. 延时函数; 如果只是像那些入门教程那样直接写在main函数里,这是非常简单的。
现在让我们考虑,如何实现 独立于MCU这个目标。 首先,我们知道,LED的亮灭控制,本质上是控制IO口输出高或者低电平。这是与MCU有关的——不同的单片机,操作的方式和操作寄存器是不一样的。 延迟函数非常好办,因为它与平台无关。 倒是LED的亮灭函数,它与单片机有关,因此,不适宜直接封装到库里去。 但是,再仔细想想,尽管控制LED亮灭的寄存器不一样,然而,在这个LED闪烁函数里,让LED亮,让LED灭这个操作本身,却是与控制LED亮灭无关的。 我的意思是,不管你通过什么寄存器来控制LED亮灭,但我什么时候让LED亮什么时候让它灭却是与寄存器无关的。 这就好比,我想去成都旅游这件事,和我到底是坐火车还是坐汽车,或者飞机去成都这几种交通方式无关的一样。 所以,我们的做法是,“让LED什么时候亮LED什么时候灭”这个功能可以做进库里。而LED如何亮灭,交由应用程序实现。
这里头稍微有一点技术细节要处理,它也是这篇帖子里的一个技术要点(除此以外都是技术思想)。 我们已经介绍过。 库本身,在形式上,是一系列函数单独编译以后得到的二进制代码; 前面说的,Led_Light();Led_Dark(); 这两个函数,在编译库的时候,我们并没有实现这两个函数。 而我们却已经在库的源码里调用了它们。 我承认,这确实让人感觉有点怪。 而我本人,也是在逻辑上觉得可行,然后确实尝试了一次,发现的确管用以后,才理出了头绪,并由此,决定了这篇帖子采取的这种方式来实现独立于MCU平台。 原理很简单: 因为,库的编译过程,不涉及 链接 这个动作,也就是说,它不需要确保库源码里所用到的函数都已经明确定义了。 但是,它必须知道函数的接口,所以,我们只要提供一个声明即可。 而声明和定义本身是完全无关的。我们可以写一百个一千种函数定义,然后共用同一种声明。 而这不妨碍库里先调用它。 这个方法巧妙就巧妙在这里。你可以把那一百个一千种定义 引申到 一百个一千种单片机机型的寄存器操作。 就这样,我们实现了 LED闪烁函数独立于 MCU平台。 这里必须说明,对于LED这类直接操作IO的简单操作,这种库的风装方式也显得非常简单,看起来好像也没有什么太大意义。 但我想说,这只是一个入门的简单例子,就像学单片机点亮LED一样。接下来,我会一步一步举例在不同应用模式下的封装方法,如何基于这种思想实现。 你将会看到越来越复杂的应用实例,越来越复杂的实现方法,实现越来越酷的抽象方式——抽象于MCU机型,抽象于不同应用项目。
下面是代码。
具体的编译方法。
我个人最常用各种IAR的ide。在IAR下是很简单的,区别就在 option选项里,C/C++ compiler这个选项里的output 勾选 library,而不是 execute就可以了。
下面附上示例代码。
|