- 机器人等级考试
ESP32 for Arduino 字符串解析与数码管显示学习笔记
- 2025-7-28 21:31:12 @
ESP32 for Arduino 字符串解析与数码管显示学习笔记
一、课程目标
本次课程,我们将学习在 ESP32 平台上,借助 Arduino 框架进行字符串解析操作,以及控制数码管显示数据。通过学习 String 库函数的使用,掌握字符串的各类处理技巧,再结合硬件控制,实现从串口接收数据并在数码管显示,让大家既能深入理解字符串操作,又能上手硬件交互,感受嵌入式开发的乐趣 。
二、知识储备 - Arduino 字符串解析核心函数(ESP32 适用)
在 ESP32 的 Arduino 开发环境中,String 库为我们提供了丰富的字符串处理函数,以下逐个学习:
1. String 对象
- 作用:就像一个“容器”,用来创建字符串实例,后续对字符串的操作都基于这个对象。
- 示例:
String str = "Hello, ESP32!";
,这样就创建了一个名为str
的字符串对象,里面存着"Hello, ESP32!"
这段内容 。
2. length() 函数
- 功能:获取字符串的长度,也就是字符串里包含多少个字符(空格、字母等都算)。
- 用法示例:
String str1 = "hello";
// 串口打印字符串长度,这里会输出 5,因为 "hello" 有 5 个字符
Serial.println(str1.length());
- 代码注释解读:先创建字符串
str1
,然后调用length()
函数获取其长度,再通过串口打印出来,方便我们查看结果 。
3. indexOf() 函数
- 功能:从左往右找指定字符或子串在字符串里的位置,位置编号从 0 开始。有两种用法:
indexOf(val)
:直接找val
首次出现的位置。indexOf(val, from)
:从from
位置开始找val
首次出现的位置 。
- 用法示例:
String str1 = "hellohiokhinice";
String str2 = "hi";
// 找 str2 首次出现的位置,会返回 5(因为 "hi" 从第 5 位开始,位置从 0 算)
int index1 = str1.indexOf(str2);
Serial.println(index1);
// 从第 6 位(5 + 1)开始找第二个 "hi" ,会返回新的位置
int index2 = str1.indexOf(str2, 5 + 1);
Serial.println(index2);
- 代码注释解读:先定义两个字符串
str1
和str2
,第一次用indexOf
找str2
在str1
里第一次出现的位置,第二次指定从5 + 1
位置开始找,这样就能找第二个str2
的位置啦,最后把找到的位置通过串口打印 。
4. substring() 函数
- 功能:从字符串里截取部分内容,有两种用法:
substring(from)
:从from
位置(从 0 开始)开始,截取到字符串末尾。substring(from, to)
:从from
位置开始,截取到to
位置,但不包含to
位置的字符 。
- 用法示例:
String str1 = "hellohiokhinice";
// 从第 11 位开始截取,会得到 "nice"
String t1 = str1.substring(11);
Serial.println(t1);
// 从第 5 位开始,截取到第 7 位(不包含第 7 位),得到 "hi"
String t2 = str1.substring(5, 7);
Serial.println(t2);
- 代码注释解读:定义字符串
str1
后,第一次截取从第 11 位到末尾,第二次精准截取从第 5 位到第 7 位(不含第 7 位),把截取结果通过串口打印,就能看到效果啦 。
5. toInt() 函数
- 功能:把字符串里的数字内容转换成整数类型。
- 用法示例:
String str2 = "320";
// 把 "320" 转换成整数 320
int n2 = str2.toInt();
Serial.println(n2);
- 代码注释解读:创建字符串
str2
存着数字字符串,调用toInt()
函数就能转成整数,串口打印出来就是转换后的整数啦,这样在处理串口传过来的数字字符串时超有用 。
6. toFloat() 函数
- 功能:将字符串里的小数内容转换成浮点数类型。
- 用法示例:
String str3 = "3.1415926";
// 把字符串转成浮点数,这里会输出 3.1415926 左右(因显示精度可能有小变化)
float n3 = str3.toFloat();
Serial.println(n3);
- 代码注释解读:定义存小数的字符串
str3
,用toFloat()
转成浮点数,串口打印查看转换结果,处理带小数的传感器数据等场景常用到 。
7. endsWith() 和 startsWith() 函数
- endsWith() 功能:判断字符串是否以指定的子串结尾,返回
true
(是)或false
(否)。 - startsWith() 功能:判断字符串是否以指定的子串开头,返回
true
或false
。 - 用法示例:
String str1 = "hellohiokhinice";
// 判断是否以 "nice" 结尾,返回 true
Serial.println(str1.endsWith("nice"));
// 判断是否以 "ok" 结尾,返回 false
Serial.println(str1.endsWith("ok"));
// 判断是否以 "hello" 开头,返回 true
Serial.println(str1.startsWith("hello"));
- 代码注释解读:对
str1
分别用endsWith
判断结尾、startsWith
判断开头,把结果通过串口打印,在判断字符串格式(比如协议指令首尾特征)时很好用 。
三、硬件控制 - 数码管显示(基于 74HC595 扩展)
1. 硬件连接说明(配合 ESP32 )
我们用 74HC595 芯片扩展引脚来控制数码管,涉及以下引脚:
dataPin
(数据引脚,对应 74HC595 的 DS ):用来传输数据。clockPin
(时钟引脚,对应 74HC595 的 SH_CP ):控制数据传输节奏。latchPin
(锁存引脚,对应 74HC595 的 ST_CP ):把传输到 74HC595 的数据锁存,让数码管显示 。 在实际接线时,按照代码里定义的引脚(dataPin = 9
、clockPin = 10
、latchPin = 11
,也可根据自己硬件调整 ),把 ESP32 对应引脚和 74HC595 、数码管正确连接好,才能让数码管正常工作 。
2. 关键函数解析
(1)disPlayNumber(int digit, int number)
函数
- 功能:在数码管的指定位(
digit
)显示指定数字(number
)。 - 代码及注释:
void disPlayNumber(int digit, int number){
byte v = 0b0;
// 通过 bitSet 函数设置要显示的位,digit - 1 是因为位置从 0 开始算
shiftOut(dataPin, clockPin, MSBFIRST, bitSet(v, digit - 1));
// 传输数字对应的段选数据,~disNum[number] 是因为数码管是共阴极,取反让对应段点亮
shiftOut(dataPin, clockPin, LSBFIRST, ~disNum[number]);
digitalWrite(latchPin, LOW); // 拉低锁存引脚,开始传输数据到 74HC595
digitalWrite(latchPin, HIGH); // 拉高锁存引脚,把数据锁存,数码管显示对应数字
}
- 解读:先准备好要控制的位和数字对应的段选数据,通过
shiftOut
函数把数据按顺序传到 74HC595 ,再控制锁存引脚,让数码管亮起来显示指定数字 。
(2)disPlayNumberS(int n)
函数
- 功能:把整数
n
分解成个位、十位、百位、千位等数字,然后逐个调用disPlayNumber
函数在数码管不同位显示。 - 代码及注释:
void disPlayNumberS(int n){
int arr[5]={};
// 获取个位数字,n % 10 就是取余数,得到最后一位
arr[1] = n % 10;
// 获取十位数字,先 n / 10 去掉个位,再 % 10 取余数得到十位
arr[2] = n / 10 % 10;
arr[3] = n / 100 % 10; // 获取百位数字
arr[4] = n / 1000 % 10; // 获取千位数字
for(int i = 1; i <= 4; i++){
// 4 - i + 1 是计算要显示的位,比如 i=1 时,对应数码管最左边位(假设四位数码管)
disPlayNumber(4 - i + 1, arr[i]);
}
}
- 解读:通过数学运算把整数
n
拆分成各个位的数字存在数组里,再循环调用disPlayNumber
,让数码管每一位显示对应数字,这样就能把完整的整数显示出来啦 。
(3)loop
函数里的串口数据处理
- 代码及注释:
int value = 0;
void loop() {
// 判断串口是否有数据进来,Serial.available() > 0 表示有数据
if(Serial.available() > 0){
// 从串口读取整数,存到 value 里
value = Serial.parseInt();
// 读取换行符,避免影响下次数据读取
Serial.read();
}
// 调用函数把 value 显示在数码管上
disPlayNumberS(value);
}
- 解读:不断检测串口,有数据就读取整数,处理掉换行符,然后调用
disPlayNumberS
函数在数码管显示,这样就能实现从串口接收数字并显示的功能啦 。
四、完整代码整合与实践
1. 字符串解析测试代码(可先在串口看效果)
把前面字符串解析的功能整合到 setup
函数(因为只需要运行一次查看结果),代码如下:
void setup() {
Serial.begin(115200); // 初始化串口,波特率 115200
// 以下是字符串解析相关测试
String str1 = "hellohiokhinice";
String str2 = "hi";
// length() 测试
Serial.println("=== length() 测试 ===");
Serial.println("字符串 str1 的长度:" + String(str1.length()));
// indexOf() 测试
Serial.println("\n=== indexOf() 测试 ===");
int index1 = str1.indexOf(str2);
Serial.println("str2 在 str1 中首次出现的位置:" + String(index1));
int index2 = str1.indexOf(str2, 5 + 1);
Serial.println("str2 在 str1 中从第 6 位开始出现的位置:" + String(index2));
// substring() 测试
Serial.println("\n=== substring() 测试 ===");
String t1 = str1.substring(11);
Serial.println("从第 11 位截取的字符串:" + t1);
String t2 = str1.substring(5, 7);
Serial.println("从第 5 位到第 7 位(不含第 7 位)截取的字符串:" + t2);
// toInt() 测试
Serial.println("\n=== toInt() 测试 ===");
String numStr = "320";
int num = numStr.toInt();
Serial.println("字符串转整数结果:" + String(num));
// toFloat() 测试
Serial.println("\n=== toFloat() 测试 ===");
String floatStr = "3.1415926";
float fNum = floatStr.toFloat();
Serial.println("字符串转浮点数结果:" + String(fNum));
// endsWith() 和 startsWith() 测试
Serial.println("\n=== endsWith() 和 startsWith() 测试 ===");
Serial.println("str1 是否以 'nice' 结尾:" + String(str1.endsWith("nice")));
Serial.println("str1 是否以 'ok' 结尾:" + String(str1.endsWith("ok")));
Serial.println("str1 是否以 'hello' 开头:" + String(str1.startsWith("hello")));
}
void loop() {
// 这里暂时不需要循环执行的内容
}
- 实践步骤:
- 把代码上传到 ESP32 ,打开串口监视器,就能看到各个字符串函数测试的结果啦,对照前面学的知识,看看是不是和预期一样,加深理解 。
2. 数码管显示完整代码(结合字符串解析与硬件控制)
整合字符串解析(假设从串口接收字符串转数字)和数码管显示功能,代码如下:
const int dataPin = 9; // 数据引脚 (DS)
const int clockPin = 10; // 时钟引脚 (SH_CP)
const int latchPin = 11; // 锁存引脚 (ST_CP)
const byte disNum[11] = {
// 数码管各段状态定义(共阴极:1=亮,0=灭)
// abcdefgdp
0b11111100, //0
0b01100000, //1
0b11011010, //2
0b11110010, //3
0b01100110, //4
0b10110110, //5
0b10111110, //6
0b11100000, //7
0b11111110, //8
0b11110110, //9
0b00000001 //.
};
void setup() {
pinMode(dataPin, OUTPUT);
pinMode(clockPin, OUTPUT);
pinMode(latchPin, OUTPUT);
Serial.begin(115200);
Serial.println("ESP32 字符串解析与数码管显示测试就绪!");
}
void disPlayNumber(int digit, int number){
byte v = 0b0;
shiftOut(dataPin, clockPin, MSBFIRST, bitSet(v, digit - 1));
shiftOut(dataPin, clockPin, LSBFIRST, ~disNum[number]);
digitalWrite(latchPin, LOW);
digitalWrite(latchPin, HIGH);
}
void disPlayNumberS(int n){
int arr[5]={};
arr[1] = n % 10;//获取个位
arr[2] = n / 10 % 10;//获取十位
arr[3] = n / 100 % 10;
arr[4] = n / 1000 % 10;
for(int i=1;i<=4;i++){
disPlayNumber(4 - i + 1, arr[i]);
}
}
int value = 0;
void loop() {
if(Serial.available() > 0){
String recvStr = Serial.readStringUntil('\n'); // 读取串口传来的字符串(含数字等)
// 这里可以先解析字符串,比如判断是否是数字字符串,再转成整数
// 假设传来的是数字字符串,直接转整数
value = recvStr.toInt();
}
disPlayNumberS(value);
}
- 实践步骤:
- 先按照硬件连接说明接好 ESP32 、74HC595 和数码管。
- 上传代码到 ESP32 ,打开串口监视器,发送数字(比如
1234
),看看数码管是不是正确显示啦。也可以尝试发送带字符串解析逻辑的内容(比如先传个字符串,在代码里用indexOf
等函数处理后再转数字显示),拓展玩法 。
五、学习总结与鼓励
恭喜你呀!通过这节课,你已经掌握了 ESP32 在 Arduino 框架
0 条评论
目前还没有评论...