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


#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;
}
}
