嵌入式系统的人机界面原型设计策略自然界面交互的探索与实践嵌入式开发培训班
在目标硬件尚未实现之前,通过PC机上的软件模拟人机界面是一个常见的做法。设计工程师需要利用PC上的工具和编程语言来构建这个模拟原型。这篇文章将探讨如何使用特定的工具和编码风格,以及不同语言之间文件接口的问题,这对于仿真设计人员来说具有指导意义。
构建一个人机界面的原型可以帮助设计团队成员更好地理解接口对设计的要求以及它的可用性。以下是一种方法,在目标硬件还没有实现的情况下,使用PC来创建一个人机界面原型:
利用PC上的人机界面原型模拟设备操作过程,使其他团队成员能够看到设备的工作流程。当我们在纸张上绘制交互式设备时,要想判断是否能实际实现所描述的交互性能,就需要很大的想象力。而如果有了一个工作原型,那么情况就会清晰很多,并且允许多个旁观者评论正在规划中的接口设计。此外,用接口原型进行测试,还能帮助决定最终硬件需要多少按钮、LED、数字显示器或文本显示器。
当硬件不工作时,利用接口原型为人机界面编写软件。在这种情况下,出现在PC屏幕上的接口原型必须采用C、C++或者适用于嵌入式开发的语言控制。在某些情况下,可以假设最终目标是C语言。
为了达到这个目的,我们首先要考虑哪部分软件需要仿真。在最简单的情况下,软件可能只用于打开或关闭一个LED,或向小字符LCD显示器输出字符串。控制人的操作物理元件通常只是非常基本的一项功能,因此能够在PC上编写这样的软件带来的优点是微不足道,因为开关LED可能只需一行代码,而调用10行至20行函数以显示字符串也相对简单。但真正困难的是如何决定究竟打开还是关闭LED,以及确定应该显示哪个字符串。例如,当被测传感器持续超过警戒线一段时间,并且符合设置条件后,可能会选择打开LED;当用户按下菜单中项目的“下一步”按钮时,又可能查找描述该菜单项及其操作表,以决定应该展示什么信息。
我们的目的是创建一个能够在PC屏幕变化并表示两个状态(警报状态)的人类-计算机交互系统。我们可以编写检查警告条件和管理菜单项选项所需代码,使其既能运行于PC,又能运行于目标设备上。这一种方式并不新颖,但对于那些没有自己的开发环境,如PDA或游戏主板等目标设备而言,这种方法尤为重要。
为了创建这些仿真,我们使用了Borland C++(简称CPB),尽管它不是专门为嵌入式系统开发设计,但我发现它非常适合我们的需求,而且使用CPB不会将我们的设计限制到任何特定处理器或结构中。CPB提供了一组预定义图形组件,其中大多数是桌面应用程序,而非嵌入式项目,但是仍有一小部分子集可以用于我们当前讨论的情景,比如UI元素,如LED,可以通过图片来模拟。而CPB有三种版本:标准版、专业版和企业版,对于我们即将讨论的人工界面而言,只需标准版即可满足需求。
每个按钮、滑块标签以及UI元素都可以通过拖放环境插入到表格(简单对话窗口)中生成C++类框架。当用户点击图片或者移动滑块时,都会产生一系列事件,每个元素都与一系列事件相关联。这一些响应由程序员选择执行。在前台板由工业设计团队制作时,有整个图像可供使用;或者如果物理模型已经存在,可以用数字照片作为背景。我采用图像对象(在CPB内部称之为Timage)来展示大多数物理元部件,因为这样就可以引入位图并进行展示。例如,我引入发光二极管的图像。在该应用中,我展示了包含五个按钮和四个发光二极管的一个虚拟模型,如图1所示背景图片中所有二极管处于熄灭状态。一旦软件决定其中的一个二极管应亮起,该亮起二极管图片就覆盖了熄灭状态下的二极管图片,从而点亮了二极管 图像。
由于这种简单重叠多幅图片技术,我们就可以模拟现实中的物理显示屏部分。如果我采纳CPB IDE来创造含有单词“ALARM”的注释,并给予其命名为AlarmIndicator,那么我就可以编写如下函数以控制它:
void setAlarmState(Boolean state) {
PanelForm->AlarmIndicator->Visible = state;
}
PanelForm包含所有用于演示期间所用的所有视觉对象——包括 AlarmIndicator。当我把这个标签拖动到表格窗体中的时候,它变成了表格的一个数据成员属性—Visible只能通过分配改变值公共数据成员使得属性值改变—任何地方都能访问修改属性值—除了特殊状态允许IDE内调整属性值—点击标记并调整Visible属性颜色字体也同样可修改
现在,让我们看一下setAlarmState()函数,它驱动基于CPB的人工仿真:
void setAlarmState(Boolean state) {
if (state) {
ledRegister = 0x02;
} else {
ledRegister = ~0x02;
}
}
这段代码仅供CPB专用,不会直接运行于最后期望平台。但不久之后,我们必须开始撰写另一种形式相同但针对平台特别化版本,即:
void setAlarmState(Boolean state) {
if (state) {
ledRegister &= ~(1 << LED_BIT); // clear the bit
} else {
ledRegister |= (1 << LED_BIT); // set the bit
}
}
有时候,一些小函数因为它们造成过度调用而导致问题,在较小系统里这方面尤其受到关注之一些支持优化宏或者内联(inline),通常只有当项目完成阶段才开始实施此类改进
代码组织:
如果已经撰写好了两个setAlarm-State()版本,那么要确保一次只执行其中一种必不可少。一种策略是在完成产品硬件发展后,将全部依赖与继续旧体系保持兼容性的行为替换掉所有依赖新体系命令后的旧命令。如果这样做,那么从那之后不能再次启动原始仿真调试环境 anymore读者们认为这是无妨,但事实上,即使已完成产品层级调试环境往往比目标硬盘调试速度慢,而且每次更新源代价高昂。此外,与之相关的是断点跟踪跟踪能力与步骤跟踪能力缺乏正如同无法找到正确路径一样。
因此,在制造过程结束后,还拥有大量价值同时让研发人员根据他们偏好的个人喜好配置不同的参数设置,以便快速测试不同的实验结果。
然而,如果您想要最大限度地减少成本,同时提高效率,则应当尽量避免过早地转向完全基于最新技术解决方案,而应该逐步迁移您的生产设施以确保平稳过渡。
总结:
综上所述,无论是寻求最佳解决方案还是希望最大限度减少成本及提升效率,最终成功关键就是保持灵活性并不断学习新的技能,同时积累经验,为未来挑战做准备。
虽然建立人类-计算机会话系统是一个复杂任务,但是借助现代技术辅助进行这一过程变得越发容易,也越加重要。
请记住,您不仅仅是在建立一个人工智能,你还正在塑造未来世界的一片天空。你拥有巨大的责任去创造创新解决方案,使人类生活更加美好,更富有人文关怀,同时尊重自然规律。你有什么计划吗?