截图:
能做到实在是不容易啊。-CSDN blink-领先的开发者技术社区


链接:
https://wokwi.com/projects/415868878166248449
代码:
/**************************************************************************
这是基于SSD1306驱动器的单色OLED显示屏的一个示例
在adafruit商店中购买一个!
------> http://www.adafruit.com/category/63_98
本示例用于通过I2C通信的128x64像素显示屏
需要3个引脚进行接口(两个I2C引脚和一个复位引脚)。
Adafruit投入时间和资源提供此开源代码,请通过从Adafruit购买产品来支持Adafruit和开源硬件!
由Limor Fried/Ladyada为Adafruit Industries编写,
并得到开源社区的贡献。
BSD许可证,请查看license.txt以获取更多信息
上述所有文本以及下面的启动屏幕必须在任何重新分发中包含。
**************************************************************************/
#include <SPI.h> // 包含SPI库(虽然此示例使用I2C,但SPI库是Adafruit_GFX库的一部分)
#include <Wire.h> // 包含I2C库
#include <Adafruit_GFX.h> // 包含Adafruit_GFX库,提供图形绘制功能
#include <Adafruit_SSD1306.h> // 包含Adafruit_SSD1306库,用于控制SSD1306驱动的OLED显示屏
#define SCREEN_WIDTH 128 // OLED显示屏宽度,以像素为单位
#define SCREEN_HEIGHT 64 // OLED显示屏高度,以像素为单位
// 声明一个连接到I2C(SDA、SCL引脚)的SSD1306显示屏
#define OLED_RESET 4 // 复位引脚编号(或者如果与Arduino复位引脚共享则为-1)
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET); // 创建SSD1306显示屏对象
#define NUMFLAKES 10 // 动画示例中的雪花数量
#define LOGO_HEIGHT 64 // 徽标高度
#define LOGO_WIDTH 128 // 徽标宽度
static const unsigned char PROGMEM logo_bmp[] =
{
// 这里是一个位图数据数组,定义了要在显示屏上显示的徽标图案
// 数组中的每个字节代表显示屏上的一行像素,1表示白色像素,0表示黑色像素
// 数据已经过压缩,具体解码方式取决于drawBitmap函数的实现
};
void setup() {
Serial.begin(9600); // 初始化串口通信,波特率为9600
// SSD1306_SWITCHCAPVCC = 从3.3V内部生成显示屏电压
if(!display.begin(SSD1306_SWITCHCAPVCC, 0x3D)) { // 地址0x3D用于128x64显示屏
Serial.println(F("SSD1306 allocation failed")); // 如果显示屏初始化失败,打印错误信息
for(;;); // 不要继续,无限循环
}
// 显示初始显示屏缓冲区内容——库使用Adafruit启动屏幕初始化此内容
display.display();
delay(2000); // 暂停2秒
// 清除缓冲区
display.clearDisplay();
// 在白色中绘制单个像素
display.drawPixel(10, 10, SSD1306_WHITE);
// 在屏幕上显示显示屏缓冲区。在绘制命令之后必须调用display()才能使它们在屏幕上可见!
display.display();
delay(2000); // 暂停2秒
// display.display()不需要在每个绘制命令之后调用,
// 除非这就是你想要的...相反,你可以批量处理一组绘制操作,
// 然后通过调用display.display()一次性更新屏幕。这些示例演示了这两种方法...
testdrawline(); // 绘制多条线
testdrawrect(); // 绘制矩形(轮廓)
testfillrect(); // 绘制矩形(填充)
testdrawcircle(); // 绘制圆(轮廓)
testfillcircle(); // 绘制圆(填充)
testdrawroundrect(); // 绘制圆角矩形(轮廓)
testfillroundrect(); // 绘制圆角矩形(填充)
testdrawtriangle(); // 绘制三角形(轮廓)
testfilltriangle(); // 绘制三角形(填充)
testdrawchar(); // 绘制默认字体的字符
testdrawstyles(); // 绘制“样式化”字符
testscrolltext(); // 绘制滚动文本
testdrawbitmap(); // 绘制一个小位图图像
// 反转和恢复显示屏,期间暂停
display.invertDisplay(true);
delay(1000);
display.invertDisplay(false);
delay(1000);
testanimate(logo_bmp, LOGO_WIDTH, LOGO_HEIGHT); // 动画位图
}
void loop() {
// 主循环为空,因为所有演示都在setup()中完成
}
void testdrawline() {
int16_t i;
display.clearDisplay(); // 清除显示屏缓冲区
// 从左到右绘制水平线
for(i=0; i<display.width(); i+=4) {
display.drawLine(0, 0, i, display.height()-1, SSD1306_WHITE);
display.display(); // 用每条新绘制的线更新屏幕
delay(1);
}
// 从上到下绘制垂直线
for(i=0; i<display.height(); i+=4) {
display.drawLine(0, 0, display.width()-1, i, SSD1306_WHITE);
display.display();
delay(1);
}
delay(250); // 暂停250毫秒
display.clearDisplay();
// 从左到右绘制水平线(从底部开始)
for(i=0; i<display.width(); i+=4) {
display.drawLine(0, display.height()-1, i, 0, SSD1306_WHITE);
display.display();
delay(1);
}
// 从下到上绘制垂直线(从右开始)
for(i=display.height()-1; i>=0; i-=4) {
display.drawLine(0, display.height()-1, display.width()-1, i, SSD1306_WHITE);
display.display();
delay(1);
}
delay(250);
display.clearDisplay();
// 从右到左绘制水平线(从底部开始)
for(i=display.width()-1; i>=0; i-=4) {
display.drawLine(display.width()-1, display.height()-1, i, 0, SSD1306_WHITE);
display.display();
delay(1);
}
// 从下到上绘制垂直线(从左开始)
for(i=display.height()-1; i>=0; i-=4) {
display.drawLine(display.width()-1, display.height()-1, 0, i, SSD1306_WHITE);
display.display();
delay(1);
}
delay(250);
display.clearDisplay();
// 从下到上绘制水平线(从左开始)
for(i=0; i<display.height(); i+=4) {
display.drawLine(display.width()-1, 0, 0, i, SSD1306_WHITE);
display.display();
delay(1);
}
// 从左到右绘制垂直线
for(i=0; i<display.width(); i+=4) {
display.drawLine(display.width()-1, 0, i, display.height()-1, SSD1306_WHITE);
display.display();
delay(1);
}
delay(2000); // 暂停2秒
}
void testdrawrect(void) {
display.clearDisplay();
// 绘制一系列减小的矩形
for(int16_t i=0; i<display.height()/2; i+=2) {
display.drawRect(i, i, display.width()-2*i, display.height()-2*i, SSD1306_WHITE);
display.display(); // 用每个新绘制的矩形更新屏幕
delay(1);
}
delay(2000); // 暂停2秒
}
void testfillrect(void) {
display.clearDisplay();
// 绘制一系列减小的填充矩形
for(int16_t i=0; i<display.height()/2; i+=3) {
// 使用逆色,使矩形交替显示白色和黑色
display.fillRect(i, i, display.width()-i*2, display.height()-i*2, SSD1306_INVERSE);
display.display(); // 用每个新绘制的矩形更新屏幕
delay(1);
}
delay(2000); // 暂停2秒
}
void testdrawcircle(void) {
display.clearDisplay();
// 绘制一系列增大的圆
for(int16_t i=0; i<max(display.width(),display.height())/2; i+=2) {
display.drawCircle(display.width()/2, display.height()/2, i, SSD1306_WHITE);
display.display();
delay(1);
}
delay(2000); // 暂停2秒
}
void testfillcircle(void) {
display.clearDisplay();
// 绘制一系列减小的填充圆
for(int16_t i=max(display.width(),display.height())/2; i>0; i-=3) {
// 使用逆色,使圆交替显示白色和黑色
display.fillCircle(display.width() / 2, display.height() / 2, i, SSD1306_INVERSE);
display.display(); // 用每个新绘制的圆更新屏幕
delay(1);
}
delay(2000); // 暂停2秒
}
void testdrawroundrect(void) {
display.clearDisplay();
// 绘制一系列增大的圆角矩形
for(int16_t i=0; i<display.height()/2-2; i+=2) {
display.drawRoundRect(i, i, display.width()-2*i, display.height()-2*i,
display.height()/4, SSD1306_WHITE);
display.display();
delay(1);
}
delay(2000); // 暂停2秒
}
void testfillroundrect(void) {
display.clearDisplay();
// 绘制一系列增大的填充圆角矩形
for(int16_t i=0; i<display.height()/2-2; i+=2) {
// 使用逆色,使圆角矩形交替显示白色和黑色
display.fillRoundRect(i, i, display.width()-2*i, display.height()-2*i,
display.height()/4, SSD1306_INVERSE);
display.display();
delay(1);
}
delay(2000); // 暂停2秒
}
void testdrawtriangle(void) {
display.clearDisplay();
// 绘制一系列减小的三角形
for(int16_t i=0; i<max(display.width(),display.height())/2; i+=5) {
display.drawTriangle(
display.width()/2 , display.height()/2-i,
display.width()/2-i, display.height()/2+i,
display.width()/2+i, display.height()/2+i, SSD1306_WHITE);
display.display();
delay(1);
}
delay(2000); // 暂停2秒
}
void testfilltriangle(void) {
display.clearDisplay();
// 绘制一系列增大的填充三角形
for(int16_t i=max(display.width(),display.height())/2; i>0; i-=5) {
// 使用逆色,使三角形交替显示白色和黑色
display.fillTriangle(
display.width()/2 , display.height()/2-i,
display.width()/2-i, display.height()/2+i,
display.width()/2+i, display.height()/2+i, SSD1306_INVERSE);
display.display();
delay(1);
}
delay(2000); // 暂停2秒
}
void testdrawchar(void) {
display.clearDisplay();
display.setTextSize(1); // 正常1:1像素比例
display.setTextColor(SSD1306_WHITE); // 绘制白色文本
display.setCursor(0,0); // 从左上角开始
display.cp437(true); // 使用完整的256字符“代码页437”字体
// 不是所有字符都适合在显示屏上显示。这是正常的。
// 库将绘制它能绘制的内容,其余部分将被裁剪。
for(int16_t i=0; i<256; i++) {
if(i == '\n') display.write(' '); // 如果是换行符,则写入空格
else display.write(i); // 否则写入当前字符
}
display.display(); // 显示文本
delay(2000); // 暂停2秒
}
void testdrawstyles(void) {
display.clearDisplay();
display.setTextSize(1); // 正常1:1像素比例
display.setTextColor(SSD1306_WHITE); // 绘制白色文本
display.setCursor(0,0); // 从左上角开始
display.println(F("Hello, world!")); // 打印“Hello, world!”
display.setTextColor(SSD1306_BLACK, SSD1306_WHITE); // 绘制“逆色”文本
display.println(3.141592); // 打印π的近似值
display.setTextSize(2); // 绘制2倍缩放文本
display.setTextColor(SSD1306_WHITE);
display.print(F("0x")); display.println(0xDEADBEEF, HEX); // 以十六进制打印十六进制数
display.display(); // 显示文本
delay(2000); // 暂停2秒
}
void testscrolltext(void) {
display.clearDisplay();
display.setTextSize(2); // 绘制2倍缩放文本
display.setTextColor(SSD1306_WHITE);
display.setCursor(10, 0); // 从(10, 0)开始
display.println(F("scroll")); // 打印“scroll”
display.display(); // 显示初始文本
delay(100); // 暂停100毫秒
// 在不同方向上滚动,期间暂停:
display.startscrollright(0x00, 0x0F); // 从右向左滚动
delay(2000); // 暂停2秒
display.stopscroll(); // 停止滚动
delay(1000); // 暂停1秒
display.startscrollleft(0x00, 0x0F); // 从左向右滚动
delay(2000); // 暂停2秒
display.stopscroll(); // 停止滚动
delay(1000); // 暂停1秒
display.startscrolldiagright(0x00, 0x07); // 向下对角线滚动
delay(2000); // 暂停2秒
display.startscrolldiagleft(0x00, 0x07); // 向上对角线滚动
delay(2000); // 暂停2秒
display.stopscroll(); // 停止滚动
delay(1000); // 暂停1秒
}
void testdrawbitmap(void) {
display.clearDisplay();
// 在显示屏中央绘制位图
display.drawBitmap(
(display.width() - LOGO_WIDTH ) / 2,
(display.height() - LOGO_HEIGHT) / 2,
logo_bmp, LOGO_WIDTH, LOGO_HEIGHT, 1);
display.display(); // 显示位图
delay(1000); // 暂停1秒
}
#define XPOS 0 // 索引到函数中的'icons'数组
#define YPOS 1
#define DELTAY 2
void testanimate(const uint8_t *bitmap, uint8_t w, uint8_t h) {
int8_t f, icons[NUMFLAKES][3];
// 初始化“雪花”位置
for(f=0; f< NUMFLAKES; f++) {
icons[f][XPOS] = random(1 - LOGO_WIDTH, display.width()); // 随机x位置
icons[f][YPOS] = -LOGO_HEIGHT; // 初始y位置(屏幕外)
icons[f][DELTAY] = random(1, 6); // 随机y方向速度
Serial.print(F("x: "));
Serial.print(icons[f][XPOS], DEC); // 打印x位置
Serial.print(F(" y: "));
Serial.print(icons[f][YPOS], DEC); // 打印y位置
Serial.print(F(" dy: "));
Serial.println(icons[f][DELTAY], DEC); // 打印y方向速度
}
for(;;) { // 无限循环...
display.clearDisplay(); // 清除显示屏缓冲区
// 绘制每个雪花:
for(f=0; f< NUMFLAKES; f++) {
display.drawBitmap(icons[f][XPOS], icons[f][YPOS], bitmap, w, h, SSD1306_WHITE); // 绘制雪花
}
display.display(); // 在屏幕上显示显示屏缓冲区
delay(200); // 暂停1/10秒
// 然后更新每个雪花的坐标...
for(f=0; f< NUMFLAKES; f++) {
icons[f][YPOS] += icons[f][DELTAY]; // 增加y位置
// 如果雪花在屏幕底部之外...
if (icons[f][YPOS] >= display.height()) {
// 重新初始化为随机位置,刚好在屏幕顶部之外
icons[f][XPOS] = random(1 - LOGO_WIDTH, display.width());
icons[f][YPOS] = -LOGO_HEIGHT;
icons[f][DELTAY] = random(1, 6);
}
}
}
}
这段代码演示了如何使用Adafruit SSD1306库在128x64像素的OLED显示屏上执行各种图形操作,包括绘制线条、矩形、圆形、三角形、文本、位图以及动画效果。每个函数都展示了如何使用库函数来执行特定的图形绘制任务,并通过display.display()
函数将缓冲区内容刷新到屏幕上。
/**************************************************************************
This is an example for our Monochrome OLEDs based on SSD1306 drivers
Pick one up today in the adafruit shop!
------> http://www.adafruit.com/category/63_98
This example is for a 128x64 pixel display using I2C to communicate
3 pins are required to interface (two I2C and one reset).
Adafruit invests time and resources providing this open
source code, please support Adafruit and open-source
hardware by purchasing products from Adafruit!
Written by Limor Fried/Ladyada for Adafruit Industries,
with contributions from the open source community.
BSD license, check license.txt for more information
All text above, and the splash screen below must be
included in any redistribution.
**************************************************************************/
#include <SPI.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#define SCREEN_WIDTH 128 // OLED display width, in pixels
#define SCREEN_HEIGHT 64 // OLED display height, in pixels
// Declaration for an SSD1306 display connected to I2C (SDA, SCL pins)
#define OLED_RESET 4 // Reset pin # (or -1 if sharing Arduino reset pin)
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
#define NUMFLAKES 10 // Number of snowflakes in the animation example
#define LOGO_HEIGHT 64
#define LOGO_WIDTH 128
static const unsigned char PROGMEM logo_bmp[] =
{
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xcf, 0xff, 0xff, 0xff, 0xff, 0xf1, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xe7, 0xff, 0xff, 0xff, 0xff, 0xf0, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xe7, 0xff, 0xff, 0xff, 0xff, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xe7, 0xff, 0xfe, 0x3f, 0xff, 0xc1, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xf8, 0x0f, 0xff, 0xfc, 0x3f, 0xff, 0xc3, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xf0, 0xff, 0xfc, 0x0e, 0x3f, 0xfb, 0x27, 0xff, 0xe6, 0xbf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xf9, 0xff, 0xff, 0x00, 0x1f, 0xfb, 0x07, 0xff, 0xfc, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xfc, 0x7f, 0xff, 0x83, 0x3f, 0xf9, 0x0f, 0xff, 0xfe, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xc0, 0x7f, 0xff, 0x0e, 0x3f, 0xf0, 0x1f, 0xff, 0xfb, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xe0, 0xff, 0xfe, 0x1e, 0x7f, 0xf0, 0x3f, 0xff, 0xdb, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xf3, 0xff, 0xfc, 0x38, 0xff, 0xff, 0x63, 0xff, 0x9f, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xec, 0x3f, 0xf8, 0x38, 0xff, 0xef, 0x23, 0xff, 0x98, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xc0, 0x3f, 0xf1, 0x70, 0x1f, 0xe7, 0x27, 0xff, 0x9e, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xc0, 0x3f, 0xf0, 0x68, 0x1f, 0xe6, 0x67, 0xff, 0x9e, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xcc, 0x7f, 0xe0, 0x40, 0x3f, 0xc4, 0x4f, 0xff, 0x98, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xf8, 0x7f, 0xe0, 0x00, 0xff, 0xc0, 0x41, 0xff, 0x9e, 0x03, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xf0, 0xff, 0xe3, 0x00, 0xff, 0x83, 0x61, 0xff, 0x80, 0x03, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xc7, 0x3f, 0xff, 0xfc, 0xff, 0x87, 0x79, 0xff, 0x0f, 0x9f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0x80, 0x0f, 0xff, 0xfc, 0xff, 0x8f, 0x7f, 0xf0, 0x7f, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0x00, 0x0f, 0xff, 0xfc, 0xff, 0xdf, 0x7f, 0xf3, 0xff, 0x07, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xc1, 0xff, 0xff, 0xfc, 0xff, 0xf8, 0x7f, 0xfd, 0x3f, 0xc3, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xfc, 0xff, 0xfc, 0x7f, 0xfc, 0x3f, 0xe7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xfd, 0xff, 0xfc, 0x7f, 0xfc, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xfd, 0xff, 0xfe, 0x7f, 0xfc, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xf9, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xf9, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xf9, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xfb, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xfb, 0xff, 0xff, 0xff, 0xff, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf9, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xce, 0x3f, 0xff, 0xf8, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x8e, 0x1f, 0xff, 0xf8, 0x7f,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc7, 0x8f, 0xff, 0x3e, 0x07, 0xff, 0xe0, 0x7f,
0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x1f, 0xfe, 0x06, 0x0f, 0xfe, 0x3e, 0x07, 0xff, 0xc0, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x0f, 0xf8, 0x06, 0x0f, 0xff, 0x1f, 0x0f, 0xff, 0xe1, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x07, 0xf8, 0x1e, 0xff, 0xff, 0x8e, 0x1f, 0xff, 0xf3, 0x3f,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x87, 0xfe, 0x04, 0xff, 0xff, 0xcc, 0x1f, 0xff, 0xe0, 0x7f,
0xff, 0xff, 0xff, 0xff, 0xff, 0xfb, 0x87, 0xfe, 0x04, 0x63, 0xfc, 0xc8, 0x3f, 0xff, 0xe0, 0xb3,
0xff, 0xff, 0xff, 0xff, 0xff, 0xf2, 0x0f, 0xfc, 0x0c, 0x03, 0xf8, 0xc0, 0x3f, 0xff, 0x80, 0x33,
0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0x07, 0xff, 0x0c, 0x07, 0xfc, 0x02, 0x0f, 0xf3, 0x88, 0x63,
0xff, 0xff, 0xff, 0xff, 0xff, 0xf3, 0x07, 0xff, 0x84, 0x1f, 0xfe, 0x07, 0xc7, 0xf3, 0xf0, 0xe7,
0xff, 0xff, 0xff, 0xff, 0xff, 0xf1, 0x87, 0xff, 0x04, 0x1f, 0xfc, 0xcf, 0x87, 0xf3, 0xf1, 0xe7,
0xff, 0xff, 0xff, 0xff, 0xff, 0xe1, 0x07, 0xe8, 0x0c, 0x4f, 0xfc, 0x98, 0x0f, 0xfb, 0xe1, 0xe7,
0xff, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x07, 0xe0, 0x00, 0x4f, 0xfc, 0x90, 0x0f, 0xf9, 0xc0, 0x47,
0xff, 0xff, 0xff, 0xff, 0xff, 0xf2, 0x0f, 0xf0, 0x00, 0xcf, 0xfd, 0x32, 0x03, 0xf9, 0xcc, 0x0f,
0xff, 0xff, 0xff, 0xff, 0xff, 0xf1, 0x8f, 0xf9, 0x83, 0xcf, 0xfc, 0x30, 0x01, 0xfc, 0xdd, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xf3, 0xff, 0xf8, 0x1f, 0xcf, 0xfc, 0x78, 0x71, 0xfc, 0x0c, 0x01,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x1f, 0xcf, 0xfc, 0x7f, 0xff, 0xfe, 0x00, 0x03,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xdf, 0x9f, 0xfc, 0x7f, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
};
void setup() {
Serial.begin(9600);
// SSD1306_SWITCHCAPVCC = generate display voltage from 3.3V internally
if(!display.begin(SSD1306_SWITCHCAPVCC, 0x3D)) { // Address 0x3D for 128x64
Serial.println(F("SSD1306 allocation failed"));
for(;;); // Don't proceed, loop forever
}
// Show initial display buffer contents on the screen --
// the library initializes this with an Adafruit splash screen.
display.display();
delay(200); // Pause for 2 seconds
// Clear the buffer
display.clearDisplay();
// Draw a single pixel in white
display.drawPixel(10, 10, SSD1306_WHITE);
// Show the display buffer on the screen. You MUST call display() after
// drawing commands to make them visible on screen!
display.display();
delay(200);
// display.display() is NOT necessary after every single drawing command,
// unless that's what you want...rather, you can batch up a bunch of
// drawing operations and then update the screen all at once by calling
// display.display(). These examples demonstrate both approaches...
testdrawline(); // Draw many lines
testdrawrect(); // Draw rectangles (outlines)
testfillrect(); // Draw rectangles (filled)
testdrawcircle(); // Draw circles (outlines)
testfillcircle(); // Draw circles (filled)
testdrawroundrect(); // Draw rounded rectangles (outlines)
testfillroundrect(); // Draw rounded rectangles (filled)
testdrawtriangle(); // Draw triangles (outlines)
testfilltriangle(); // Draw triangles (filled)
testdrawchar(); // Draw characters of the default font
testdrawstyles(); // Draw 'stylized' characters
testscrolltext(); // Draw scrolling text
testdrawbitmap(); // Draw a small bitmap image
// Invert and restore display, pausing in-between
display.invertDisplay(true);
delay(100);
display.invertDisplay(false);
delay(100);
testanimate(logo_bmp, LOGO_WIDTH, LOGO_HEIGHT); // Animate bitmaps
}
void loop() {
}
void testdrawline() {
int16_t i;
display.clearDisplay(); // Clear display buffer
for(i=0; i<display.width(); i+=4) {
display.drawLine(0, 0, i, display.height()-1, SSD1306_WHITE);
display.display(); // Update screen with each newly-drawn line
delay(1);
}
for(i=0; i<display.height(); i+=4) {
display.drawLine(0, 0, display.width()-1, i, SSD1306_WHITE);
display.display();
delay(1);
}
delay(100);
display.clearDisplay();
for(i=0; i<display.width(); i+=4) {
display.drawLine(0, display.height()-1, i, 0, SSD1306_WHITE);
display.display();
delay(1);
}
for(i=display.height()-1; i>=0; i-=4) {
display.drawLine(0, display.height()-1, display.width()-1, i, SSD1306_WHITE);
display.display();
delay(1);
}
delay(100);
display.clearDisplay();
for(i=display.width()-1; i>=0; i-=4) {
display.drawLine(display.width()-1, display.height()-1, i, 0, SSD1306_WHITE);
display.display();
delay(1);
}
for(i=display.height()-1; i>=0; i-=4) {
display.drawLine(display.width()-1, display.height()-1, 0, i, SSD1306_WHITE);
display.display();
delay(1);
}
delay(100);
display.clearDisplay();
for(i=0; i<display.height(); i+=4) {
display.drawLine(display.width()-1, 0, 0, i, SSD1306_WHITE);
display.display();
delay(1);
}
for(i=0; i<display.width(); i+=4) {
display.drawLine(display.width()-1, 0, i, display.height()-1, SSD1306_WHITE);
display.display();
delay(1);
}
delay(200); // Pause for 2 seconds
}
void testdrawrect(void) {
display.clearDisplay();
for(int16_t i=0; i<display.height()/2; i+=2) {
display.drawRect(i, i, display.width()-2*i, display.height()-2*i, SSD1306_WHITE);
display.display(); // Update screen with each newly-drawn rectangle
delay(1);
}
delay(200);
}
void testfillrect(void) {
display.clearDisplay();
for(int16_t i=0; i<display.height()/2; i+=3) {
// The INVERSE color is used so rectangles alternate white/black
display.fillRect(i, i, display.width()-i*2, display.height()-i*2, SSD1306_INVERSE);
display.display(); // Update screen with each newly-drawn rectangle
delay(1);
}
delay(200);
}
void testdrawcircle(void) {
display.clearDisplay();
for(int16_t i=0; i<max(display.width(),display.height())/2; i+=2) {
display.drawCircle(display.width()/2, display.height()/2, i, SSD1306_WHITE);
display.display();
delay(1);
}
delay(200);
}
void testfillcircle(void) {
display.clearDisplay();
for(int16_t i=max(display.width(),display.height())/2; i>0; i-=3) {
// The INVERSE color is used so circles alternate white/black
display.fillCircle(display.width() / 2, display.height() / 2, i, SSD1306_INVERSE);
display.display(); // Update screen with each newly-drawn circle
delay(1);
}
delay(200);
}
void testdrawroundrect(void) {
display.clearDisplay();
for(int16_t i=0; i<display.height()/2-2; i+=2) {
display.drawRoundRect(i, i, display.width()-2*i, display.height()-2*i,
display.height()/4, SSD1306_WHITE);
display.display();
delay(1);
}
delay(200);
}
void testfillroundrect(void) {
display.clearDisplay();
for(int16_t i=0; i<display.height()/2-2; i+=2) {
// The INVERSE color is used so round-rects alternate white/black
display.fillRoundRect(i, i, display.width()-2*i, display.height()-2*i,
display.height()/4, SSD1306_INVERSE);
display.display();
delay(1);
}
delay(200);
}
void testdrawtriangle(void) {
display.clearDisplay();
for(int16_t i=0; i<max(display.width(),display.height())/2; i+=5) {
display.drawTriangle(
display.width()/2 , display.height()/2-i,
display.width()/2-i, display.height()/2+i,
display.width()/2+i, display.height()/2+i, SSD1306_WHITE);
display.display();
delay(1);
}
delay(200);
}
void testfilltriangle(void) {
display.clearDisplay();
for(int16_t i=max(display.width(),display.height())/2; i>0; i-=5) {
// The INVERSE color is used so triangles alternate white/black
display.fillTriangle(
display.width()/2 , display.height()/2-i,
display.width()/2-i, display.height()/2+i,
display.width()/2+i, display.height()/2+i, SSD1306_INVERSE);
display.display();
delay(1);
}
delay(200);
}
void testdrawchar(void) {
display.clearDisplay();
display.setTextSize(1); // Normal 1:1 pixel scale
display.setTextColor(SSD1306_WHITE); // Draw white text
display.setCursor(0, 0); // Start at top-left corner
display.cp437(true); // Use full 256 char 'Code Page 437' font
// Not all the characters will fit on the display. This is normal.
// Library will draw what it can and the rest will be clipped.
for(int16_t i=0; i<256; i++) {
if(i == '\n') display.write(' ');
else display.write(i);
}
display.display();
delay(200);
}
void testdrawstyles(void) {
display.clearDisplay();
display.setTextSize(1); // Normal 1:1 pixel scale
display.setTextColor(SSD1306_WHITE); // Draw white text
display.setCursor(0,0); // Start at top-left corner
display.println(F("Hello, world!"));
display.setTextColor(SSD1306_BLACK, SSD1306_WHITE); // Draw 'inverse' text
display.println(3.141592);
display.setTextSize(2); // Draw 2X-scale text
display.setTextColor(SSD1306_WHITE);
display.print(F("0x")); display.println(0xDEADBEEF, HEX);
display.display();
delay(200);
}
void testscrolltext(void) {
display.clearDisplay();
display.setTextSize(2); // Draw 2X-scale text
display.setTextColor(SSD1306_WHITE);
display.setCursor(10, 0);
display.println(F("scroll"));
display.display(); // Show initial text
delay(100);
// Scroll in various directions, pausing in-between:
display.startscrollright(0x00, 0x0F);
delay(200);
display.stopscroll();
delay(100);
display.startscrollleft(0x00, 0x0F);
delay(200);
display.stopscroll();
delay(100);
display.startscrolldiagright(0x00, 0x07);
delay(200);
display.startscrolldiagleft(0x00, 0x07);
delay(200);
display.stopscroll();
delay(100);
}
void testdrawbitmap(void) {
display.clearDisplay();
display.drawBitmap(
(display.width() - LOGO_WIDTH ) / 2,
(display.height() - LOGO_HEIGHT) / 2,
logo_bmp, LOGO_WIDTH, LOGO_HEIGHT, 1);
display.display();
delay(6666);
}
#define XPOS 0 // Indexes into the 'icons' array in function below
#define YPOS 1
#define DELTAY 2
void testanimate(const uint8_t *bitmap, uint8_t w, uint8_t h) {
int8_t f, icons[NUMFLAKES][3];
// Initialize 'snowflake' positions
for(f=0; f< NUMFLAKES; f++) {
icons[f][XPOS] = random(1 - LOGO_WIDTH, display.width());
icons[f][YPOS] = -LOGO_HEIGHT;
icons[f][DELTAY] = random(1, 6);
Serial.print(F("x: "));
Serial.print(icons[f][XPOS], DEC);
Serial.print(F(" y: "));
Serial.print(icons[f][YPOS], DEC);
Serial.print(F(" dy: "));
Serial.println(icons[f][DELTAY], DEC);
}
for(;;) { // Loop forever...
display.clearDisplay(); // Clear the display buffer
// Draw each snowflake:
for(f=0; f< NUMFLAKES; f++) {
display.drawBitmap(icons[f][XPOS], icons[f][YPOS], bitmap, w, h, SSD1306_WHITE);
}
display.display(); // Show the display buffer on the screen
delay(200); // Pause for 1/10 second
// Then update coordinates of each flake...
for(f=0; f< NUMFLAKES; f++) {
icons[f][YPOS] += icons[f][DELTAY];
// If snowflake is off the bottom of the screen...
if (icons[f][YPOS] >= display.height()) {
// Reinitialize to a random position, just off the top
icons[f][XPOS] = random(1 - LOGO_WIDTH, display.width());
icons[f][YPOS] = -LOGO_HEIGHT;
icons[f][DELTAY] = random(1, 6);
}
}
}
}
Wokwi Arduino Mega 2560 - OLED 实验报告
实验目的
- 熟悉Wokwi仿真平台的使用,掌握在Wokwi上搭建Arduino Mega 2560开发环境的方法。
- 掌握Arduino Mega 2560与OLED显示屏的接线方法。
- 编写代码实现OLED显示屏上显示静态文字或图形。
- 通过实验加深对Arduino编程和硬件接口的理解。
实验器材
- Wokwi仿真平台
- Arduino Mega 2560开发板(仿真)
- OLED显示屏模块(仿真)
- 杜邦线(仿真)
实验原理
Arduino Mega 2560简介
Arduino Mega 2560是基于ATmega2560微控制器的开发板,具有54个数字输入/输出引脚、16个模拟输入引脚、4个硬件串行端口以及多个外部中断和PWM输出。它拥有丰富的接口资源,适合构建需要大量I/O接口和内存空间的复杂项目。
OLED显示屏简介
OLED(有机发光二极管)显示屏是一种自发光显示技术,具有亮度高、对比度高、视角广、响应速度快等优点。在本实验中,我们使用的是I2C接口的OLED显示屏,通过I2C通信协议与Arduino Mega 2560进行数据传输。
I2C通信协议
I2C(Inter-Integrated Circuit)是一种串行通信协议,使用两根线(SCL和SDA)实现设备之间的通信。SCL(时钟线)用于同步数据传输,SDA(数据线)用于传输数据。I2C协议支持多主多从架构,允许多个设备共享同一总线。
实验步骤
1. 搭建仿真环境
- 打开Wokwi仿真平台:访问Wokwi官网,注册并登录账号。
- 创建新项目:点击“New Project”按钮,选择“Arduino Mega 2560”作为开发板。
- 添加OLED显示屏模块:在仿真界面左侧的元件库中搜索“OLED”,找到并拖拽到仿真区域中。
2. 接线
在Wokwi仿真平台上,使用虚拟杜邦线将Arduino Mega 2560与OLED显示屏连接起来。具体接线如下:
- OLED显示屏的VCC引脚连接到Arduino Mega 2560的3.3V引脚。
- OLED显示屏的GND引脚连接到Arduino Mega 2560的GND引脚。
- OLED显示屏的SCL引脚连接到Arduino Mega 2560的SCL引脚(通常为A5引脚)。
- OLED显示屏的SDA引脚连接到Arduino Mega 2560的SDA引脚(通常为A4引脚)。
3. 编写代码
在Wokwi仿真平台的代码编辑器中编写以下代码,实现OLED显示屏上显示“Hello, Wokwi!”文字。
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
// OLED显示屏的分辨率
#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64
// 声明OLED显示屏对象
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, -1);
void setup() {
// 初始化串口通信,用于调试
Serial.begin(9600);
// 初始化OLED显示屏
if (!display.begin(SSD1306_I2C_ADDRESS, I2C_TWO_WIRE)) {
Serial.println(F("SSD1306 allocation failed"));
for (;;); // Don't proceed, loop forever
}
// 清屏
display.clearDisplay();
// 设置文本大小
display.setTextSize(1);
display.setTextColor(SSD1306_WHITE);
// 在OLED显示屏上显示文字
display.setCursor(0, 0);
display.println("Hello, Wokwi!");
// 更新显示屏
display.display();
}
void loop() {
// 主循环中不需要执行任何操作
}
cpp复制代码
#include <Wire.h> | |
#include <Adafruit_GFX.h> | |
#include <Adafruit_SSD1306.h> | |
// OLED显示屏的分辨率 | |
#define SCREEN_WIDTH 128 | |
#define SCREEN_HEIGHT 64 | |
// 声明OLED显示屏对象 | |
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, -1); | |
void setup() { | |
// 初始化串口通信,用于调试 | |
Serial.begin(9600); | |
// 初始化OLED显示屏 | |
if (!display.begin(SSD1306_I2C_ADDRESS, I2C_TWO_WIRE)) { | |
Serial.println(F("SSD1306 allocation failed")); | |
for (;;); // Don't proceed, loop forever | |
} | |
// 清屏 | |
display.clearDisplay(); | |
// 设置文本大小 | |
display.setTextSize(1); | |
display.setTextColor(SSD1306_WHITE); | |
// 在OLED显示屏上显示文字 | |
display.setCursor(0, 0); | |
display.println("Hello, Wokwi!"); | |
// 更新显示屏 | |
display.display(); | |
} | |
void loop() { | |
// 主循环中不需要执行任何操作 | |
} |
4. 上传并运行代码
- 上传代码:在Wokwi仿真平台上,点击“Upload”按钮将代码上传到Arduino Mega 2560开发板(仿真)。
- 运行仿真:点击“Run”按钮启动仿真,观察OLED显示屏上是否显示“Hello, Wokwi!”文字。
实验结果
在Wokwi仿真平台上运行代码后,OLED显示屏上成功显示了“Hello, Wokwi!”文字,说明实验成功。
实验分析
1. 代码解析
- 库文件包含:代码中包含了
Wire.h
、Adafruit_GFX.h
和Adafruit_SSD1306.h
三个库文件,分别用于I2C通信、图形处理和OLED显示屏驱动。 - OLED显示屏初始化:通过
display.begin(SSD1306_I2C_ADDRESS, I2C_TWO_WIRE)
函数初始化OLED显示屏,设置I2C地址和通信模式。 - 文字显示:使用
display.setCursor(0, 0)
函数设置光标位置,display.println("Hello, Wokwi!")
函数在指定位置显示文字。 - 显示屏更新:调用
display.display()
函数更新显示屏内容。
2. 实验难点与解决方案
-
难点一:OLED显示屏的接线。由于OLED显示屏模块有多种接口类型(如SPI、I2C等),需要仔细查看模块说明书,确保接线正确。
-
解决方案:查阅OLED显示屏模块的说明书,了解各引脚的功能和接线方法。在Wokwi仿真平台上,可以通过拖拽虚拟杜邦线进行接线,方便快捷。
-
难点二:代码编写。需要熟悉Arduino编程语言和OLED显示屏的驱动库函数。
-
解决方案:参考Arduino官方文档和Adafruit提供的OLED显示屏驱动库示例代码,逐步编写和调试代码。
实验结论
通过本次实验,我们成功在Wokwi仿真平台上搭建了Arduino Mega 2560与OLED显示屏的仿真环境,并实现了OLED显示屏上显示静态文字的功能。实验过程中,我们掌握了Wokwi仿真平台的使用、Arduino Mega 2560与OLED显示屏的接线方法以及Arduino编程技巧。本次实验不仅加深了我们对Arduino硬件和编程的理解,还为我们后续开展更复杂的项目奠定了基础。
后续建议
- 扩展功能:可以尝试在OLED显示屏上显示动态图形或动画,进一步挖掘OLED显示屏的显示潜力。
- 集成传感器:可以将其他传感器(如温度传感器、湿度传感器等)与Arduino Mega 2560连接,将采集到的数据实时显示在OLED显示屏上。
- 优化代码:对代码进行优化,提高程序的执行效率和可读性。例如,使用函数封装重复的代码片段,提高代码的可维护性。
以下是一个关于在 Wokwi 平台上使用 Arduino Mega 2560 与 OLED 显示屏进行应用的非常详细的教程:
一、实验准备
-
硬件准备
- Arduino Mega 2560 开发板(在 Wokwi 平台上模拟)
- OLED 显示屏(如 SH1106 型号)
- 杜邦线(用于连接)
-
软件准备
- Wokwi 在线仿真平台
- Arduino IDE(用于编写和上传代码)
- u8g2 库(用于 OLED 显示屏的驱动和控制)
二、OLED 显示屏连接
在 Wokwi 平台上,将 OLED 显示屏的 SDA 和 SCL 引脚分别连接到 Arduino Mega 2560 的 SDA 和 SCL 引脚。通常,Arduino Mega 2560 的 SDA 引脚为 20,SCL 引脚为 21。
三、安装 u8g2 库
- 打开 Arduino IDE。
- 点击“工具”菜单,选择“管理库”。
- 在库管理器中搜索“u8g2”,找到后点击“安装”。
四、编写代码
以下是一个使用 u8g2 库在 OLED 显示屏上显示字符串、整数、浮点数和中文的示例代码:
#include <Arduino.h>
#include <U8g2lib.h>
#include <Wire.h>
// 初始化 OLED 显示屏,使用 SH1106 型号,I2C 接口
U8G2_SH1106_128X64_NONAME_F_HW_I2C u8g2(U8G2_R0, 21, 20, U8X8_PIN_NONE);
void setup(void) {
u8g2.begin(); // 初始化 OLED 显示屏
u8g2.enableUTF8Print(); // 启用 UTF-8 编码,以便显示中文
}
void loop(void) {
// 显示字符串
u8g2.clearBuffer(); // 清除缓冲区
u8g2.setFont(u8g2_font_6x13_tf); // 设置字体类型
u8g2.drawStr(0, 10, "Hello World!"); // 在坐标 (0, 10) 处显示字符串
u8g2.setCursor(0, 40); // 设置光标位置
u8g2.print("Hello World!"); // 在光标处打印字符串
u8g2.sendBuffer(); // 显示缓冲区内容
delay(1000);
// 显示整数和浮点数
u8g2.clearBuffer();
u8g2.setFont(u8g2_font_6x13_tf);
int int_num = 15; // 要显示的整数变量
float float_num = 15.156; // 要显示的浮点数变量
u8g2.setCursor(0, 10);
u8g2.print(int_num); // 打印整数
u8g2.setCursor(0, 40);
u8g2.print(float_num); // 打印浮点数(自动四舍五入到小数点后两位)
u8g2.sendBuffer();
delay(1000);
// 显示中文
u8g2.clearBuffer();
u8g2.setFont(u8g2_font_unifont_t_chinese2); // 设置中文字体
u8g2.setFontDirection(0); // 设置字体方向
u8g2.setCursor(0, 15);
u8g2.print("Hello World!"); // 打印英文字符串
u8g2.setCursor(0, 40);
u8g2.print("你好世界"); // 显示中文
u8g2.sendBuffer();
delay(1000);
}
cpp复制代码
#include <Arduino.h> | |
#include <U8g2lib.h> | |
#include <Wire.h> | |
// 初始化 OLED 显示屏,使用 SH1106 型号,I2C 接口 | |
U8G2_SH1106_128X64_NONAME_F_HW_I2C u8g2(U8G2_R0, 21, 20, U8X8_PIN_NONE); | |
void setup(void) { | |
u8g2.begin(); // 初始化 OLED 显示屏 | |
u8g2.enableUTF8Print(); // 启用 UTF-8 编码,以便显示中文 | |
} | |
void loop(void) { | |
// 显示字符串 | |
u8g2.clearBuffer(); // 清除缓冲区 | |
u8g2.setFont(u8g2_font_6x13_tf); // 设置字体类型 | |
u8g2.drawStr(0, 10, "Hello World!"); // 在坐标 (0, 10) 处显示字符串 | |
u8g2.setCursor(0, 40); // 设置光标位置 | |
u8g2.print("Hello World!"); // 在光标处打印字符串 | |
u8g2.sendBuffer(); // 显示缓冲区内容 | |
delay(1000); | |
// 显示整数和浮点数 | |
u8g2.clearBuffer(); | |
u8g2.setFont(u8g2_font_6x13_tf); | |
int int_num = 15; // 要显示的整数变量 | |
float float_num = 15.156; // 要显示的浮点数变量 | |
u8g2.setCursor(0, 10); | |
u8g2.print(int_num); // 打印整数 | |
u8g2.setCursor(0, 40); | |
u8g2.print(float_num); // 打印浮点数(自动四舍五入到小数点后两位) | |
u8g2.sendBuffer(); | |
delay(1000); | |
// 显示中文 | |
u8g2.clearBuffer(); | |
u8g2.setFont(u8g2_font_unifont_t_chinese2); // 设置中文字体 | |
u8g2.setFontDirection(0); // 设置字体方向 | |
u8g2.setCursor(0, 15); | |
u8g2.print("Hello World!"); // 打印英文字符串 | |
u8g2.setCursor(0, 40); | |
u8g2.print("你好世界"); // 显示中文 | |
u8g2.sendBuffer(); | |
delay(1000); | |
} |
五、上传代码
- 在 Arduino IDE 中编写并保存上述代码。
- 选择正确的开发板(Arduino Mega 2560)和端口(在 Wokwi 平台上为虚拟端口)。
- 点击“上传”按钮,将代码上传到 Wokwi 平台上的 Arduino Mega 2560。
六、观察结果
在 Wokwi 平台上,观察 OLED 显示屏上依次显示的字符串、整数、浮点数和中文。确保显示内容与预期一致。
七、注意事项
- 库选择:确保安装了正确的 u8g2 库版本,并根据 OLED 显示屏的型号选择合适的驱动。
- 引脚连接:确保 OLED 显示屏的 SDA 和 SCL 引脚正确连接到 Arduino Mega 2560 的对应引脚。
- 字体设置:显示中文时需要设置合适的中文字体,并确保启用了 UTF-8 编码。
- 代码调试:在上传代码前,仔细检查代码逻辑和语法错误,确保程序能够正常运行。
以下是一个关于在 Wokwi 平台上使用 Arduino Mega 2560 进行 SPI 通信的非常详细的教程:
一、实验准备
-
硬件准备
- Arduino Mega 2560 开发板(在 Wokwi 平台上模拟)
- SPI 从设备(如 SD 卡模块、OLED 显示屏等,这里以 SD 卡模块为例)
- 杜邦线(用于连接)
-
软件准备
- Wokwi 在线仿真平台
- Arduino IDE(用于编写和上传代码)
- SD 库(Arduino IDE 默认已安装,用于 SD 卡操作)
二、SPI 通信原理
SPI(Serial Peripheral Interface,串行外设接口)是一种同步串行通信协议,用于微控制器与各种外设之间的通信。SPI 总线通常包括四条信号线:
- MOSI(Master Out Slave In):主机输出,从机输入。
- MISO(Master In Slave Out):主机输入,从机输出。
- SCK(Serial Clock):串行时钟信号,由主机产生。
- SS(Slave Select)或 CS(Chip Select):从机选择信号,由主机控制。
三、Arduino Mega 2560 SPI 引脚
在 Arduino Mega 2560 上,SPI 引脚通常定义为:
- MOSI:引脚 51
- MISO:引脚 50
- SCK:引脚 52
- SS:引脚 53
四、连接电路
在 Wokwi 平台上,将 SD 卡模块的 MOSI、MISO、SCK 和 CS 引脚分别连接到 Arduino Mega 2560 的对应引脚。通常,SD 卡模块的 CS 引脚连接到 Arduino 的 SS 引脚(引脚 53)。
五、编写代码
以下是一个使用 Arduino Mega 2560 通过 SPI 与 SD 卡模块进行通信的示例代码:
#include <SPI.h>
#include <SD.h>
// 定义 SD 卡模块的 CS 引脚
const int chipSelect = 53;
void setup() {
// 初始化串口通信
Serial.begin(9600);
// 初始化 SPI 通信
SPI.begin();
// 初始化 SD 卡
if (!SD.begin(chipSelect)) {
Serial.println("SD card initialization failed!");
return;
}
Serial.println("SD card initialized.");
// 创建一个文件
File dataFile = SD.open("datalog.txt", FILE_WRITE);
if (dataFile) {
dataFile.println("Hello, SD card!");
dataFile.close();
Serial.println("Data written to file.");
} else {
Serial.println("Failed to open file for writing.");
}
// 读取文件
dataFile = SD.open("datalog.txt");
if (dataFile) {
Serial.println("Reading from file:");
while (dataFile.available()) {
Serial.write(dataFile.read());
}
dataFile.close();
} else {
Serial.println("Failed to open file for reading.");
}
}
void loop() {
// 主循环中不需要执行任何操作
}
cpp复制代码
#include <SPI.h> | |
#include <SD.h> | |
// 定义 SD 卡模块的 CS 引脚 | |
const int chipSelect = 53; | |
void setup() { | |
// 初始化串口通信 | |
Serial.begin(9600); | |
// 初始化 SPI 通信 | |
SPI.begin(); | |
// 初始化 SD 卡 | |
if (!SD.begin(chipSelect)) { | |
Serial.println("SD card initialization failed!"); | |
return; | |
} | |
Serial.println("SD card initialized."); | |
// 创建一个文件 | |
File dataFile = SD.open("datalog.txt", FILE_WRITE); | |
if (dataFile) { | |
dataFile.println("Hello, SD card!"); | |
dataFile.close(); | |
Serial.println("Data written to file."); | |
} else { | |
Serial.println("Failed to open file for writing."); | |
} | |
// 读取文件 | |
dataFile = SD.open("datalog.txt"); | |
if (dataFile) { | |
Serial.println("Reading from file:"); | |
while (dataFile.available()) { | |
Serial.write(dataFile.read()); | |
} | |
dataFile.close(); | |
} else { | |
Serial.println("Failed to open file for reading."); | |
} | |
} | |
void loop() { | |
// 主循环中不需要执行任何操作 | |
} |
六、上传代码
- 在 Arduino IDE 中编写并保存上述代码。
- 选择正确的开发板(Arduino Mega 2560)和端口(在 Wokwi 平台上为虚拟端口)。
- 点击“上传”按钮,将代码上传到 Wokwi 平台上的 Arduino Mega 2560。
七、观察结果
在 Wokwi 平台上,观察串口监视器输出的信息。如果 SD 卡初始化成功,应该能够看到“SD card initialized.”和“Data written to file.”等提示信息。随后,程序会尝试读取文件并打印其内容到串口监视器。
八、注意事项
- 引脚连接:确保 SD 卡模块的引脚正确连接到 Arduino Mega 2560 的对应引脚。
- 库依赖:确保 Arduino IDE 中已安装 SD 库,并且代码中正确包含了相关头文件。
- 文件操作:在 SD 卡上进行文件操作时,确保文件名和路径正确,并且文件存在或可创建。
- 错误处理:在代码中添加适当的错误处理逻辑,以便在初始化失败或文件操作失败时能够输出错误信息。
通过本教程,您可以掌握在 Wokwi 平台上使用 Arduino Mega 2560 进行 SPI 通信的基本方法和技巧。您可以根据需要修改代码以适应不同的 SPI 从设备或应用场景。