qq_28852193 2024-04-06 11:14 采纳率: 0%
浏览 197
已结题

Arduino SSD1315 esp32 汉字边缘显示问题

gpt,小程序的别来凑热闹了,我不是不会上网,复制粘贴一通浪费自己和别人的时间。这个问题的采纳只会给正常回答。
Arduino代码,屏幕是SSD1315,单片机用的esp32,问题在显示汉字部分,边缘会乱码,屏幕会略过这个汉字(如图2略过了“研”和“融”这两个字)。我想是1个汉字占了2个或3个英文字符的位置,导致一部分汉字字符在上一行,一部分在下一行,所以显示不了,但是不知道如何解决,想问有没有简单的解决方案。
第一张是串口监视器看到的数据,第二张是屏幕显示的数据

img

img


#include <WiFi.h>
#include <WebSocketsServer.h>
#include <Wire.h>
#include <U8g2lib.h>
#include <algorithm>

#define MAX_DISPLAYED_LINES 3      // 设置最大显示行数
#define MIN_DISPLAY_DURATION 5000  // 设置最小显示时间,单位为毫秒

const char* ssid = 
const char* password = 

WebSocketsServer webSocket = WebSocketsServer(81);

U8G2_SSD1306_128X64_NONAME_F_SW_I2C u8g2(U8G2_R0, /* clock=*/22, /* data=*/21, /* reset=*/U8X8_PIN_NONE);

String displayContent = "";
bool newMessage = false;

void webSocketEvent(uint8_t num, WStype_t type, uint8_t* payload, size_t length) {
  switch (type) {
    case WStype_TEXT:
      Serial.printf("[%u] 收到文本消息: %s\n", num, payload);

      // 解析消息
      String message = String((char*)payload);
      if (message.startsWith("display:")) {
        // 提取要显示的内容
        displayContent = message.substring(8);
        Serial.println("更新显示为: " + displayContent);
        newMessage = true;
      }
      break;
  }
}

void setup() {
  u8g2.begin();
  u8g2.enableUTF8Print();
  Serial.begin(115200);
  // 连接WiFi
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    delay(1000);
    Serial.println("连接到WiFi...");
  }
  Serial.println("WiFi连接成功");
  Serial.println(WiFi.localIP());
  //在屏幕上显示连接WiFi后获取到的IP地址
  displayContent = WiFi.localIP().toString();
  newMessage = true;
  // 启动WebSocket服务器
  webSocket.begin();
  webSocket.onEvent(webSocketEvent);
}

// 记录已显示的行数
int displayedLines = 0;  
// 记录上一次显示的时间
unsigned long lastDisplayTime;

void printStringAsCharArray(String inputString) {
  int stringLength = inputString.length();
  char charArray[stringLength + 1]; 
  
  inputString.toCharArray(charArray, stringLength + 1);
  
  Serial.print("String as char array: ");
  for (int i = 0; i < stringLength; i++) {
    Serial.print(charArray[i]);
    Serial.print(" ");
  }
  Serial.println();
}


void loop() {
  // 处理WebSocket事件
  webSocket.loop();
  u8g2.setFont(u8g2_font_wqy12_t_gb2312);
  // u8g2.setFont(u8g2_font_wqy4_t_chinese2);
  // 检查是否有新消息
  if (newMessage) {
    // 清空屏幕
    u8g2.clearBuffer();

    displayedLines = 0;
    lastDisplayTime = millis();

    // 设置文本显示区域
    int displayWidth = u8g2.getWidth();
    int displayHeight = u8g2.getHeight();
    int textX = 0;
    int textY = 20;
    int maxCharsPerLine = 30;

    int lineHeight = u8g2.getAscent() - u8g2.getDescent() + 5;

    // // 剩余待显示的文本
    String remainingText = displayContent;

    while (remainingText.length() > 0) {  //当有剩余显示的文本

      // 如果已显示行数超过阈值,且距离上一次显示的时间不足5秒,延时一段时间再处理
      if (displayedLines >= MAX_DISPLAYED_LINES && millis() - lastDisplayTime < MIN_DISPLAY_DURATION) {
        delay(MIN_DISPLAY_DURATION - (millis() - lastDisplayTime));
        // 清空屏幕
        u8g2.clearBuffer();
        displayedLines = 0;
        textY = 20;
        lastDisplayTime = millis();
      }

      // 计算当前行大概可以显示的字符数,如果剩余字符数足够少就全显示了
      int charsToDisplay = std::min(maxCharsPerLine, (int)remainingText.length());

      // 截取当前行的文本,即要显示的文本
      String currentLine = remainingText.substring(0, charsToDisplay);
      // 计算一下长度
      int currentLineWidth = u8g2.getUTF8Width(currentLine.c_str());

      // 如果长度大于屏幕
      while (currentLineWidth > displayWidth) {
        // 获取最后一个元素
        char lastChar = currentLine.charAt(currentLine.length() - 1);
        // 减少要显示的字符
        charsToDisplay--;
        // 如果是中文字符
        if (lastChar > 127) {
          // 再减少一个要显示的字符
          charsToDisplay--;
          currentLine = remainingText.substring(0, charsToDisplay);
          currentLineWidth = u8g2.getUTF8Width(currentLine.c_str());

        } else {
          // 英文字符
          currentLine = remainingText.substring(0, charsToDisplay);
          currentLineWidth = u8g2.getUTF8Width(currentLine.c_str());
        }
      }
      Serial.println(currentLine);

      // 绘制当前行文本
      u8g2.drawUTF8(textX, textY, currentLine.c_str());   
      u8g2.sendBuffer();

      // 更新坐标
      textY += lineHeight;
      displayedLines++;  //接下来写的那行,下标从0开始

      // 截取剩余文本
      remainingText = remainingText.substring(charsToDisplay);
      // printStringAsCharArray(remainingText);
    }

    u8g2.sendBuffer();

    // 更新屏幕
    newMessage = false;
  }
}

  • 写回答

11条回答 默认 最新

  • 百锦再@新空间创想科技 优质创作者: 编程框架技术领域 2024-04-06 14:56
    关注

    img

    对于你遇到的问题,很可能是由于字符编码的问题所导致的显示异常。通常情况下,汉字占用的字节数会比英文字符多,这可能导致字符显示位置的偏移,从而出现乱码或部分汉字显示不全的情况。

    为了解决这个问题,你可以尝试以下几种方法:

    使用专门库进行中文显示: 确保你使用的屏幕驱动已经支持了中文字符的显示功能,并且按照驱动库的说明进行设置和调用。

    调整字符显示位置: 可以尝试调整字符显示的起始位置,使得汉字能够正确显示在屏幕上。你可以通过修改屏幕显示的起始位置来尝试调整字符的显示位置。

    使用自定义字库: 将所需的中文字符制作成自定义字库,然后通过屏幕驱动或者显示库来显示这些自定义的中文字符。这样能够确保每个中文字符所占的位置都是统一的,不会出现显示偏移的问题。

    检查屏幕分辨率和显示模式: 确保屏幕的分辨率和显示模式的设置是正确的,不会导致字符显示位置的错误。

    评论 编辑记录

报告相同问题?

问题事件

  • 已结题 (查看结题原因) 4月7日
  • 修改了问题 4月6日
  • 创建了问题 4月6日