嵌入式开发中设计界面的5个技巧

更新时间: 2022-11-24 15:30:51来源: 粤嵌教育浏览量:7072

  嵌入式软件开发人员的日常活动是为他们正在开发的软件组件设计界面。界面描述了可以与组件进行的交互、其行为以及其输入和输出。不幸的是,许多经过深思熟虑的界面使得开发人员更难有效地使用它们。本文将探讨所有嵌入式开发人员都应该遵循的设计软件界面的五个技巧。

  技巧1–使用通用界面语言

  在设计界面时,尽量遵循行业标准术语和技术,以使界面令人难忘。尽管现在大多数IDE都有一些代码补全的智能,但它并不总是有效的。当开发人员“处于流程中”时,被迫查看界面可能会中断开发。

  例如,如果你正在设计数字输入/输出接口,你可以考虑定义接口函数和方法名称,如:

  Dio_Init

  Dio_Write

  Dio_Read

  Dio_DeInit

  更符合面向对象范例的更好界面是:

  Dio_Create

  Dio_Write

  Dio_Read

  Dio_Destroy

  我们希望避免不明确的硬件接口的名称。

  技巧2–限制界面的大小

  人类的大脑只能在短期的“RAM”中存储7-12条信息。如果需要更多的信息,记忆就变得更加困难。将接口的大小限制在10-12通常足以满足组件的需要。

  如果接口扩展到超过10到12个功能,这表明组件试图做得太多了!此时,嵌入式开发人员应该仔细研究是否应该将组件拆分为多个具有更明确目的的组件。这样做可以提高组件的代码结构、可移植性和可重用性。开发人员更有可能更好地记住界面!

  

  技巧3——使用TDD来指定接口

  对于想要编写可测试代码并避免“以后调试”编码实践的开发人员来说,测试驱动开发是一个极好的工具。然而,TDD确实有进一步的用途,因为我们可以用它来创建测试,以验证接口如何如预期的那样运行。

  在界面设计过程的早期,开发人员通常会创建一个他们想要包含的函数或方法的列表。然后,他们会对这些函数的输入和输出进行初步猜测。一旦创建了初始列表,开发人员应该为他们的组件创建一个测试列表,用于证明他们的组件工作正常。

  有了初始测试列表,嵌入式开发人员可以开始构建需要构建接口的单元测试。当他们完成每个测试时,他们会发现他们最初的界面设计会进化以满足系统的需求。当测试完成时,将会发生两件事。首先,一系列测试将描述如何与组件和界面交互。第二,组件将准备好生产。

  技巧4——使界面可扩展

  当使用C与硬件交互时,例如与数字输入/输出外设交互,我们可以构建一个接口,允许我们通过扩展向驱动程序添加功能。例如,在界面中包含以下两个函数:

  Dio_RegisterRead

  Dio_RegisterWrite

  这两个功能将提供对硬件外设寄存器的低级访问。开发人员可以根据手头的应用程序构建任意数量的自定义模块和接口,扩展驱动程序提供的简单数字输入/输出接口。在这种情况下,仔细的规划使我们可以轻松地扩展接口,而无需修改我们的底层驱动程序。

  

  技巧5——必要时抽象接口

  近80%的嵌入式软件开发人员使用C语言开发他们的嵌入式系统。乍一看,如果不先创建复制和粘贴的接口模板,嵌入式开发人员很难重用他们的接口。使用C似乎不像我们在C++中那样提供抽象。在C++中,我们可以用虚方法创建一个类来定义我们的抽象接口。当我们需要更改底层代码时,我们希望抽象接口。例如,如果我想让我的数字输入/输出驱动器为两个不同的微控制器工作。

  在C语言中,我们可以用一点小技巧在我们的接口中获得类似的行为。诀窍是不要将我们的接口定义为头中的原型函数列表,而是将我们的接口定义为如下结构中的函数指针列表:

  typedef struct

  {

  bool (*Init)( const DioConfig_t * const Config);

  bool (*Read)(const DioObj_t * const, DioData_t * const DioData);

  bool (*Write)(const DioObj_t * const, DioData_t * const DioData);

  } Dio_t;

  当我们定义结构变量时,我们可以按如下方式分配将被调用的函数:

  const Dio_t Dio =

  {

  Dio_Init,

  Dio_Read,

  Dio_Write

  };

  通过更改结构初始化,我可以轻松地更改我正在访问的底层驱动程序。例如,在嵌入式开发中,对于STM32微控制器,我可以使用以下内容:

  const Dio_t Dio =

  {

  STM32_Dio_Init,

  STM32_Dio_Read,

  STM32_Dio_Write

  };

  对于MSP430,我可能会使用以下内容:

  const Dio_t Dio =

  {

  MSP430_Dio_Init,

  MSP430_Dio_Read,

  MSP430_Dio_Write

  };

  此时,应用程序代码并不关心底层的Dio函数调用是什么!如果我想初始化Dio,我只需调用:

  Dio.Init(Config);

  很酷的是,它看起来很像我在调用类中的方法,但我使用的是C。我还有一个很好的抽象,可以将应用程序代码与底层硬件调用解耦。这是双赢!

  结论

  开发人员在实现新模块时总是会创建新的接口。诀窍是这样做,使界面自然、令人难忘且易于扩展。经常会有人试图创建界面并继续前进;然而,接口可能是组件的基本元素。一旦界面设置好,进行更改可能会导致巨大的麻烦和更改的努力。

  这篇文章探讨了一些基本技巧,以帮助你设计嵌入式软件界面。遵循这些最低限度的最佳实践将帮助你设计难忘且可扩展的界面,并防止嵌入式开发人员在开发过程中被绊倒。

免费预约试听课