微控制器编程与面向对象编程

电器工程 Arduino 微控制器 嵌入式
2022-01-13 07:00:20

我用 C++ 完成了一些基本的面向对象编程(创建 B 树、散列算法、双链表),并且我用 C 完成了一些小项目(比如制作科学计算器等)

就程序员必须具备的思维方式和“思维”而言,硬件编程(特别是微控制器)与软件/面向对象编程有何不同?

我的大多数人通常认为一个人比另一个人更难吗?

以我的背景(如上所述)我是否需要为进入硬件编程做很多准备,或者我可以直接潜入没有太多准备?

4个回答

在处理大多数微控制器时,您将不得不完全放弃面向对象的范例。

微控制器通常受寄存器和 RAM 限制,时钟速率较慢且没有流水线/并行代码路径。例如,您可以忘记 PIC 上的 Java。

你必须进入汇编语言的思维模式,并按程序编写。

您必须保持代码相对平坦并避免递归,因为 RAM 限制通常会导致堆栈问题。

您必须学习如何编写高效的中断服务程序(通常用汇编语言)。

您可能必须使用汇编语言手动重构部分代码,以实现编译器不支持(或支持不佳)的功能。

您必须编写考虑到字大小和大多数微控制器缺乏 FPU 功能的数学代码(即在 8 位微控制器上进行 32 位乘法 = 邪恶)。

这是一个不同的世界。对我来说,在处理微控制器时,拥有计算机科学或专业编程背景可能会像完全没有知识一样成为障碍。

你需要考虑几件事:

  • 您将使用 C 作为语言
  • 您仍然可以使用函数指针创建面向对象的感觉,以便您可以覆盖函数等。我在过去和当前的项目中都使用过这种方法并且效果很好。所以 OO 部分存在,但不是 C++ 意义上的。

还有其他限制会发挥作用,例如有限的速度和内存。因此,作为一般准则,我避免:

  • 使用堆,如果有办法在没有 Malloc 的情况下解决问题,我会这样做。例如,我预先分配缓冲区并使用它们。
  • 我故意减少编译器设置中的堆栈大小以尽早解决堆栈大小问题,并仔细优化。
  • 我假设每一行代码都会被一个事件打断,所以我避免使用不可重入代码
  • 我假设甚至中断都是嵌套的,所以我相应地编写了该代码
  • 除非必要,否则我会避免使用操作系统。70% 的嵌入式项目并不真正需要操作系统。如果我必须使用操作系统,我只使用具有可用源代码的东西。(弗里托斯等)
  • 如果我使用的是操作系统,我几乎总是抽象一些东西,以便我可以在几个小时内更改操作系统。
  • 对于驱动程序等。我只会使用供应商提供的库,我从不直接摆弄这些位,除非我别无选择。这使代码可读并改进了调试。
  • 我查看循环和其他东西,尤其是在 ISR 中,以确保它们足够快。
  • 我总是随身携带一些 GPIO 来测量东西、上下文切换、ISR 运行时间等。

名单还在继续,我在软件编程方面可能低于平均水平,我相信有更好的做法。

我都做,所以这是我的看法。

我认为到目前为止,嵌入式最重要的技能是您的调试能力。所需的心态大不相同,因为可能会出错的地方更多,而且您必须非常开放地考虑您尝试做的事情可能出错的所有不同方式。

这是新嵌入式开发人员面临的最大问题。个人电脑的人往往会更艰难,因为他们已经习惯了为他们工作。他们往往会浪费大量时间来寻找为他们做事的工具(提示:没有很多)。有很多人一遍又一遍地撞墙,不知道还能做什么。如果您觉得自己被卡住了,请退后一步,弄清楚您是否可以确定所有可能出现的问题。系统地缩小你的潜在问题列表,直到你弄清楚。从这个过程中可以直接得出结论,你应该通过一次不要改变太多来限制问题的范围。

有经验的嵌入式人员倾向于认为调试是理所当然的......大多数不能很好地完成调试的人不会持续很长时间(或者在简单地接受“固件很难”作为为什么某个功能的答案的大公司工作晚了几年)

您正在处理在您的开发系统的外部系统上运行的代码,对不同平台的目标具有不同程度的可见性。如果在您的控制之下,请推动开发帮助以帮助提高对目标系统的可见性。使用调试串行端口、bit banging 调试输出、著名的闪烁灯等。当然至少要学习如何使用示波器并使用带有“示波器”的引脚 I/O 来查看某些功能何时进入/退出、ISR 触发等. 我已经看到人们比实际需要的时间更长,因为他们从不费心设置/学习如何使用正确的 JTAG 调试器链接。

更重要的是要非常清楚您拥有相对于 PC 的确切资源。仔细阅读数据表。考虑您尝试做的任何事情的资源“成本”。学习面向资源的调试技巧,例如用魔法值填充堆栈空间以跟踪堆栈使用情况。

虽然 PC 和嵌入式软件都需要一定程度的调试技能,但嵌入式软件更重要。

我假设您的 C++ 经验是基于 PC 的。

程序员从 PC 转移到微控制器时经常犯的一个错误是他们没有意识到资源是多么有限在 PC 上,当您创建包含 100 000 个条目的表或编写编译为 1MB 机器代码的程序时,没有人会阻止您。
有些控制器拥有丰富的内存资源,尤其是在高端,但它与您所习惯的仍然相去甚远。对于一个爱好项目,您可能总是可以追求最大,但在一个专业项目中,您通常会被迫使用较小的设备,因为它更便宜
在一个项目中,我使用的是 TI MSP430F1101. 1KB 程序存储器、128 字节配置闪存、128 字节 RAM。该程序不适合 1K,所以我不得不在配置 Flash 中编写一个 23 字节的函数。使用这些小型控制器,您可以按字节计算在另一种情况下,程序存储器太小了 4 个字节。Boss 不允许我使用具有更多内存的控制器,而是我必须优化已经优化的机器代码(它已经用汇编程序编写)以适应额外的 4 个字节。你明白了。

根据您正在使用的平台,您将不得不处理非常低级别的 I/O一些开发环境具有写入 LCD 的功能,但在其他开发环境中,您需要自己动手,并且必须从头到尾阅读 LCD 的数据表才能知道如何控制它。
您可能必须控制继电器,这比 LCD 更容易,但它需要您进入微控制器的寄存器级别。同样是数据表或用户手册。您必须再次在数据表中了解微控制器的结构,您可以在框图中找到该结构。在微处理器时代,我们讨论过编程模型,这基本上是处理器寄存器的阵容。今天的微控制器非常复杂,对所有寄存器的描述可以占据 100 页数据表中最好的部分。IIRC 只是对 MSP430 时钟模块的描述长达 25 页。

您经常需要处理实时事件处理。例如,您必须在 10\$\mu\$s 内处理一个中断,并且在此期间还有另一个需要相同时序精度的中断。

微控制器通常用 C 编程C++ 相当消耗资源,因此通常不可用。(大多数微控制器的 C++ 实现都提供了有限的 C++ 子集。)就像我说的,根据平台的不同,您可能拥有大量可用的函数库,这可以为您节省相当多的开发时间。值得花一些时间来研究它,如果你知道什么是可用的,它可能会在以后为你节省很多时间。