所有嵌入式系统最终都要连接到外部传感器与执行器或内部功能模块与外设等硬件以实现输入输出、数据存储及通信功能。每种设计方案中的每个硬件都有其自己的特性,需要设计人员认真对待。
设计方案中使用的硬件如果发生任何变化,即便是仅仅添加或去除一个输入或输出端口,也会影响到嵌入式软件,有时甚至会造成非常严重的影响。如果在设计过程后期才做出上述变动,那么就可能导致产品不能及时上市。解决这一问题的办法,就是在系统设计过程中确保完全的硬件独立性。
硬件独立性设计(design-out the hardware)就是指将所有控制和算法软件与硬件接口软件相分离。我们应有效地设计与硬件有关的逻辑封装器和接口,这样不管什么时候用逻辑部件来替换正在使用中的特定硬件,也不会影响控制和算法软件。
通过便于理解的逻辑接口(函数、宏、符号)将硬件提取出来,这不仅有助于提高设计的可移植性,而且还能使开发人员集中精力解决实际的应用问题,甚至在明确采用什么硬件之前就能开始设计工作。这听起来似乎比较简单,您可能认为现在您或您的工作团队正是这么做的。
不过,我们不妨来认真研究一下当前的设计项目(或者曾经喜欢的项目),看看要是更换其中的微控制器,会出现什么情况。如果改用不同的微控制器,尤其是不同厂商的微控制器的话,要是会对项目造成严重影响,那么您在设计过程中就没有实现硬件独立性。
为了成功实现硬件独立性设计,我们必须在设计过程中保持清醒的头脑。我们不必等硬件完全设计好了再开始开发嵌入式软件,也不必等到明确所有要求后最终确定硬件选择,而是可以将设计方案中的硬件选择与设计方案相分离,这样在市场崭露头角的时候我们就可以开始设计工作,从而有助于赢得关键客户。说到底,有哪些设计项目中硬件是真的一成不变的呢?最后总是会出现硬件变动的情况。
用这种方法开始设计工作有助于提高整体灵活性,这既是由于硬件几乎随时“能够”替换,同时也是由于我们不用担心硬件的替换问题了。此外,由于硬件特定的功能位于封装器与接口中,因此这有助于简化调试工作,也增加了不同项目之间 IP 的重复利用率。
“硬件独立性设计” 是什么意思?
最简单地说,嵌入式系统的硬件独立性设计就是在逻辑上把嵌入式应用软件与所有硬件直接相连的软件相分离。所谓“所有”硬件就是指物理设计或选定微控制器发生变化时可能发生的任何变化因素。
显然这包括选定微控制器中支持硬件的所有器件,如模数转换器(ADC)和通信接口(UART、SPI、I2C、USB、CAN 等)。不过如果物理系统设计还包括传感器与执行器,那么它们的变动也会影响软件,因此必须确保其 为硬件独立性设计。
此外,不要忘了输入/输出端口与嵌入式存储器等常见元件。如果它们发生变动,也会影响应用(比方说用于记录数据日志或存储配置选择的非易失性存储器,或提供内部上拉或内置驱动电路的输入端口)。总之,所有硬件都要做到独立系统设计。
有的读者可能会想,硬件独立性设计方案到底有什么新颖之处?几千年以前,睿智的所罗门国王曾经说过:“太阳下面没有什么东西是新的。”嵌入式系统硬件独立性设计背后的理念实际并不是什么新东西。自从现代嵌入式系统设计出现以来(我认为大约是在 1980 年吧),工程师一直在围绕硬件构建封装器与接口。
本文要说明的是,我们应当把这种方法发挥到逻辑极致,否则我们的项目就仍然会受限于硬件,就不能在需要时灵活地更改硬件。我希望您通过本文能够充分认识到硬件选择对嵌入式设计的影响,并能够了解到在今后设计中消除硬件变化影响的一些小窍门。
从何做起?
开始项目设计时,您至少要有一些基本的想法或要求。我们应着手设计一种独立于硬件的系统。系统应当实现什么功能?最终目标是什么?需要哪些驱动、监控功能?如果加入硬件的话,就要把整个信号链中的各个部分组成一个有机的整体。
您会发现,所有彼此相互连接的硬件实际上都是替换硬件情况下潜在的问题来源。我们要用封装器或接口将所有硬件隔离起来。就马达控制设计而言,我们不妨来看看它的算法,看看要用哪些数据来确定驱动指令。
为了控制算法,不管采用什么硬件,不管是几安培的负载电流,还是每分钟多少转的转速,还是百分比驱动命令,都必须确保逻辑性。
通过硬件和算法相结合,负载电流转换为电压,ADC 对其采样后转换成数字计数,再通过数学函数转换为毫安;上面每个步骤都需要进行“包装”,避免底层硬件改变时影响软件应用。
如果在设计过程中完全遵循上述步骤,那么最终我们就能实现两个目的。首先,我们能明确硬件与最终系统的关系,并了解到类似但不同的新项目如何从现有的设计方案受益。其次,如果需要设计全新的项目,采用完全不同的应用类型,那么仍能参考现有的项目,只需对其加以调整,就能满足新项目的要求,只需根据新式应用替换或删除有关层即可。
以前,微控制器的高级大型电路板支持套件需要专业工作组或电脑天才来做特殊处理,而他们又总是因为工作太忙而难以作出必要的调整,现在,我们可以支持逻辑解构,逐步满足各相关功能需求,确保满足整体需求。
记得上大学时,即便考试答题时没有得出正确的答案,但如果演算过程逻辑清晰、条理分明、系统而有组织,并加以适当注解,那么仍能在考试中获得一定的分数。这个道理与硬件独立性设计方案的道理是一样的。
我们不需要做到特别严格的有组织性,只需将封装器与接口在逻辑上进行集中,就能方便地替代实际硬件。举例来说,如果我们把所有与微控制器直接相关的封装器与接口集中在一个地方,而不是将其分散在不同的文件中,那么就能在最后关头轻松更换微控制器。
通过实例说明工作原理
我们不妨通过一个应用实例来说明上述道理。在这个应用中,我们根据温度来控制风扇转速,一步步完成相关设计工作,确保硬件独立性设计。在开始项目设计之前,我们已知:1) 我们需要获得温度读数。 2) 我们需要根据温度计算出所需的风扇转速。 3) 我们需要读取当前风扇转速。 4)我们需要根据当前风扇命令以及实际风扇转速与理想转速之间的误差计算出新的风扇命令。5)我们需要向风扇输出新的命令。
图1给出了该系统的逻辑方框图。矩形块表示依赖于硬件,而椭圆形则表示独立于硬件。根据该图所示的逻辑关系,控制工程师可以利用 MatLab 等模拟套件开始系统开发工作,而设计结果则能直接输入最终设计方案(尤其是用 C 语言等几乎所有微控制器都支持的高级语言编写的情况,更是如此)。
随着项目开发的进展,我们决定采用热敏电阻作为温度传感器(因为热敏电阻成本低且能满足特殊属性需要)。 我们从下图2可以看出,“获取温度”这个矩形块又扩展为依赖于硬件且与热敏电阻设计相关的不同功能块,其中包括热敏电阻的硬件特性及其接口电路等。
温度在热敏电阻中以电阻表示;在信号调节电路中,电阻则表示为电压,通过 ADC 转换,电压则转换为 0 至 4095 之间的数值;在软件中,该数值则转换为机器可存储和显示的温度值(比方说定点值温度,间隔为0.1℃)。
我们将温度放入数据存储系统中,让数据值更新同步于控制算法,这样温度就能与控制算法一样保持最新,从而确保将软硬件更好地隔离开来。
随后,我们在设计方案中发现,使用热敏电阻的话微控制器将不能满足温度热点的要求,一直在热敏电阻与微控制器引脚之间运行模拟线路的话,就会造成太多噪声并导致信号损耗。
因此,我们决定在温度区采用集成电路 LM75 I2C 作为温度传感器,将温度进行本地转化,并向I2C 总线提供数字值作为从设备。
现在,为了获得温度值,如下图 3所示,我们必须在微控制器中启用 I2C 主通信硬件,读取 LM75 中的一组寄存器,并将温度的原生表达法(最低有效位为 0.125℃)转化为此前选定的温度表达法(定点值温度,间隔为 0.1℃)。
由于我们实现了控制软件隔离,即便采用新的温度读取方法,控制应用软件也不会因为硬件改变而受到影响。
有关LM75的特性可以集中在上图3所示的蓝色矩形框中,我们可在不影响控制软件的前提下对其加以检查和验证。
举例来说,一些设备会在 I2C 主机每次读取温度值/寄存器时启动新的转换,如果读取速度过快或者过于频繁,那么LM75 就难以完成转换。控制算法则不用担心这些问题。
微控制器的抽取
我们在上面的实例中有意识地改变了微控制器外部的硬件,说明外部硬件转变不会影响控制软件。同样,即便微控制器内部硬件发生变化,也不会造成影响。
如果我们如图 2 所示先设计热敏电阻,随后再改动我们的微控制器,那么配置和读取 ADC 的命令就会变化,对输入进行多路复用和采样的寄存器序列也会变化,进而计数到温度的转换也会发生改变。