我已经用C ++完成了一些基本的面向对象的编程(创建B树,哈希算法,双链表),并且已经在C中完成了小项目(例如制作科学计算器等)。
就程序员必须具有的思维方式和“思维”而言,硬件编程(特别是针对微控制器)与面向软件/对象的编程有何不同?
我大多数人通常认为一个人比另一个人难吗?
以我的背景(如上所述),我是否需要为硬件编程做很多准备工作,还是可以在没有太多准备工作的情况下直接涉足?
我已经用C ++完成了一些基本的面向对象的编程(创建B树,哈希算法,双链表),并且已经在C中完成了小项目(例如制作科学计算器等)。
就程序员必须具有的思维方式和“思维”而言,硬件编程(特别是针对微控制器)与面向软件/对象的编程有何不同?
我大多数人通常认为一个人比另一个人难吗?
以我的背景(如上所述),我是否需要为硬件编程做很多准备工作,还是可以在没有太多准备工作的情况下直接涉足?
Answers:
与大多数微控制器打交道时,您将必须完全放弃面向对象的范例。
微控制器通常受寄存器和RAM的限制,时钟速率慢且没有流水线/并行代码路径。例如,您可以忘记PIC上的Java。
您必须进入汇编语言的思维方式,然后进行程序编写。
您必须使代码保持相对平坦并避免递归,因为RAM限制通常会导致堆栈问题。
您必须学习如何编写高效的中断服务例程(通常使用汇编语言)。
您可能必须以汇编语言手动重构部分代码,以实现编译器不支持(或支持不佳)的功能。
您必须编写数学代码,其中要考虑到大多数微控制器的字长和缺乏FPU功能(即在8位微指令上进行32位乘法=邪恶)。
这是一个不同的世界。对我而言,拥有计算机科学或专业编程背景可能像对待微控制器时完全不了解一样是一个障碍。
您需要考虑以下几件事:
还有其他限制,例如速度和内存有限。因此,作为一般准则,我避免:
清单还在继续,在软件编程方面,我可能低于平均水平,我相信有更好的做法。
我都做,所以这是我的看法。
我认为到目前为止,嵌入式中最重要的技能是调试能力。所需的思维方式有很大不同,因为有更多的地方可能出错,并且您必须非常开放地考虑尝试采取的所有不同方式都可能出错。
对于新的嵌入式开发人员来说,这是最大的问题。PC人往往会觉得比较粗糙,因为他们已经习惯了为他们工作。他们往往会浪费大量时间寻找工具来代替他们做事(提示:没有太多)。一遍又一遍地撞墙撞墙,不知道该怎么办。如果您觉得自己陷入困境,请退后一步,确定是否可以找出所有可能出问题的地方。系统地缩小您的潜在问题列表,直到找到答案。从此过程中可以直接得出结论,您应该通过一次不进行太多更改来限制问题的范围。
经验丰富的嵌入式人员倾向于将调试视为理所当然的事情……大多数不能很好地完成调试的人不会持续很长时间(或在大型公司中工作,而这些公司只是接受“固件很困难”作为某种功能为何的答案。已经晚了)
您正在开发在开发系统的外部系统上运行的代码,各个平台对目标的可见程度不同。如果在您的控制之下,请寻求开发辅助工具以帮助提高对目标系统的可见性。使用调试串行端口,调试中的比特输出,著名的闪烁灯等。当然,至少要了解如何使用示波器,并将引脚I / O与“范围”一起使用,以查看某些功能何时进入/退出,ISR触发等。我已经看到人们为之奋斗的时间比实际需要的时间更长,这仅仅是因为他们从不费心去设置/学习如何使用适当的JTAG调试器链接。
重要的是要非常清楚您相对于PC拥有的资源。仔细阅读数据表。考虑您正在尝试做的任何事情的资源“成本”。学习面向资源的调试技巧,例如使用魔术值填充堆栈空间以跟踪堆栈使用情况。
虽然PC和嵌入式软件都需要一定程度的调试技能,但对于嵌入式而言,这更为重要。
我假设您的C ++经验是基于PC的。
程序员从PC转移到微控制器的一个经常犯的错误是,他们没有意识到有限的资源是多么有限。在PC上,当您创建具有100 000项的表或编写可编译为1MB机器代码的程序时,没人会阻止您。
这里是它拥有丰富的内存资源,尤其是在高端微控制器,但它仍然是相去甚远什么,你会来。对于业余项目,您可能总是可以发挥最大作用,但是在专业项目中,由于价格更便宜,您经常会被迫使用较小的设备。
在一个项目中,我正在使用TI MSP430F1101
。1KB的程序存储器,128字节的配置Flash,128字节的RAM。该程序不适合1K,因此我必须在配置Flash中编写一个23字节的函数。使用这些小型控制器,您可以按字节计算。在另一情况下,程序存储器太小了4个字节。老板不会让我使用带有更多内存的控制器,而是我不得不优化一个已经优化的机器代码(它已经用汇编器编写了)以适合额外的4个字节。您得到了图片。
根据你在你的工作平台上就必须处理非常低的水平的I / O。一些开发环境具有可写入LCD的功能,但在其他开发环境上则需要您自己完成,并且必须从头到尾阅读LCD的数据表以了解如何进行控制。
您可能需要控制一个继电器,这比LCD还要容易,但是这将需要您进入微控制器的寄存器级别。再次提供数据表或用户手册。您必须再次在数据表中了解微控制器的结构,您可以在框图中找到它。在微处理器时代,我们谈论一种编程模型,基本上是处理器寄存器的组合。当今的微控制器是如此复杂,以至于对所有寄存器的描述都占据了100页数据表的最佳部分。IIRC仅对MSP430的时钟模块进行了25页的描述。
微控制器通常用C编程。C ++占用大量资源,因此通常不用担心。(大多数用于微控制器的C ++实现提供有限的C ++子集。)就像我说的那样,根据平台的不同,您可能拥有广泛的可用功能库,可以节省大量开发时间。值得花一些时间研究它,如果您知道有什么用,它可能为您节省很多时间。
“硬件编程”可能意味着很多事情。编写非常小的芯片(例如10F200、512条指令,几个字节的RAM)几乎就像设计电子电路一样。另一方面,使用大型GUI工具包对大型Cortex微控制器(1 Mb FLASH,64 kB RAM)进行编程可能非常类似于PC / GUI编程。恕我直言,一个好的嵌入式/实时程序员需要软件(例如工程学方面)和电路设计方面的技能。对于较大的uC,C ++是不错的语言选择,对于很小的语言,C可能是唯一的选择。Assemby知识可能很方便,但是我不建议您完全在组装中进行严肃的项目。
我已经与(SWI和EE)双方的人员进行了认真的嵌入式工作。我通常更喜欢SWI人员,只要他们具有多线程编程方面的经验。
您的问题听起来像您想深入了解嵌入式编程。一定要这样做。对于低级方面(连接芯片的外设及其周围的硬件),您将需要学习一些新技能,但这是很多工作而没有很多新概念。对于项目的较高层,您可以利用现有的知识。
对于您调用的每个arduino库方法,都有大量的C / C ++代码使之成为可能,它被很好地打包以供您用作API。查看一下hardware / arduino / *目录下的arduino源代码,您将看到为您编写的所有C / C ++,它们直接与AVR微控制器的寄存器交互。如果您的目标是学习如何编写这样的内容(直接针对硬件),那么这里有很多内容要讲。如果您的目标是使用它们的库进行某些工作,那么可能没有什么要讨论的,因为大多数艰苦的工作都为您完成,并且它们的库和开发环境非常易于使用。
但是,在使用资源受限的设备时,一些经验法则可能适用于arduino环境或其他环境:
请注意您正在使用多少内存。代码大小(用于闪存)和静态RAM使用率(代码中的常数将始终存在于RAM中)。我认为静态RAM的使用从一开始就更为重要,因为它很容易忽略。对于堆栈,堆和常量,只有1000个字节可以使用的情况并不少见。明智地使用它,所以当字节或无符号char的整数(每个1字节)就足够时,请避免使用长整数数组(每个4字节)之类的东西。这里的另一个答案很好地涵盖了其他一些重要方面,所以我就在这里停止,我主要是想指出一点,如果您不使用arduino库并编写自己的 C库,那么还有很多要讲的内容。
关于微控制器与OOP编程,它们并非相反。确实所有供应商库都使用纯C语言,但是所有平台也都支持C ++ OOP。开发人员可以在此基础上构建并确实构建C ++高级库和设备固件。很好的例子是Arduino库,它们是官方的和用户构建的-大多是C ++类。也许并不是所有的OOP优势都可以在嵌入式环境中得到充分利用,但是众所周知的C ++ vs C优势在这里也是有效的。
关于思维方式和思维,如其他答案所述,微控制器是非常受资源限制的平台(特别是在RAM中,速度较慢)-诸如动态内存分配之类的东西,通常都排除了C ++异常。只要选择了正确的硬件,就很容易采用这些限制并使用其他技术(在其他平台中也广泛使用)。
在我看来,更艰巨的挑战可能是嵌入式编程中的另一个额外维度-时序。这是因为通常嵌入式软件会处理大量实时事件,严格定时的协议以驱动外围硬件和一般任务本身(这些在其他“高级”平台中也有一些相似之处,例如多线程应用程序)。
在处理新硬件时,请准备好阅读大量数据表-我想这可能与“心态”问题部分有关:)当然,需要一些EE和硬件知识。
我还要指出的是,如今嵌入式软件开发不需要汇编语言。实际上,Java(默认情况下为OOP)已经存在并且正在变得强大(至少对于某些类型的嵌入式设备(例如IoT设备),它的前途可能非常光明)。