成为订阅者(免费)

加入29,000名其他订阅者以获得用户销售折扣和 其他免费资源。
:
:
大学教师'担心 - 您的邮件地址完全是 安全的。我保证使用它 只要 to send you MicroZine.

arduino. 字符串

您使用Arduino String类来管理存储的文本行 SRAM,您可以以不同的方式控制字符串:

  • 初始化它们 - 轻松设置文本消息。
  • 连接它们(添加字符或附加另一个字符串)。
  • 搜索(识别字符串中的内容)。
  • and more.

他们为来自外界的人类界面提供。所以 例如,您将使用字符串存储,并稍后发送消息 LCD或通过串行链路等接收和发送数据。

笔记: 在这个页面中这个词'String'(在本页中)具有首都第一字母 到字符串类(C ++)而非大写'string' refers to C 风格字符串。您可以在Arduino Compiler中使用(AVR compiler).

按示例学习Arduino字符串

要了解如何使用Arduino字符串,请通过串行端口解决简单的问题,接收和传输数据。

编译C / C ++代码的一个问题是要更改常量 程序需要重新编译,这需要时间。使用序列 端口允许您实时更新内部变量 重新编译代码。

以下代码接受 来自串口的数据以文本命令的形式控制 简单的开/关变量。下面的另一部分向您展示了如何获得 在Arduino程序运行时,整数文本值为整数变量。

It's的一个有趣的问题,因为来自RS232接口的数据是"serial"所以你必须建立一个来自的命令 串口字节按字节。您还需要识别命令完成后,然后在命令上执行操作。

正如您为所有串行通信所做的那样,首先要做的是 以波特率初始化setup()函数中的串行类 (启动消息也很有用来显示代码已开始):

void setup (void) {
   Serial.begin(9600);
Serial.println("Command Interpreter");
 }

本教程 操作代码将在循环功能中,但随着您的程序 生长,您将想要创建一个单独的函数来包含该功能 串行解码操作。因为现在让它在循环中留下它。

首先你需要 声明您将用于保存数据的类型字符串的变量 来自串口;这将是sdata。所以sdata是一个字符串类 字符串类型的对象。

细绳 sdata="";

由于每个字节的数据都进来,您还需要一个临时存储区域来处理它:

byte ch = ' ';
确定是否已收到字节所需的功能是
Serial.available()

如果在串行端口处收到任何内容,则返回true。

接下来,您需要使用String类成员函数读取()从串行端口读取变量中的数据:

Serial.read();

这返回一个字节的数据。

arduino. 字符串串行命令解码结构

使用这四位代码,您可以按如下方式构造串行接收器:

细绳 sdata="";  // Initialised to nothing.

void setup (void) {
   Serial.begin(9600);
Serial.println("Command Interpreter");
 }
void loop(void ) { byte ch; if (Serial.available()) { ch = Serial.read(); sdata += (char)ch; if (ch=='\r') { // Command recevied and ready. sdata.trim(); // Process command in sdata.

sdata = ""; // Clear the string ready for the next command.
 
} } }

setup()中的代码将串行端口初始化为9600波特并打印出第一个字符串消息。

在Loop()中,串行端口被持续监控,如果字节是 收到它被置于变量CH中并附在字符串SDATA上。如果 那个字节是回车(CR - 当您击中返回键时) 修剪函数用于在末尾删除所有空格 sdata。 SDATA现在准备被解码。

请注意如何连接字符串,即添加到结尾 另一个通过使用超载的'+'操作员,这里使用缩短的 form '+='.

就在离开IF条件之前,SDATA设置为NEEL NELLEATE,用于下一个命令解码。

arduino. 字符串串行命令控件

现在让我们看看评论后写下的部分:

// Process command in sdata.
这是您可以解码以\ R结尾的串行数据(现在通过TRIM()删除)。

最简单的方法是检查第一个字符并使用它 在交换机语句中。在特定位置SE访问字符 字符串的Charat成员函数。

sdata.charAt(0)

这里's切换语句,用于解码每个命令

         // Process command in sdata.
         switch( sdata.charAt(0) ) {
         case 's':
            start = 1;
            Serial.println("Start Process");
            break;
         case 't':
            test = 1;
            Serial.println("Test");
            break;
         default: Serial.println(sdata);
         } // switch

请注意,Serial.printLn如何使用回馈信息 用户。这并不是必要的,但允许你看到一个 命令已被攻击 - 使程序更易于使用。变量启动和测试在程序之前定义。

上面的代码使您可以简单控制微控制器内的变量。

arduino. 字符串串行命令值条目

要在串行控件下进入变量中的值,可以使用以下部分作为交换机语句的一部分。

         case 'v':
            if (sdata.length()>1){
               瓦Str = sdata.substring(1);
                = 瓦Str.toInt();
            }
            Serial.print("Val ");
            Serial.println();
            break;

这只是使用函数子字符串()和oint()来检索a 从串行端口编号字符串并将其转换为内部号码 format.

如果串行数据输入以V然后v然后v)开始 切换语句已激活。如果之后有更多数据'v' i.e. 您键入了一个数字,然后将Valstr设置为从中启动的新字符串 sdata的索引1到最后,即避免'v' character.

瓦Str is then decoded from string to int using the toInt() function 并且在变量中放置的值'val'. 'val'然后打印回到 串口显示发生了什么。

如果你只输入了'v'然后只有最后两个打印语句是 自字符串以来执行'S的长度现在是一个。通过这种方式,您可以更改或仅查询值 'val'.

arduino. 字符串草图示例

使用Arduino字符串的全命令解码器

以下Arduino字符串草图示例拉动上述所有内容 代码片段一起向您展示如何解码串行数据 将值输入到任何Arduino草图中的变量中。

细绳 sdata="";  // Initialised to nothing.
byte test,start;

void setup (void) {
   Serial.begin(9600);
   Serial.println("Command Interpreter");
}

void loop(void ) {
byte ch;
细绳 瓦Str;
 在 t ;

   if (Serial.available()) {
      ch = Serial.read();

      sdata += (char)ch;

      if (ch=='\r') {  // Command received and ready.
         sdata.trim();

         // Process command in sdata.
         switch( sdata.charAt(0) ) {
         case 's':
            start = 1;
            Serial.println("Start Process");
            break;
         case 't':
            test = 1;
            Serial.println("Test");
            break;
         case 'v':
            if (sdata.length()>1){
               瓦Str = sdata.substring(1);
                = 瓦Str.toInt();
            }
            Serial.print("Val ");
            Serial.println();
            break;
         default: Serial.println(sdata);
         } // switch

         sdata = ""; // Clear the string ready for the next command.
      } // if \r
   }  // available
}

[文件:string.ino]

基于字符串的命令解码器(IDE Ver 1.8.8)的统计信息:

素描使用3912字节(12%)的程序存储空间。最大是30720字节。
全局变量使用248字节(12%)的动态内存,为局部变量留下1800字节。最大是2048字节。

命令解码器的串行监视结果

这里's在您输入时会发生什么's', 't', 'v198' - 在每个命令点击返回键后(输入键)。

Command Interpreter
Start Process
Test
Val 198

这表明切换语句的每个部分被激活 变量val具有十进制值198.这是真的 the code...

Serial.println();

...转换内部二进制表示'val'进入文本可读表单,并将数据发送到串行端口。

使用C字符串的完整命令解码器

现在让我们看看相同操作的C字符串版本(您'请看看为什么偶尔!)

byte test,start;

#define BUF_LEN 20

void setup (void) {
   Serial.begin(9600);
   Serial.println("Command Interpreter");
}

void loop(void ) {
static char sdata[BUF_LEN], *pSdata=sdata;
byte ch;
 在 t ;

   if (Serial.available()) {
      ch = Serial.read();

      // -1 for null terminator space
      if ((pSdata - sdata)>=BUF_LEN-1) {
pSdata--;
Serial.print("BUFFER OVERRUN\n");
}
*pSdata++ = (char)ch; if (ch=='\r') { // Command received and ready. pSdata--; // Don't add \r to string. *pSdata = '\0'; // Null terminate the string. // Process command in sdata. switch( sdata[0] ) { case 's': start = 1; Serial.println("Start Process"); break; case 't': test = 1; Serial.println("Test"); break; case 'v': if (strlen(sdata)>1) = atoi(&sdata[1]); Serial.print("Val "); Serial.println(); break; default: Serial.println(sdata); } // switch pSdata = sdata; // Reset pointer to start of string. } // if \r } // available }

上面的Arduino字符串统计信息(基于C字符串)命令解码器(IDE Ver 1.8.8):

草图使用2076字节(6%)的程序存储空间。最大是30720字节。
全局变量使用270字节(13%)的动态内存,为局部变量留下1778个字节。最大是2048字节。

笔记: 上述程序的输出和终极操作与其完全相同'String-class' based one.

arduino. 字符串参考文献

arduino字符串对象

对于c对象字符串,看起来很好的地方是 arduino. 字符串参考。这向您展示了可用的成员函数(滚动链接)。

arduino. 字符串(C型字符串)

对于c对象字符串,一个好地方看起来是 arduino. C字符串参考.

但是,上面的链接不详细介绍用于C样式字符串的功能。为此看起来 标准参考。此链接很好,因为它按照最常使用的顺序排序函数。

P.S.看看strtok(),因为这可以允许您处理一个 具有多个命令的命令行用分隔符分隔。一个 半冒号 - 对于更复杂的串行命令解码器有用。

字符串和C字符串的比较

下表显示了内存使用情况的差异:

类型
闪光
SRAM.
细绳
3912 248
C字符串
2076
270
差异字符串CF C字符串
+1836
-22

注意:似乎字符串类使用 较少的SRAM,但实际上使用堆并使用超过C字符串使用 (它只是不容易衡量,因为它可以随着字符串创建和销毁的时间一致)。

使用类字符串来控制字符串无疑是最简单的方法 非常类似于诸如Python的更高级别语言,但它来了 以成本 - 成本是闪存程序内存。

闪存

虽然此C字符串程序与基于字符串的C字符串程序完全相同的操作,但基于字符串的一个响应 1836年的字节 闪光。这是在后台执行魔法的字符串类。

此内存量可能对具有大闪光灯的设备可能无关紧要 记忆,但使用Arduino Uno时相当重大(32K Flash).

arduino. 字符串SRAM使用

您可以看到C Strings的SRAM用于C字符串高于字符串 - 这是因为缓冲区被声明为静态字节数组 在程序运行之前:

static char sdata[BUF_LEN],

这意味着在运行时保留此字符串的SRAM。什么时候 使用堆(在字符串类中)内存在运行时分配。 这真的意味着 编译器尚不知道使用多少内存(或将) 使用字符串对象时的程序(并且它将与有一个更大 使用Malloc管理SRAM块的开销和免费 C和C ++中使用的内存分配和拒绝函数)。

SRAM. 内存大小

要注意的另一件事是:

  • 在字符串程序中,没有内存声明。

没有规格的用于存储的内存大小 String - 实际上字符串存储在SRAM中,但它们使用堆。 堆是未使用的内存,可以在堆栈和变量之间坐在 space.

你应该使用字符串吗?

如果您在网上搜索,您会发现可能存在问题 使用基于堆的系统,这是由于内存碎片。 堆中的碎片是在较大长度的弦串时引起的 不被分配给'freed'内存块(自块以来 been previously 'freed'太小了);他们必须分配 新记忆。这留下了许多小块未使用的内存。

在极端情况的记忆碎片中,当你有低时造成的 SRAM!和大量的字符串操作,可能导致您的程序 挂起 - 解决方案是按重置按钮!小程序 带有少量字符串,罚款(那里赢了't be #enough memory 碎片使程序挂起。

以下陈述来自汽车联盟 制造商Misra(电机行业软件可靠性协会)。 他们专门禁止使用基于堆的内存管理,因为 safety is crucial:

    Misra C ++规则18-4-1,无法使用动态堆内存分配。

这个 文档 描述静态,动态内存碎片等。但其最终结论是:

疲惫还在 我们在实时嵌入中使用动态内存的主要障碍 系统。基于STD :: Bad_Alloc的良好失败策略可以 解决许多问题, 但在高完整性系统中动态 内存使用率将保持不可接受。

对于不使用许多字符串的程序,Arduino字符串类是 美好的。但是,如果您有低级别的SRAM并使用大量字符串 操纵你可以遇到碎片问题(随机 failure).

究竟是什么字符串?

如上所述,字符串是存储在SRAM中的文本行。

注意:本节适用于串和C字符串。

两个字符串和'strings'是动态实体,这意味着它们可以是 自从SRAM中存在以来,无论何时都有所要随意更改。对于嵌入式 通常具有非常低的SRAM(Arduino Uno 2K字节)的系统 这意味着除非你放所有的常量,否则SRAM会很快消失 strings into Flash.

实际上字符串在C或C ++中倍换,因为他们使用 both Flash and SRAM.

第一个原因是初创化。你可能想要开始 字符串,其中一些信息为例如"Initialising I2C" etc.; Sometimes you don't e.g.串行输入的接收缓冲区。要做 初始化您需要某处存放电源时的字符串 关闭,该商店是闪存。

第二个原因是字符串被定义为RAM中存在的 它们可以随着程序运行而更改。

在某些情况下,你不't want an 可更新的字符串e.g,用于永不改变的短信。问题 是编译器赢了'知道字符串永远不会去 change.

将字符串放入闪存中

将字符串放入Flash,在Arduino代码中,附上固定的字符串 用f宏e.g。 serial.print(f("My fixed string")); That leaves the 闪存中的字符串。

使用f()宏停止转移 从闪存到SRAM的初始化数据并仅使用数据 从闪存中,您可以保存SRAM。

提示: 还有其他专门用于使用闪存的功能 例如字符串从闪存复制到'SRAM中的正常字符串'. You can find 这些通过搜索"Arduino progmem strcpy_p."。这些都是专门的 你赢了的功能'经常需要,但很高兴知道他们是 available.


arduino. 字符串和C字符串比较

字符串类的优点

  • 不允许缓冲区溢出。
  • 易于使用和直观的尤。附加字符串使用'+ operator

字符串类的缺点

  • 使用更多闪存。
  • 使用堆导致堆碎片。
  • 使用运行时使用未定义数量的SRAM的堆。

C字符串的优点

  • 使用最小闪存。
  • 不使用堆。
  • 您可以完全控制如何使用内存。

C字符串的缺点

  • 不直观。
  • 如果不小心,可以让缓冲区溢出。





新的! Comments

让你说到你刚刚阅读的东西!留下下面的框中的评论。




隐私政策 | 接触 | 关于我

网站地图 | 使用条款


 ezoic. 报告此广告

访问我们的Facebook页面:

   点击这里



最近的文章

  1. 如何使用ADS1115

    使用ADS1115精度16位ADC进行教程进行低功耗。

    阅读更多

  2. arduino. 模拟输出...易模拟输出生成

    arduino. 模拟输出:如何创建最精确的PWM模拟输出以及如何创建模拟PWM正弦波。

    阅读更多

  3. 数号和等效的快速宏。加快代码!

    了解DigitalWrite()的工作原理......现在使用17倍宏宏!

    阅读更多

  4. TCS230颜色传感芯片:如何运作以及如何使用它。

    如何使用TCS230(/ TCS3200)彩色检测器芯片并轻松将其添加到您的任何项目中。

    阅读更多

  5. 如何使用ADXL345进行运动感测等。

    使用ADXL345 Acellerometer,您可以检测到16G!您还可以了解如何使用它来点击检测等。

    阅读更多

  6. HMC5883L 3轴数字MAGENTOMTER如何运作

    HMC5883L - 如何制作数字罗盘,了解HMC5883L和QMC5883L之间的差异以及它们是否兼容。

    阅读更多



读者 Comments

"I wanted to thank
你这么好
对于所有信息
你已经提供了
你的网站's

高超 极好的 ."

- 逃亡Potthath.

"This site really is
最好的和我最喜欢的。
我发现这里有很多很有用
项目和提示。"

- 米兰

Bursach.<at>gmail.com<

"Awesome site,
非常,非常容易和好
导航!"


-
Matt_tr. <at>
wolf359.cjb.net.


学习微控制器

"Interested in
微控制器?"

注册
免费7天指南:

自由 GUIDE : CLICK HERE


"I am a newbie to PIC
我想说
 how great your
网站一直在为我。"


- 戴夫

de_scott.<at>bellsouth.net

"Your site is a great
和完美的工作。
恭喜。"


- SURESH.

IntegratedInfosys.<at>
Yahoo.com.

"I couldn't find the correct
要定义的词语
你的网页。

非常有用,揭开,
诚实明确。

非常感谢
你的时间和作品。
问候。 "


- Anon.

回到顶部