C ++与Arduino语言?


81

使用Arduino时每种语言有什么优势?

我认为这是一个很好的一般性问题,但我会补充一点为什么我要问是否有人想给我小费。

我对JavaScript,PHP等预处理语言有丰富的经验,并且喜欢Java和Visual Basic等语言。换句话说,我知道编程技术以及经典和原型对象定向,但是对直接与硬件通信一无所知。

我正在制作一个八轴飞行器,并认为面向对象的方法将是最简单的。(该软件将具有很多功能...)但是,我从未用C ++编写过。

由于这是一个Q&A网站,应该可以帮助其他人,因此,仅在开始时提出的一般性问题就很重要,但是我很乐意就我的情况发表任何意见。


16
避免使用Arduino IDE,因为它不应该使用其IDE名称,它甚至是一个非常糟糕的编辑器:它对于初学者和简单的草图可能很好,但是应该迅速寻求更好的东西。
jfpoilpret 2014年

4
这是 “ Arduino编程语言”的含义(实际上是其含义)的相当简洁的细分
AdjunctProfessorFalcon

10
C++ vs. The Arduino Language?-“ Arduino语言” C ++。有一些预处理可以节省您编写函数原型的时间,但绝对可以是C ++。
尼克·加蒙

2
没有arduino语言。它只是一个图书馆。
Overdrivr

2
与评论问题无关:Atmel Studio是免费的,恕我直言,它比arduino编程的Visual Studio更好。还支持Visual Micro插件,尽管对于编程和调试arduinos根本不需要。
cyberponk

Answers:


55

我作为教授(编程,机电一体化)的个人经验是,如果您以前有编程经验,并且了解OOP等概念,那么最好使用C / C ++。arduino语言对于初学者来说确实很棒,但是有一些限制(例如,您必须将所有文件都放在同一文件夹中)。它基本上是C / C ++的简化(您几乎可以将arduino代码复制并粘贴到C / C ++文件中,并且可以使用)。同样有意义的是,您可以使用一个广为人知的IDE作为eclipse:

http://playground.arduino.cc/Code/Eclipse

最初,您需要对开发环境进行更多的设置和配置,但是恕我直言,这对于拥有其他任何语言经验的程序员来说都是值得的。

无论如何,几天之内开始使用arduino语言和arduino IDE来熟悉arduino硬件,然后使用Eclipse迁移到C / C ++来真正开发项目,这对您没有害处。


谢谢你的想法。我将使用Arduino IDE学习如何控制所有不同的硬件,例如传感器和LCD屏幕等。然后,我将使用C ++来制作用于八轴飞行器的软件。您是否了解其他语言的人读的好书和简短书?我发现的许多书籍中的“问题”是,它们包含了很多我不需要的东西,因为我使用的是小型Atmel微控制器而不是UI计算机。
,金(Kim)的朋友

1
朱利安·贝勒(Julien Bayle)写的一本不错的书“ Arduino C编程”非常有用。它不是C语言,而是C语言,但应帮助您理解基础。
fenix688 2014年

那是一个很好的要求:一本简短而又不错的书,其中包含C ++基础知识,适合其他语言的程序员。抱歉,我无法提供任何建议,我不知道有任何好的建议。实际上,我写了一本书,专门针对我的学生(开发电子游戏),但这只是西班牙语。对于一本好实用的C ++书,我会推荐Deitel&Deitel How to C ++,您可以跳过许多高级章节。
drodri 2014年

1
C ++支持OO功能,而C语言不支持。
克里斯·奥

1
@FriendofKim不完全是我的意思(尽管从技术上讲您可以,因为Due足够快以支持用于非兆位串行通信的软件解决方案,它总共有5个U(S)ARTS,而Arduino库仅提供了4个它们,但是iirc Due板始终不为其中一个USART提供引脚。Arduino库将USART配置为使用异步模式,但是我需要以高达6Mbps的速度进行同步(并且我不得不使用SPI模式,因为输入必须被视为原始比特流,因此不能使用停止位等),这也涉及到修改默认的PIO控制器配置。
JAB

48

从理论上讲...
实际上并没有Arduino语言。它实际上只是带有某些特定于域的库的C ++。这些增加了各种功能,例如可以调用以控制硬件的功能。如果没有这些功能,则需要直接使用特殊寄存器来控制所有内容。嵌入式程序通常就是这样完成的。它的速度很快,但是很难学习和理解。

除了这些功能之外,这些库还为某些类型添加了替代名称。例如,boolean并且byte不在C ++标准中。但是,它们直接等效于boolunsigned char

所有这些都意味着您可以轻松地将通用C ++代码直接移植到Arduino。但是,以其他方式返回可能需要进行一些较小的编辑。

在实践中……
综上所述,Arduino的编程与常规C ++编程并不完全相同。但是,所有嵌入式编程都有很多差异(例如,有限的内存和处理能力)。

还值得注意的是,如果您使用的是官方的Arduino IDE,那么在设置代码方面会遇到各种烦人的怪癖和局限性。在所有情况下都存在变通办法(据我所知),但是有时它们很令人沮丧。

为了获得充分的灵活性,请使用带有插件的第三方IDE(例如Eclipse)来支持Arduino。那应该为您提供C ++的所有优势,以及Arduino库。


25

使用Arduino时,C ++与Arduino语言相比有什么优势?我对JavaScript,PHP等预处理语言有丰富的经验,并且喜欢Java和Visual Basic等语言。

首先,Arduino编译器/ IDE按原样接受C和C ++。实际上,许多库都是用C ++编写的。许多底层系统不是面向对象的,但可能是面向对象的。

因此,“ arduino语言”是C ++或C。

C ++不会被垃圾收集。它确实管理范围内的变量-如果您编写:

int led = 13;

void blinkTimes(int value)
{
   int i;

   for(i=0;i<value;i++)
   {
      digitalWrite(led, HIGH);
      delay(1000);
      digitalWrite(led, LOW);
      delay(1000);
   }
}

然后,无论呼叫多少次,您都将发现led并且i不会增长或泄漏blinkTimes

如果i是一个类,则函数结束后将同样进行处理。因此,只要您不使用new或使用类似的内存分配功能来创建新对象,那么您就不必担心泄漏。

如果创建大型类并在深度嵌套的函数中使用大量类,则可能仍会耗尽内存,但是通常,在开始处理newand free函数之前,您不会遇到麻烦。

如果您使用new,则必须delete在适当的时间致电。C ++以及通过扩展的Arduino没有自动垃圾收集功能,您必须显式管理自己的内存。


1
好吧,如果没有垃圾回收实例化对象(带有新对象),那么我也必须学习。我想任何有关C ++的书都将介绍。谢谢您的答复!
金的朋友

14

Arduino语言 C ++,但与大多数C ++品种有很大不同。Arduino语言内置了很多抽象,尤其是在硬件接口中,这使其使用非常简单。如果您具有Java的背景知识,那么C和C ++应该非常相似。

Arduino和C ++之间的主要区别在于内存存储。通常,现代计算机具有超过2GB的RAM,而Arduino Uno具有2kB(少100万倍)。Arduino还使用8位指令,而不是计算机使用的32位指令。这将主要影响您可以存储在变量中的信息量。

如果您对Arduino世界不熟悉,则应该查阅教程,因为那里有很多不错的教程。


你提到记忆。我有Due,它具有96KB的RAM。但是我最后要说的是由于内存泄漏(在直升机上安装了非常昂贵的相机)而使直升机坠毁。
,金(Kim)的朋友

如果没有另外指定,是否可以自动处理C ++中的内存(例如Java中的垃圾收集器)?
2014年

2
C ++标准不能保证内存大小-c ++已经在嵌入式硬件上运行,无需修改。
2014年

2
您在描述的是硬件平台之间的差异,而不是C ++。
Cyber​​gibbons 2014年

5
@FriendofKim在C ++中,有两种不同的实例化变量/对象的方法。如果您在本地实例化它们(例如int blah = 5;),那么当它们超出范围时(即在循环或函数结束时),它们将被自动销毁。但是,如果在堆上实例化它们(例如int *blah = new int(5);),则需要自己释放它们。但是,在嵌入式编程中使用堆数据通常并不明智。
彼得·布卢姆菲尔德

14

---更新170412
我三年前从存在独特的“ Arduino C ++”的角度编写了原始答案。IDE中使用的语言标准的C ++,因为它是由GNU C ++编译器实现的。出现“表观”差异的原因是,IDE将进行一些预处理,以通过填充一些#includes f / ex来帮助该语言的新手避免几个“陷阱”。但是您可以-并且我愿意-为它编写正确的C ++,并得到您所期望得到的。
---结束更新

一定要将C ++语言功能的使用限制在您完全理解其实现的功能上。有一些功能可以编译成更多的资源密集型代码,这比阅读源代码显而易见。可选生成的.lss(合并的源代码和程序集)列表可以让您深入了解C ++编译器在不使用时的工作方式。

关于内存的问题:C ++不会进行垃圾回收。基于堆栈的语言(例如C和C ++)确实在堆栈上为函数入口处的自动变量分配了临时存储,然后在函数返回时释放了这些临时变量,但这不是真正的垃圾回收。在堆或全局内存中创建的对象一直存在,直到您明确删除它们为止。确保知道在何处,何时以及将创建多长时间的各种对象。您真的不希望您的代码new-ing和delete-ing对象随意地出现。它们将内置在堆内存中,使其碎片化并导致其长大到堆栈中。那时,您的代码和您的“直升机”将崩溃。

C为您做的更少因此对您做的更少。这不是一个坏选择。如果您明智地选择了额外的功能,那么具有少数C ++功能的C可能是一个更好的选择。C++是您的两个选择:

[原始答案]-C ++是一种标准化的语言。它已广泛部署在包括嵌入式系统在内的许多环境中,因此,与非常相似的C ++语言“ Arduino”相比,它已经得到了更全面的测试。这对于您正在计划的关键任务/安全关键应用程序尤其重要。代码损坏意味着“直升机崩溃”,即使它没有伤害到某人,也损坏您的昂贵机器。

  • 作为标准,C ++是可移植的。需要升级处理器吗?除了特定于芯片的代码之外的所有代码都将移植到新代码中。是否需要更改工具集,开发系统,主机OS?到处都将支持C ++。尽管Arduino IDE可以在支持Java的任何地方运行,但这是唯一使用Arduino C ++的工具,并且它是一个非常有限的工具。如果您想使用Eclipse,AVR工具,在命令行上赤脚,在Emacs中开发或在您喜欢的任何其他环境中开发,则将支持标准C ++。

  • Arduino IDE在背后做了很多事情-具体来说,当它认为您需要它们时,它会#include .h文件。即使是正确的,您也确实要编写或至少看到并理解编译器将要看到的所有内容。编程语言不是为计算机设计的(计算机在吃早餐时吃点东西);它们是为人而设计的,特别是跟随您进行项目工作的人,其中最重要的人可能是...您!在编写模块后的6个月内,您必须回来进行增强,或者更多可能,修复它。您确实希望能够看到编译器看到的所有内容。


2
这是一个很好的答案。显然您喜欢C ++,我也应该喜欢它!...但是,认真的说,一旦我了解了与不同传感器等的“通信”是如何工作的,我将立即跳入C ++。
金的朋友

你知道关于这方面的好书吗?(适用于已经使用其他语言进行编程多年的人,只需要C ++的“嵌入式部分”。)
Kim

您是否认为Accelerated C ++是一本好书?
金的朋友

2
我希望我能为您提供“正确”的书,但我来到C ++的背后是很多C语言,而Kernighan&Ritchie的《The C Programming Language》仍然是我的首选书籍(坏双关语),因为它没有明确的C ++语言,以及Ellis&Stroustrup的C ++注解C ++参考手册。但是对于写入硬件,您可以很好地查看Arduino.cc用户提供的一些设备库。首先使用pinMode(),digitalWrite()和digitalRead()函数对I / O端口进行调整,然后对它们的模拟I / O进行调整,最终,...
JRobert

1
...计划直接写入I / O寄存器以提高速度和内存空间。诸如blinky.cpp和hello.cpp之类的程序是开始搞乱硬件的好地方。添加一个简单的万用表,然后将几个带有正确限流电阻的LED永久焊接到一条腿上,您应该能够看到您所做的努力的真实结果。之后,请阅读您感兴趣的任何硬件的数据表,以了解您可以读取/必须写入的信号以使其发挥作用。温度传感器易于使用,不是每个人都需要冰箱记录仪吗?玩得开心!
JRobert

10

以我的经验,在内存有限的计算机上运行时,最好避免新建删除

  • 内存管理本身会使用宝贵的程序和RAM空间
  • ISR向量在编译时设置。类实例很难(不可能?)在运行时声明ISR
  • 通常,您会在编译时知道所需的类实例-例如3个按钮去抖器,显示驱动器和2行显示驱动器
  • 使用new或delete时,内存管理会引入未知的延迟。

在某些情况下,使用动态实例构造和销毁是合理的,但我怀疑它们很少。


作为C ++的新手,我有一个有关STD的后续问题。使用它是一个坏主意吗?如果没有,如何添加(Eclipse)?我已经设置好了AVR编译器,并且运行良好。
,金(Kim)的朋友

1
您所说的一切都是正确的,但我不认为这是对OP问题的答案。new并且delete在Arduino IDE中也可用。
jfpoilpret 2014年

这不是答案,而是非常有用的信息,我非常感谢。
金的朋友

8

正如在几个答案中提到的那样,如果您通常在对嵌入式系统进行编程,则应该避免使用new除非您正在管理自己的内存堆并且您真的知道对象生命周期将是什么。静态分配或堆栈变量要安全得多。就是说,管理诸如在函数持续时间内分配的可变长度缓冲区之类的东西的一个常见技巧是拥有一个自动变量(在堆栈上),该对象是一个在其构造函数中调用new的对象,然后将delete放入析构函数中因此,当对象超出范围时,缓冲区将释放回堆。同样,这通常在微小的微米中使用有限,但这是一个很好的模式。


6

除了上面的评论,我还要进一步强调一下您在Arduino板上拥有的工作RAM的问题,尤其是Uno(以及其他共享同一微控制器的)。我最近写了一个简单的Space Invaders游戏,该游戏在32x32 LED矩阵上运行,反复遇到内存不足引起的问题。

Uno只有2048个字节的RAM。我的矩阵库占用了3/4的库,剩下大约400个字节用于游戏。因为我打算在某个时候“升级”项目,以便在功能更强大的Due上使用同一程序运行多个游戏,所以我设计了具有OO主体和大量类继承的代码。(游戏类通过虚拟更新和绘画调用继承,游戏实体都被继承)。

我只是增加了入侵者而用光了内存。我试图通过对它们的成员变量进行位域保存来节省内存,但是在添加屏蔽对象时又用光了。经过更多的刮擦后,我用光了炸弹/子弹。此时,我搜寻了代码并删除了所有“虚拟”标签(我所有的类原型都是从Visual Assist代码段构建的,而析构函数都是自动虚拟的)。这使我的内存使用量立即减少了一半,从而释放了足够的空间来完成代码。

长话短说,最终结果是C ++代码实际上并未使用任何C ++功能。您可能只是坚持使用C并非常了解您的内存使用情况。如果超过2KB,您将无济于事-尤其是当您使用任何动态分配时,该代码将停止工作,并且会费时费力,直到您考虑内存溢出的可能性。

PS-位域变量是错误的。很坏。除了增加处理开销外,我还没有跟踪向游戏添加新状态的次数,但是代码无法运行,我也不明白为什么。我的状态变量不够宽,无法容纳新的状态值,所以我遇到了一些意外状态。


4

Arduino语言 C ++(尽管通常以“带有类的C”的形式实现,这实际上在嵌入式系统微控制器领域相当普遍)。故事结局。人们以为这已经是另一种语言了,已经足够了!它使用g ++编译器。

证明:

在“偏好设置”中启用编译过程中的详细输出,然后上传,阅读这些行就会学到很多东西。

以下是一些其他见解:

我自己的话:

Arduino代码 C ++。Arduino 核心功能只是您可以使用的一组C ++类和库。它是使用GNU gcc / g ++编译器构建和编译的。您可以将setup()和loop()函数简单地放入必需的main()函数(实际上这里-请注意,该文件是“ main.cpp”,这是C ++源文件),并且有一些额外的功能进行预处理以确保它是有效的C ++程序(例如:为您扫描所有函数原型[aka:声明],以便即使函数原型稍后出现在.ino文件中,也可以使用该函数)。但是,许多Arduino都是以“ C风格”编写的,因此需要使用# extern "C" {}大括号将C ++阻止“名称更改”(也称为“名称修饰/名称修饰”)函数调用由AVR-libc实现的C函数,AVR-libc是ATmega328和其他AVR架构微控制器的C实现。

Arduino的话:

我可以用C语言对Arduino板进行编程吗?
实际上,您已经可以了; Arduino语言只是可以从您的代码中调用的一组C / C ++函数。您的草图进行了微小的更改(例如,自动生成函数原型)然后直接传递给C / C ++编译器(avr-g ++)。avr-g ++ 支持的所有标准C和C ++结构都应在Arduino上运行。有关更多详细信息,请参见Arduino构建过程中的页面。”

资料来源:https : //www.arduino.cc/en/Main/FAQ#toc13

何时使用Arduino库和纯C或C ++?

因此,使用Arduino语言简化事情,并在需要更多专业化的地方编写自己的函数。我确实建议您尽管编写代码还是要快速脱离IDE,只不过将其用于编译即可。设置IDE首选项以使用“外部编辑器”。然后,使用专业的源代码编辑器/ IDE(例如Sublime Text 3AtomVisual Studio CodeEclipse CDT)编写代码。然后,您可以单击返回Arduino IDE进行编译和上传。如果您使用Eclipse,则可以使用Eclipse中的方法(请参见此处的其他答案,也请参见Arduino的Eclipse Eclipse文章),因此也请考虑使用这些技术。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.