(1)字符串用于存储文本,可用于在LCD或Arduino IDE串行监视器窗口中显示文本。 同时字符串对于存储用户输入也很有用。 例如,用户在连接到Arduino的键盘上键入的字符。
(2)Arduino编程中有两种类型的字符串:
① 字符数组,与C编程中使用的字符串相同;
② Arduino String,它允许我们在程序中使用字符串对象。
(3)构造 String 类的实例,以下都是字符串的有效声明:
String stringOne = "Hello String"; // 用双引号括起来的常量字符串(即 char 数组)
String stringOne = String('a'); // 单个常量字符,用单引号括起来
String stringTwo = String("This is a string"); // converting a constant string into a String object
String stringOne = String(stringTwo + " with more"); //concatenating two strings
String stringOne = String(13); // 一个常量整数
String stringOne = String(analogRead(0), DEC); // using an int and a base
String stringOne = String(45, HEX); // using an int and a base (hexadecimal)
String stringOne = String(255, BIN); // using an int and a base (binary)
String stringOne = String(millis(), DEC); // using a long and a base
String stringOne = String(5.698, 3); // 浮点数或双精度数,使用指定的小数位
字符串声明 | 功能说明 |
---|---|
String thisString = String(13) | 十进制字符串"13" |
String thisString = String(13, HEX) | 字符串"d",它是 13 的十六进制表示 |
String thisString = String(13, BIN) | 字符串"1101",它是 13 的二进制表示 |
String(val) | val:要格式化为字符串的变量。允许的数据类型:string、char、byte、int、long、unsigned int、unsigned long、float、double。 |
String(val, base) | val同上,base:(可选)格式化整数值的基数 |
String(val, decimalPlaces) | val同上,decimalPlaces:仅当 val 为 float 或 double 时.所需的小数位 |
String类 | 功能描述 |
---|---|
String() | String 类的实例,注意:在“双引号”中指定的常量字符串被视为char数组,不是String类的实例 |
charAt(n) | 返回字符串中第n个字符 |
compareTo(S2) | 和给的S2字符串比较,如果两个字符串相同,返回值等于0;否则,返回值不等于0 |
equals() | 比较两个字符串是否相等。 比较区分大小写,这意味着字符串“hello”不等于字符串“HELLO”。 |
length() | 返回字符串中的字符数 |
substring(from, to) | 获取String的子字符串。从指定的起始索引 " from " 到结束索引 " to " (不包括)截取字符串的子串。 |
substring(from) | 返回一个从给定索引" from " 到结尾的新的字符串 |
toInt() | 返回字符串中数字为整数值 |
toCharArray(buf,len) | 把字符串转换成数组char[]。buf:指定char[]的位置,char[] 的大小一定要>=字符串的大小,len:复制的长度 |
strlen() | 用于获取字符串的长度。 字符串的长度仅适用于可打印字符,不包括空终止符。 |
sizeof() | 用于获取包含字符串的数组的长度。 长度包括空终止符,因此长度比字符串的长度多一个。 |
strcat() | 将传递给它的第二个字符串放到传递给它的第一个字符串的末尾 |
concat(S2) | 返回字符串和字符串S2合并后的新字符串 |
equals(S2) | 如果字符串和S2完全相符,就返回TRUE |
(1)串口通信协议:
串行通信协议应严格遵守,串行通信协议是一套规则,必须应用这些规则才能使设备正确地解释它们相互交换的数据。但是,Arduino 会自动处理这个问题,这样程序员/用户的工作就可以简化为简单的写(发送的数据)和读(接收的数据)。Arduino 串口通信的优缺点如下:
① 优点:传输线少,长距离传送时成本低
② 缺点:数据的传送控制比并行通信复杂
(2)串行通信的分类:
① 同步通信 —— 同步的设备使用相同的时钟,它们的时序彼此同步。
② 异步通信 —— 异步的设备具有各自的时钟,并由前一状态的输出触发。
如果给所有连接的设备提供相同的时钟,则它们是同步的。如果没有时钟线,它是异步的。
(3)串行通信的传输方向:
① 单工:是指数据传输仅能沿一个方向,不能实现反向传输。
② 半双工:是指数据传输可以沿两个方向,但需要分时进行。
③ 全双工:是指数据可以同时进行双向传输。
(4)串口通信定义:串口通信(Serial CommunicaTIons)是指串口按位(bit)发送和接收字节。串口用于ASCII码字符的传输,通信使用3根线完成,分别是地线、发送线、接收线。由于串口通信是异步的,端口能够在一根线上发送数据同时在另一根线上接收数据,其他线用于握手,但不是必须的。串口通信最重要的参数是波特率、数据位、停止位和奇偶校验。 对于两个进行通信的端口,这些参数必须要匹配。
(5)波特率:通信双方需要使用一致的的波特率才能正常通信。 Arduino串口通信通常会使用以下波特率:300、600、1200、2400、4800、9600、14400、19200、28800、38400、57600、115200等,最常用的是9600。波特率越大,说明串口通信的速率越快。
(6)Arduino UNO通信:通过Arduino上的USB接口与计算机连接而进行Arduino与计算机之间的串口通信。除此之外,还可以使用串口引脚连接其他的串口设备进行通信。需要注意的是,通常一个串口只能连接一个设备进行通信。
数据格式 | 功能描述 |
---|---|
起始位 | 起始位总为低电平,是一组数据帧开始传输的信号。 |
数据位 | 数据位是一个数据包,其中承载了实际发送的数据的数据段。 当Arduino通过串口发送一个数据包时,实际的数据可能不是8位的,比如,标准的ASCII码是0-127(7位)。而扩展的ASCII码则是0-255(8位)。如果数据使用简单的文本(标准ASCII码),那么每个数据包将使用7位数据。Arduino 默认使用8位数据位,即每次可以传输1B数据。 |
校验位 | 校验位是串口通信中一种简单的检错方式。可以设置为偶校验或者奇校验。当然,没有校验位也可以。Arduino 默认无校验位。 |
停止位 | 每段数据帧的最后都有停止位表示该段数据帧传输结束。停止位总为高电平,可以设置停止位为1位或2位。Arduino默认是1位停止位。当串口通信速率较高或外部干扰较大时,可能会出现数据丢失的情况。为了保证数据传输的稳定性,最简单的方式就是降低通信波特率或增加停止位和校验位。在Arduino中,可以通过 Serial.begin(speed,config) 语句配置串口通信的数据位、停止位和校验位参数。 |
Serial类 | 功能描述 | 语法 | 参数 | 返回值 |
---|---|---|---|---|
begin() | 初始化串口,通常置于setup()函数中,该函数可配置串口的各项参数。 | Serial.begin(speed);Serial.begin(speed, config); | speed:波特率,一般取值9600,115200等。config:设置数据位、校验位和停止位。例如Serial. begin(9600 , SERIAL _8E2) 语句设置串口波特率为9600,数据位为8,偶校验,停止位为2。 | 无 |
end() | 结束串口通信,该操作可以释放该串口所在的数字引脚,此时串口Rx和Tx可以作为数字IO引脚使用。 | Serial.end(); | 无 | 无 |
available() | 判断串口缓冲区的状态,获取串口接收到的数据个数,即获取串口接收缓冲区中的字节数。接收缓冲区最多可保存64B的数据。 | Serial.available(); | 无 | 可读取的字节数 |
print() | 串口输出数据,写入字符数据到串口。将数据输出到串口。数据会以ASCII码形式输出。如果想以字节形式输出数据,则需要使用 write() 函数。 | Serial.print(val);Serial.print(val, format); | val:需要输出的数据,任意数据类型。format:输出的数据格式。BIN(二进制)、OCT(八进制)、DEC(十进制)、HEX(十六进制)。对于浮点数,此参数指定要使用的小数位数(默认输出2位)。 | 返回输出的字节数 |
println() | 将数据输出到串口,并回车换行。数据会以ASCII码形式输出。 | Serial.println(val);Serial.println(val, format); | val:需要输出的数据,任意数据类型。format:输出的数据格式。和 Serial.print(val) 和相同。 | 返回输出的字节数 |
readBytes() | 从接收缓冲区读取指定长度的字符,并将其存人一个数组中。若等待数据时间超过设定的超时时间,则退出该函数。 | Serial.readBytes(buffer, length); | buffer:用于存储数据的数组(char[]或者byte[])。length:需要读取的字符长度。 | 读到的字节数;如果没有找到有效的数据,则返回0。 |
peek() | 返回1字节的数据,但不会从接收缓冲区删除该数据。与read()函数不同,read()函数读取数据后,会从接收缓冲区删除该数据。 | Serial. peek(); | 无 | 进入接收缓冲区的第1字节的数据;如果没有可读数据,则返回-1。 |
write() | 输出数据到串口。以字节形式输出到串口。 | Serial. write(val);Serial. write(str);Serial. write(buf, len); | val:发送的数据。str:String型的数据。.buf:数组型的数据。len:缓冲区的长度。 | 输出的字节数 |
read() | 读取串口数据,一次读一个字符,读完后删除已读数据。 | Serial.read(); | 无 | 返回串口缓存区中第一个可读字节,当没有可读数据时返回-1。 |
readString() | 每次读取一个字符串,程序不知道什么时候能够读取完整的字符串,会默认系统等待1s的时间 | serial.readString() | 无 | String |
readStringUntil() | 每次读取一个字符串,知道遇到截至字符,比如:Serial.readStringUntil(‘,’):程序遇到逗号就不读取串口中的内容了,系统也不会等待,所以你只需要把你要传达的命令放在逗号之前就可以了,相当于给系统一个明确的提示,花费的时间与read()不相上下,但是又能成功读取到字符串。 | serial.readStringUntil(inByte) | inByte (int) 指定用于标记数据结束的字符 | String |
代码实现:
//串口通信实验
//串口助手发送"led_on()"点亮LED,发送"led_off()"熄灭LED,发送led_flash(x)使LED闪烁x次,单片机收到指令后并执行后返回"OK"
//x范围任意
int led = 13;
String myString = ""; //接收串口发送过来的值
String short_String = ""; //存储myString截取后的字符串
String xstr = ""; //存储led_flash(x)的字符串x
String Control_LED[] = {"led_on()", "led_off()", "led_flash(x)"}; //定义字符串数组
int x = 0;//存储led_flash(x)的整数x
void setup()
{
pinMode(led, OUTPUT);
Serial.begin(9600);
}
void loop()
{
if (Serial.available() > 0)//如果串口有数据
{
myString = Serial.readStringUntil('\n');//读取字符串
short_String = myString.substring(0, 8);//截取输入字符串myString的前8位字符
Control_LED[0] = Control_LED[0].substring(0, 8);//截取字符串Control_LED[0]的前8位字符
Control_LED[1] = Control_LED[1].substring(0, 8);//截取字符串Control_LED[1]的前8位字符
Control_LED[2] = Control_LED[2].substring(0, 8);//截取字符串Control_LED[2]的前8位字符
if (myString.length() > 10)
{
xstr = myString.substring(10, myString.length() - 1) ; //提取灯的闪烁次数xstr字符串
x = xstr.toInt();//将字符串xstr转成数字x
}
if (short_String.compareTo(Control_LED[0]) == 0)//比较short_String和截取后led_on()是否相同
{
Serial.println("ON");
digitalWrite(led, HIGH);
}
else if (short_String.compareTo(Control_LED[1]) == 0)//比较short_String和截取后led_off()是否相同
{
Serial.println("OFF");
digitalWrite(led, LOW);
}
else if (short_String.compareTo(Control_LED[2]) == 0 ) //比较short_String和截取后led_flash(x)是否相同
{
Serial.println("OK");
while (x > 0)
{
x--;//x为灯的闪烁次数
digitalWrite(led, HIGH);
delay(500);
digitalWrite(led, LOW);
delay(500);
}
}
}
}
(1)本实验采用Arduino UNO R3开发板及自主搭建电路的方式,实现预设功能。
(2)上位机实现按键检测的电路图,如下图所示:
代码实现:
//串口通信实验
//串口助手发送"read_key()"读取按键状态,如果按键的IO口为高电平返回"key=1",如果为低电平返回"key=0"
//按下只返回一次"key=0",松开只返回一次"key=1"
int KEY = 8;
bool flag = 0;
String myString = ""; //接收串口发送过来的值
String KEY_String = "read_key()";//定义字符串
void setup() {
pinMode(KEY, INPUT_PULLUP);
Serial.begin(9600);
}
void loop()
{
if (Serial.available() > 0)//如果串口有数据
{
myString = Serial.readStringUntil('\n');//读取字符串
}
if (myString.compareTo(KEY_String) == 0)//比较myString和"read_key()"是否相同
{
if (digitalRead(KEY) == LOW) //有按键按下
{
delay(10); //延时去抖动
if (digitalRead(KEY) == LOW) //有按键按下
{
if (flag == 1)
{
flag = 0;
Serial.println("key = 0");//有按键按下,IO口为低电平,打印"key = 0"
}
}
}
else
{
if (flag == 0)
{
flag = 1;
Serial.println("key = 1");//没有按键按下,IO口为高电平,打印"key = 1"
}
}
}
}
参考资料1: Arduino String()用法及代码示例
参考资料2: Arduino - 字符串( Strings)
参考资料3: Arduino字符串操作函数
参考资料4: Arduino基础篇(五)-- 如何快速上手串口通信(Serial)