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);
  • 代码注释解读:先定义两个字符串 str1str2 ,第一次用 indexOfstr2str1 里第一次出现的位置,第二次指定从 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() 功能:判断字符串是否以指定的子串开头,返回 truefalse
  • 用法示例
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 = 9clockPin = 10latchPin = 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 条评论

目前还没有评论...