【花雕学编程】Arduino OLED 之逐字显示带动态清屏

在这里插入图片描述
《Arduino 手册(思路与案例)》栏目介绍:
在电子制作与智能控制的应用领域:广泛涉及了Arduino BLDC、Arduino CNC、Arduino ESP32 SPP、Arduino FreeRTOS、Arduino FOC、Arduino GRBL、Arduino HTTP、Arduino HUB75、Arduino IoT Cloud、Arduino JSON、Arduino LCD、Arduino OLED、Arduino LVGL、Arduino PID 及 Arduino TFT 等方面的相关拓展思路和众多参考案例。本专栏目前博客近2300篇。
https://blog.csdn.net/weixin_41659040/category_12422453.html

Arduino是一个开放源码的电子原型平台,它可以让你用简单的硬件和软件来创建各种互动的项目。Arduino的核心是一个微控制器板,它可以通过一系列的引脚来连接各种传感器、执行器、显示器等外部设备。Arduino的编程是基于C/C++语言的,你可以使用Arduino IDE(集成开发环境)来编写、编译和上传代码到Arduino板上。Arduino还有一个丰富的库和社区,你可以利用它们来扩展Arduino的功能和学习Arduino的知识。

Arduino的特点是:
1、开放源码:Arduino的硬件和软件都是开放源码的,你可以自由地修改、复制和分享它们。
2、易用:Arduino的硬件和软件都是为初学者和非专业人士设计的,你可以轻松地上手和使用它们。
3、便宜:Arduino的硬件和软件都是非常经济的,你可以用很低的成本来实现你的想法。
4、多样:Arduino有多种型号和版本,你可以根据你的需要和喜好来选择合适的Arduino板。
5、创新:Arduino可以让你用电子的方式来表达你的创意和想象,你可以用Arduino来制作各种有趣和有用的项目,如机器人、智能家居、艺术装置等。

在这里插入图片描述

概念概述
Arduino OLED 指的是将 Arduino 开发平台与 OLED(有机发光二极管)显示屏相结合的应用组合。Arduino 是开源电子原型平台,具备灵活的硬件扩展性和简单易上手的编程环境;OLED 显示屏则以其自发光、高对比度、宽视角、响应速度快等优势,为信息展示提供了优质的视觉体验。二者结合能实现各类数据显示、图形绘制及交互界面展示等功能,在电子制作、物联网、机器人等诸多领域广泛应用。
详细解释

Arduino 相关特性
硬件特性
开源设计:Arduino 的硬件设计方案完全公开,用户能够获取其原理图、PCB 版图等详细资料。这不仅降低了开发成本,还方便开发者根据自身需求对硬件进行修改和扩展,例如制作自定义外形或功能的开发板。
丰富接口资源:Arduino 开发板配备了多种类型的接口。数字输入输出引脚可用于连接开关、继电器、LED 等设备,实现数字信号的读取和输出控制;模拟输入引脚能够采集如温度传感器、光照传感器输出的连续模拟信号,经内部 ADC(模拟 - 数字转换器)转换为数字值供程序处理。
多种供电方式:支持 USB 供电、外接电源适配器供电以及电池供电等多种方式。使用 USB 供电时,可方便地与计算机连接进行程序上传和调试;外接电源适配器则能提供稳定的电源,适用于长时间运行的项目;电池供电赋予了 Arduino 设备便携性,可应用于移动监测等场景。
软件特性
简易编程环境:Arduino 使用基于 C/C++ 的编程语言,其语法简洁易懂。Arduino IDE 是专门为其开发的集成开发环境,具有跨平台性,可在 Windows、Mac OS、Linux 等操作系统上运行。IDE 提供了直观的代码编辑界面、便捷的编译和上传功能,还内置了大量示例代码,帮助初学者快速入门。
庞大的库资源:Arduino 社区拥有丰富的开源库,涵盖了传感器驱动、通信协议、图形绘制等各个领域。例如,Wire 库用于 I2C 通信,SPI 库用于 SPI 通信,开发者可以直接调用这些库,无需从头编写底层代码,大大提高了开发效率。
OLED 显示屏特性
显示原理
OLED 基于有机材料的电致发光特性工作。当在有机材料层两端施加电压时,电子从阴极注入,空穴从阳极注入,二者在有机材料中相遇并复合,释放出能量以光的形式呈现,从而实现发光显示。由于每个像素都能独立发光,OLED 显示屏无需背光源。
性能优势
自发光与高对比度:自发光特性使得 OLED 能够实现真正的黑色显示,因为不发光的像素完全不产生光线。这使得其对比度极高,图像的亮部更亮,暗部更暗,色彩表现更加生动逼真。
宽视角:OLED 的视角非常宽广,通常可达 170° 以上。从不同角度观看显示屏,画面的颜色和亮度变化极小,能为用户提供一致的视觉体验,适用于各种需要多角度观察的应用场景。
快速响应时间:OLED 的响应时间极短,一般在几微秒到几十微秒之间。相比传统的液晶显示屏,OLED 在显示动态画面时不会出现拖影现象,能够清晰、流畅地展示快速变化的图像,如动画、视频等。
轻薄与低功耗:由于无需背光源,OLED 显示屏的结构更加简单,厚度更薄,重量更轻。同时,其在显示黑色画面时几乎不消耗电能,只有发光的像素才会消耗功率,因此在显示深色画面较多的场景下,功耗显著降低。
Arduino 与 OLED 的连接和通信
通信接口类型
SPI(Serial Peripheral Interface):SPI 是一种高速的全双工串行通信协议,Arduino 通过 SPI 接口与 OLED 显示屏连接时,通常需要使用时钟线(SCK)、主输出从输入线(MOSI)、主输入从输出线(MISO)和片选线(SS)。SPI 通信速度快,适合需要快速传输大量数据的应用场景,如显示高分辨率的图像或视频流。
I2C(Inter - Integrated Circuit):I2C 是一种串行通信协议,使用两根线进行通信,即时钟线(SCL)和数据线(SDA)。I2C 接口简单,占用 Arduino 的引脚资源少,并且支持多个设备挂载在同一总线上,通过不同的设备地址进行区分。在一些对引脚资源要求较高的项目中,I2C 接口更为适用。
通信流程
初始化:在 Arduino 代码中,首先需要初始化所选的通信接口(SPI 或 I2C),并设置相关的通信参数,如时钟频率、设备地址等。
发送数据:Arduino 根据需要显示的内容,将数据按照 OLED 显示屏的通信协议进行编码,然后通过通信接口发送给 OLED 显示屏。数据可以是字符、数字、图形等信息。
显示更新:OLED 显示屏接收到数据后,对其进行解码和处理,将相应的内容显示在屏幕上。为了实现动态显示效果,Arduino 可以定期更新发送的数据,使 OLED 显示屏不断刷新显示内容。

应用场景
数据监测与显示:在环境监测系统中,Arduino 连接各种传感器(如温度传感器、湿度传感器、空气质量传感器等)采集环境数据,然后将数据通过通信接口传输到 OLED 显示屏上进行实时显示。用户可以直观地了解环境参数的变化情况。
智能家居控制:在智能家居系统中,Arduino 作为控制核心,连接各种家电设备和传感器。OLED 显示屏可以显示家电设备的状态(如开关状态、温度设置等),并提供操作菜单,用户可以通过触摸按键或其他输入设备在 OLED 显示屏上进行操作,实现对家电设备的远程控制。
机器人交互界面:在机器人项目中,OLED 显示屏可以作为机器人的交互界面,显示机器人的工作状态、任务进度、传感器数据等信息。同时,还可以显示一些动画或图标,增强机器人的人机交互体验。
手持设备与可穿戴设备:由于 OLED 显示屏的轻薄和低功耗特性,与 Arduino 结合可用于开发手持设备和可穿戴设备。例如,制作一个便携式的健康监测设备,通过 Arduino 连接心率传感器、计步器等,将监测数据显示在 OLED 显示屏上,方便用户随时查看自己的健康状况。

在这里插入图片描述
在Arduino项目中,OLED之逐字显示带动态清屏(Character-by-Character Display with Dynamic Screen Clearing on OLED) 是一种增强用户体验的技术。通过逐个字符地显示文本,并适时进行屏幕刷新或清屏操作,可以创造出更加生动、直观的信息展示效果。以下从主要特点、应用场景以及需要注意的事项三个方面进行详细解析。

主要特点

  1. 动态展示
    逐字显示:每个字符依次出现,模拟打字机的效果,吸引用户的注意力。
    动态清屏:在需要更换显示内容时,先清除旧内容再显示新内容,确保信息清晰无误。
  2. 提升可读性
    动态显示方式比一次性全部显示更能引导用户逐步阅读信息,尤其适用于较长的文本或重要提示。
    清晰的过渡效果减少了视觉混乱,帮助用户更好地理解信息。
  3. 节省资源
    相对于复杂的动画或图形,逐字显示和简单的清屏操作对处理器和内存的要求较低,适合Arduino等资源有限的平台。
  4. 灵活调整
    可以根据不同的场景需求调整字符显示的速度、清屏时机等参数,提供个性化的用户体验。
  5. 互动性强
    结合输入设备(如按钮),可以实现交互式的信息展示,例如按下一个按钮后开始显示新的消息。

应用场景

  1. 智能穿戴设备
    在智能手表或健身追踪器上,逐字显示通知或健康提醒,提高用户与设备之间的互动性。
    示例:当收到一条新短信时,屏幕上逐字显示短信内容,用户可以通过点击按钮查看下一条消息。
  2. 智能家居控制面板
    在家庭自动化系统中,用于显示设备状态更新或操作指南,指导用户完成设置。
    示例:当用户更改恒温器设置时,屏幕上逐字显示确认信息:“温度已设置为22度”。
  3. 教育与培训工具
    制作基于Arduino的学习装置,帮助学生理解编程概念或电子元件的工作原理。
    示例:实验仪器上的显示屏逐字显示实验步骤或结果,让学生更容易跟随实验流程。
  4. 公共信息终端
    在公共场所的信息显示屏上,逐字显示公告或紧急通知,确保公众能够及时获取并理解信息。
    示例:图书馆入口处的显示屏逐字显示“今日闭馆,请改日再来”,吸引路过人员的注意。

注意事项

  1. 字符显示速度
    显示速度过快可能导致用户无法跟上信息流,而过慢则可能引起不耐烦。应根据目标受众的特点和使用场景合理设定显示间隔时间。
    建议初始设定一个适中的速度,然后根据反馈进行微调。
  2. 屏幕刷新策略
    动态清屏前需确保所有字符均已正确显示,避免因刷新过早导致部分字符丢失。
    可以考虑采用局部刷新的方式,仅更新发生变化的部分区域,减少全屏刷新带来的闪烁感。
  3. 内存管理
    虽然逐字显示相对简单,但如果处理大量文本或频繁刷新屏幕,仍需注意内存占用情况。
    对于较长的消息,可以分段加载或采用外部存储(如SD卡)来减轻内存压力。
  4. 用户体验设计
    设计时要考虑用户的阅读习惯,选择合适的字体大小和颜色对比度,确保信息易于识别。
    提供简洁明了的操作指引或状态提示,帮助用户快速掌握设备操作方法。

在这里插入图片描述
1、基础逐字显示动画(整行清屏)
功能:实现文字逐字打印效果,整行显示完成后整屏清除

#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
 
#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64
#define OLED_RESET    -1
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
 
void typewriterEffect(const char* text, int x, int y, int delayTime) {
  display.setTextSize(1);
  display.setTextColor(SSD1306_WHITE);
  
  for(int i=0; text[i]!='\0'; i++){
    display.setCursor(x, y);
    display.print(text[i]);
    display.display();
    delay(delayTime);
    
    // 动态清屏:当遇到换行符时整屏清除
    if(text[i] == '\n'){
      delay(500);
      display.clearDisplay();
      x = 0;
      y += 10;
    }
  }
}
 
void setup() {
  if(!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) {
    while(true);
  }
  display.clearDisplay();
  
  const char* demoText = "Hello!\nArduino World!\nWelcome to OLED";
  typewriterEffect(demoText, 0, 0, 100);
}
 
void loop() {}

要点解读:

通过逐个字符遍历实现打字机效果
使用\n换行符作为整屏清除的触发点
500ms延迟实现段落间隔效果
坐标系统自动换行(y += 10)
整屏清除使用clearDisplay()函数

2、局部动态擦除(行内替换)
功能:实现问答式交互,新文字覆盖旧文字区域

void interactiveDialog() {
  const char* dialogs[] = {
    "System: Access Granted",
    "User: Show Settings",
    "System: Loading Config...",
    "User: Change Brightness",
    "System: New Value Set"
  };
 
  int cursorX = 0;
  int maxWidth = 0;
  
  // 预计算最大宽度
  for(int i=0; i<5; i++){
    int16_t x1, y1;
    uint16_t w, h;
    display.getTextBounds(dialogs[i], 0, 0, &x1, &y1, &w, &h);
    maxWidth = max(maxWidth, w);
  }
 
  for(int i=0; i<5; i++){
    // 动态擦除效果
    for(int erasePos = 0; erasePos <= maxWidth; erasePos += 2){
      display.fillRect(0, 0, erasePos, 16, SSD1306_BLACK);
      display.display();
      delay(5);
    }
    
    // 逐字显示新内容
    cursorX = 0;
    for(int c=0; dialogs[i][c]!='\0'; c++){
      display.setCursor(cursorX, 0);
      display.print(dialogs[i][c]);
      cursorX += 6; // 字符宽度约6像素
      display.display();
      delay(50);
    }
    delay(1500);
  }
}
 
void setup() {
  display.begin(SSD1306_SWITCHCAPVCC, 0x3C);
  display.clearDisplay();
  interactiveDialog();
}

要点解读:
使用getTextBounds()预计算文本宽度
通过fillRect()实现局部擦除效果
擦除步进值控制(erasePos += 2)
动态计算字符显示位置(cursorX)
擦除与绘制速度差异实现平滑过渡

3、滚动消息栏(自动清屏)

功能:实现从右向左滚动的消息栏,自动循环显示


void scrollingMarquee(const char* text, int delayTime) {
  int16_t x1, y1;
  uint16_t w, h;
  display.getTextBounds(text, 0, 0, &x1, &y1, &w, &h);
  
  int scrollPos = display.width();
  while(1){
    display.clearDisplay();
    display.setCursor(scrollPos, 0);
    display.print(text);
    display.display();
    
    scrollPos -= 1;
    if(scrollPos < -w) scrollPos = display.width();
    
    delay(delayTime);
    
    // 动态清屏检测:当文字完全移出时立即清除
    if(scrollPos + w < 0 || scrollPos > display.width()){
      display.clearDisplay();
      display.display();
    }
  }
}
 
void setup() {
  display.begin(SSD1306_SWITCHCAPVCC, 0x3C);
  display.clearDisplay();
  display.setTextSize(1);
  scrollingMarquee("This is a scrolling message! ", 50);
}
 
void loop() {}

要点解读:
使用getTextBounds()获取文本宽度
通过修改setCursor坐标实现滚动效果
动态清屏条件判断(scrollPos + w < 0)
无限循环结构(while(1))
滚动速度控制(scrollPos -= 1)

通用优化技巧:
双缓冲技术:对复杂动画可先绘制到缓冲区再整体显示
非阻塞延迟:使用millis()替代delay()实现多任务
字体优化:使用自定义字库节省内存
区域刷新:仅更新变化部分(如display.startscroll())
电源管理:空闲时关闭显示(display.ssd1306_command(SSD1306_DISPLAYOFF))

在这里插入图片描述
4、逐字显示欢迎信息(带淡出清屏)​​
​​功能描述​​
文本逐字显示,完成后淡出清屏,循环播放。
适用于启动画面或提示信息。

#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>

#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64
#define OLED_RESET -1

Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);

const char *welcomeText = "Welcome to Arduino!";
int textIndex = 0;
unsigned long lastUpdate = 0;
const unsigned long delayTime = 200;  // 逐字间隔时间(毫秒)

void fadeOut() {
  for (int alpha = 255; alpha >= 0; alpha -= 5) {
    display.clearDisplay();
    display.setTextSize(1);
    display.setTextColor(display.color565(alpha, alpha, alpha));  // 模拟淡出
    display.setCursor(0, 20);
    display.print(welcomeText);  // 注意:此方法无效,需改用其他方式
    // 正确做法:分步清除部分区域(见下方修正版)
    display.display();
    delay(20);
  }
  display.clearDisplay();
  display.display();
}

void drawTextWithTypingEffect(const char *text, int index) {
  display.clearDisplay();
  display.setTextSize(1);
  display.setTextColor(SSD1306_WHITE);
  display.setCursor(0, 20);
  
  // 显示已输入的部分
  for (int i = 0; i <= index && text[i] != '\0'; i++) {
    display.print(text[i]);
  }
  
  // 如果未结束,显示光标
  if (text[index] != '\0') {
    display.print("_");
  }
  display.display();
}

void setup() {
  if (!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) {
    Serial.println(F("SSD1306 allocation failed"));
    for (;;);
  }
  display.clearDisplay();
  display.display();
  delay(1000);
}

void loop() {
  static unsigned long lastCharTime = 0;
  
  if (millis() - lastCharTime > delayTime) {
    lastCharTime = millis();
    if (textIndex < strlen(welcomeText)) {
      drawTextWithTypingEffect(welcomeText, textIndex);
      textIndex++;
    } else {
      // 完成后淡出清屏(修正版:分步清除)
      for (int i = 0; i < 10; i++) {
        display.clearDisplay();
        display.setTextSize(1);
        display.setTextColor(SSD1306_WHITE);
        display.setCursor(0, 20);
        display.print(welcomeText);
        // 模拟淡出:逐步减少显示区域
        display.fillRect(0, 20, SCREEN_WIDTH, 8 * (10 - i) / 10, SSD1306_BLACK);
        display.display();
        delay(50);
      }
      display.clearDisplay();
      textIndex = 0;  // 重置索引
      delay(1000);    // 暂停后循环
    }
  }
}

​​要点解读​​
​​逐字显示逻辑​​
drawTextWithTypingEffect() 函数通过控制 textIndex 逐个显示字符,并在末尾添加下划线模拟光标。
​​动态清屏优化​​
原代码尝试使用 color565(alpha, …) 实现淡出是错误的(SSD1306 不支持透明度)。
​​修正方案​​:分步清除屏幕下半部分(fillRect),模拟淡出效果。
​​循环播放​​
文本完成后重置 textIndex,实现无限循环。

5、动态更新传感器数据(带擦除旧值)​​
​​功能描述​​
显示传感器数据(如温度),新数据覆盖旧数据时先局部擦除,避免残影。

#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>

#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64
#define OLED_RESET -1

Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);

float temperature = 25.0;  // 模拟初始温度
unsigned long lastUpdateTime = 0;
const unsigned long updateInterval = 2000;  // 每2秒更新一次

void drawTemperature(float temp) {
  display.setTextSize(1);
  display.setTextColor(SSD1306_WHITE);
  display.setCursor(0, 20);
  display.print("Temp: ");
  display.print(temp);
  display.print(" C");
}

void eraseOldText(int x, int y, int width, int height) {
  display.fillRect(x, y, width, height, SSD1306_BLACK);  // 黑色矩形覆盖旧文本
}

void setup() {
  if (!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) {
    Serial.println(F("SSD1306 allocation failed"));
    for (;;);
  }
  display.clearDisplay();
  display.display();
  delay(1000);
}

void loop() {
  static float oldTemp = -100.0;  // 初始化为无效值
  
  if (millis() - lastUpdateTime > updateInterval) {
    lastUpdateTime = millis();
    
    // 模拟温度变化(±0.5随机波动)
    temperature += random(-5, 5) * 0.1;
    
    // 局部擦除旧温度显示区域(假设宽度约80px)
    if (oldTemp != -100.0) {
      eraseOldText(0, 20, 80, 10);  // 覆盖"Temp: XX.X C"区域
    }
    
    drawTemperature(temperature);
    display.display();
    
    oldTemp = temperature;  // 更新旧值
  }
}

​​要点解读​​
​​局部擦除技术​​
eraseOldText() 函数通过 fillRect 精确覆盖旧文本区域,避免全屏清屏导致的闪烁。
​​动态数据更新​​
模拟传感器数据变化(random() 仅作演示,实际替换为真实传感器读取)。
​​性能优化​​
仅更新变化部分,减少OLED写入次数,延长寿命。

6、交互式菜单选择(带选项高亮和确认反馈)​​
​​功能描述​​
显示可选项列表,通过按钮高亮选中项,按确认键后显示反馈信息并动态清屏。

#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>

#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64
#define OLED_RESET -1

Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);

const char *menuItems[] = {"Start", "Settings", "Info"};
const int menuCount = 3;
int selectedItem = 0;

// 模拟按钮引脚
#define BTN_UP    2
#define BTN_DOWN  3
#define BTN_ENTER 4

void drawMenu() {
  display.clearDisplay();
  display.setTextSize(1);
  
  for (int i = 0; i < menuCount; i++) {
    if (i == selectedItem) {
      display.setTextColor(SSD1306_BLACK, SSD1306_WHITE);  // 反色高亮
      display.print("> ");
    } else {
      display.print("  ");
    }
    display.println(menuItems[i]);
    display.setTextColor(SSD1306_WHITE);
  }
  
  display.display();
}

void showConfirmation(const char *message) {
  display.clearDisplay();
  display.setTextSize(1);
  display.setCursor(0, 20);
  display.println(message);
  display.display();
  
  // 动态清屏反馈(淡出效果)
  for (int i = 0; i < 10; i++) {
    display.fillRect(0, 20, SCREEN_WIDTH, 8, SSD1306_BLACK);  // 渐渐擦除文字
    display.display();
    delay(50);
  }
}

void setup() {
  pinMode(BTN_UP, INPUT_PULLUP);
  pinMode(BTN_DOWN, INPUT_PULLUP);
  pinMode(BTN_ENTER, INPUT_PULLUP);
  
  if (!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) {
    Serial.println(F("SSD1306 allocation failed"));
    for (;;);
  }
  drawMenu();
}

void loop() {
  // 按钮处理
  if (digitalRead(BTN_UP) == LOW) {
    selectedItem = (selectedItem - 1 + menuCount) % menuCount;
    drawMenu();
    delay(200);
  }
  if (digitalRead(BTN_DOWN) == LOW) {
    selectedItem = (selectedItem + 1) % menuCount;
    drawMenu();
    delay(200);
  }
  if (digitalRead(BTN_ENTER) == LOW) {
    showConfirmation("Selected: " + String(menuItems[selectedItem]));
    delay(1000);
    drawMenu();  // 返回菜单
  }
}

​​要点解读​​
​​选项高亮逻辑​​
使用反色(SSD1306_BLACK, SSD1306_WHITE)突出显示当前选中项。
​​确认反馈动画​​
showConfirmation() 函数在显示确认信息后,逐步擦除文字模拟"淡出"效果。
​​防抖处理​​
按钮操作后添加 delay(200) 防止重复触发(实际项目建议用 millis() 实现非阻塞防抖)。

注意,以上案例只是为了拓展思路,仅供参考。它们可能有错误、不适用或者无法编译。您的硬件平台、使用场景和Arduino版本可能影响使用方法的选择。实际编程时,您要根据自己的硬件配置、使用场景和具体需求进行调整,并多次实际测试。您还要正确连接硬件,了解所用传感器和设备的规范和特性。涉及硬件操作的代码,您要在使用前确认引脚和电平等参数的正确性和安全性。

在这里插入图片描述

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

驴友花雕

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值