You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在字符串数组中添加LCD自定义字符并实现?

赞美盒:自定义字符实现与代码优化

一、自定义字符在赞美语中的实现

LCD的自定义字符通过lcd.createChar(index, pattern)存入指定索引(0-7),无法直接识别字符串里的{Ao}标记,需要用以下方式处理:

  1. 替换占位符:
    把赞美语中的{Ao}替换为对应自定义字符索引的ASCII值(你将Ao存在索引0,就用\x00作为占位符)。推荐用const char*数组代替String,减少内存占用:

    // 赞美语数组,\x00对应索引0的自定义字符
    const char* compliments[] = {
      "Test 0 \x00",
      "Test 1",
      "Test 2",
      "Test 3",
      "Test 4",
      "Test 5",
      "Test 6",
      "Test 7",
      "Test 8",
      "Test 9"
    };
    
  2. 编写解析打印函数:
    遍历字符串每个字符,遇到占位符时调用lcd.write()输出自定义字符,否则打印普通字符:

    void printCompliment(const char* str) {
      while (*str != '\0') {
        if (*str == '\x00') {
          lcd.write(0);  // 输出索引0的自定义字符
        } else {
          lcd.print(*str);
        }
        str++;
      }
    }
    
  3. 调用解析函数:
    在按钮触发逻辑中,替换原lcd.print(compliments[randNum])为:

    printCompliment(compliments[randNum]);
    

二、代码优化建议

1. 修复防重复逻辑

原代码的防重复逻辑无效,正确逻辑是生成随机数后,若与上一次相同则重新生成,直到不同:

if (!digitalRead(BUTTON_PIN)) {
  // 生成与上一次不同的随机数
  do {
    randNum = random(NUM_COMPLIMENTS);
  } while (randNum == previousRandNum);
  
  previousRandNum = randNum;
  clearLowerLCDRows();
  lcd.setCursor(0, 0);
  printCompliment(compliments[randNum]);
  Serial.println(randNum);
  
  // 按钮防抖,用millis代替delay避免阻塞
  unsigned long pressTime = millis();
  while (!digitalRead(BUTTON_PIN) && millis() - pressTime < 500);
}

2. 常量与内存优化

  • 用宏定义赞美语数量,方便后续修改:
    #define NUM_COMPLIMENTS 10
    
  • 所有固定字符串用const char*代替String,避免Arduino内存碎片化问题。
  • 自定义字符数组命名更清晰,添加注释:
    // 自定义字符:挪威语字母Å的点阵
    byte custom_Aa[8] = {
      B00100,
      B01010,
      B00100,
      B01110,
      B00001,
      B01111,
      B10001,
      B01111
    };
    

3. 函数与可读性优化

  • 重命名clearLCD为clearLowerLCDRows,明确仅清除第1-3行:
    void clearLowerLCDRows() {
      for (int row = 1; row < 4; row++) {
        lcd.setCursor(0, row);
        lcd.print("                    ");
      }
    }
    
  • 变量初始化更合理:int previousRandNum = -1;(随机数范围0-9,第一次生成必然不同)。

4. 完整优化后的代码

#include <Wire.h> 
#include <LiquidCrystal_I2C.h>

// LCD初始化参数
LiquidCrystal_I2C lcd(0x27, 20, 4);

// 常量定义
const int BUTTON_PIN = 7;
#define NUM_COMPLIMENTS 10

// 全局变量
int randNum = 0;
int previousRandNum = -1;  // 初始化为-1,确保第一次随机数有效

// 自定义字符:挪威语字母Å的点阵
byte custom_Aa[8] = {
  B00100,
  B01010,
  B00100,
  B01110,
  B00001,
  B01111,
  B10001,
  B01111
};

// 赞美语数组,\x00对应索引0的自定义字符
const char* compliments[] = {
  "Test 0 \x00",
  "Test 1",
  "Test 2",
  "Test 3",
  "Test 4",
  "Test 5",
  "Test 6",
  "Test 7",
  "Test 8",
  "Test 9"
};

// 清除LCD第1-3行
void clearLowerLCDRows() {
  for (int row = 1; row < 4; row++) {
    lcd.setCursor(0, row);
    lcd.print("                    ");
  }
}

// 解析并打印含自定义字符的赞美语
void printCompliment(const char* str) {
  while (*str != '\0') {
    if (*str == '\x00') {
      lcd.write(0);  // 输出索引0的自定义字符
    } else {
      lcd.print(*str);
    }
    str++;
  }
}

void setup() {
  Serial.begin(9600);
  randomSeed(analogRead(A0));
  pinMode(BUTTON_PIN, INPUT_PULLUP);
  
  // LCD初始化
  lcd.init();
  lcd.backlight();
  lcd.createChar(0, custom_Aa);  // 将自定义字符存入索引0
  
  // 初始界面
  lcd.setCursor(0, 1);
  lcd.print("  Dette er en boks  ");
  lcd.setCursor(0, 2);
  lcd.print("     Trykk  her     ");
}

void loop() {
  // 按钮按下检测(INPUT_PULLUP,按下时为低电平)
  if (!digitalRead(BUTTON_PIN)) {
    // 生成与上一次不同的随机数
    do {
      randNum = random(NUM_COMPLIMENTS);
    } while (randNum == previousRandNum);
    
    previousRandNum = randNum;
    clearLowerLCDRows();
    lcd.setCursor(0, 0);
    printCompliment(compliments[randNum]);
    Serial.println(randNum);
    
    // 按钮防抖,避免重复触发
    unsigned long pressTime = millis();
    while (!digitalRead(BUTTON_PIN) && millis() - pressTime < 500);
  }
}

内容的提问来源于stack exchange,提问作者Robin Bråthen

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.21 04:12:56