电子说
概述
用于Arduino的Adafruit_GFX库为我们所有的LCD和OLED显示器提供了通用语法和图形功能集。这使Arduino草图可以轻松地在显示类型之间进行调整,而不必花太多精力……而且任何新功能,性能改进和错误修复将立即应用于我们完整的彩色显示屏产品中。
可以使用 Arduino Library Manager 安装Adafruit_GFX 库,这是首选的现代方法。从Arduino的“草图”菜单中,选择“包含库”,然后选择“管理库…”
在搜索字段中键入“ gfx”以快速找到它:
在这里的同时,还要寻找并安装 Adafruit_ZeroDMA 库。
Adafruit_GFX库始终与每种特定显示类型所独有的附加库一起使用-例如,ST7735 1.8英寸彩色LCD需要安装Adafruit_GFX,Adafruit_ZeroDMA 和 Adafruit_ST7735库,以下库现在以这种方式运行:
RGBmatrixPanel,用于我们的16x32和32x32 RGB LED矩阵面板。
Adafruit_TFTLCD,用于2.8“ TFT LCD触摸屏突破和Arduino的TFT触摸屏。
Adafruit_HX8340B,用于我们的带有microSD的2.2” TFT显示器。
Adafruit_ST7735,用于o具有microSD的1.8英寸TFT显示屏。
Adafruit_PCD8544,用于Nokia 5110/3310单色LCD。
Adafruit-Graphic-VFD-Display-Library,用于我们的128x64图形VFD。
适用于Arduino的Adafruit-SSD1331-OLED-Driver-Library-for-Arduino,带有microSD固定器。
用于单色128x64和128x32 OLED的Adafruit_SSD1306。
这些库是用C ++ for Arduino编写的,但是可以通过重写底层的引脚访问功能轻松地移植到任何微控制器。
旧方法
旧版本的Arduino IDE软件需要手动安装库; Arduino Library Manager尚不存在。如果使用早期版本的Arduino软件,这可能是升级的好时机。否则,本教程将说明如何安装和使用Arduino库。以下是直接下载GFX和ZeroDMA库的链接(使用上面的链接获取对应的特定于显示的库):
下载Adafruit_GFX库
下载Adafruit_ZeroDMA库
坐标系和单位
像素(像素,包括数字图像的像素)通过其水平(X)和垂直(Y)坐标进行寻址。坐标系将原点(0,0)放在左上角,正X向右增加,正Y向下增加。相对于标准的笛卡尔坐标系来说,这是颠倒的,但是在许多计算机图形系统中已经建立了惯例(这回溯到光栅扫描CRT图形的时代,从上到下都是如此)。要使用高的“人像”布局而不是宽的“横向”格式,或者如果物理限制决定了显示器在外壳中的方向,则还可以应用四个旋转设置之一,指示显示器的哪个角代表左上角。
与数学笛卡尔坐标系不同,此处的点具有维度-它们始终是一个完整的整数像素,宽且高。
坐标始终以像素为单位表示;现实世界中没有隐含的比例尺(例如毫米或英寸),显示的图形的尺寸将取决于特定显示器的点距或像素密度。如果您的目标是真实尺寸,则需要缩放坐标以适合。点间距通常可以在设备数据表中找到,或者通过测量屏幕宽度并用该测量结果除以像素数来找到。
对于有颜色的显示器,颜色表示为无符号的16位值。有些显示器在物理上可能比这更多或更少,但是该库使用16位值运行……这些对于Arduino来说很容易使用,同时还为所有不同的显示器提供一致的数据类型。红色,绿色和蓝色等原色成分全部“打包”为单个16位变量,其中最高5位传达红色,中间6位传达绿色,最低5位传达蓝色。这多余的部分分配给绿色,因为我们的眼睛对绿光最敏感。科学!
对于最常见的原色和副色,我们有一个方便的备忘单您可以将其包含在自己的代码中。当然,您可以选择65,536种不同的颜色中的任何一种,但是开始时此基本列表可能是最简单的:
下载:文件
复制代码
// Color definitions
#define BLACK 0x0000
#define BLUE 0x001F
#define RED 0xF800
#define GREEN 0x07E0
#define CYAN 0x07FF
#define MAGENTA 0xF81F
#define YELLOW 0xFFE0
#define WHITE 0xFFFF // Color definitions
#define BLACK 0x0000
#define BLUE 0x001F
#define RED 0xF800
#define GREEN 0x07E0
#define CYAN 0x07FF
#define MAGENTA 0xF81F
#define YELLOW 0xFFE0
#define WHITE 0xFFFF
对于单色(单色)显示器,颜色总是指定为simple1(设置)或0(透明)。设置/清除的语义特定于显示器的类型:对于类似发光的OLED显示器,“设置”像素会变亮,而对于反射LCD显示器,“设置”像素通常会变暗。可能会有例外,但是通常您可以依靠on0(clear)来表示新初始化的显示器的默认背景状态,无论结果如何。
图形基元
每个设备特定的显示库将具有其自己的构造函数和初始化函数。这些内容在每种显示类型的单独教程中都有介绍,或者在特定的库头文件中经常可见。本教程的其余部分介绍了不管显示类型如何都可以使用的通用图形函数。
下面的函数描述仅是 prototypes -假设显示对象被声明并初始化为特定于设备的库需要。查看每个库的示例代码,以实际使用它。例如,在showprint(1234.56)中,您的实际代码会将对象名称放在该名称之前,例如它可能会读到screen.print(1234.56)(如果已使用名称屏幕声明了显示对象)。
绘制像素(点)首先是最基本的像素推动器。您可以使用X,Y坐标和颜色来调用它,它会形成一个点:
下载:文件
复制代码
void drawPixel(uint16_t x, uint16_t y, uint16_t color); void drawPixel(uint16_t x, uint16_t y, uint16_t color);
绘制线条
您还可以绘制带有起点和终点以及颜色的线条:
下载:文件
复制代码
void drawLine(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1, uint16_t color); void drawLine(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1, uint16_t color);
对于水平或垂直线条,有优化的线条绘制功能可避免角度计算:
下载:文件
复制代码
void drawFastVLine(uint16_t x0, uint16_t y0, uint16_t length, uint16_t color);
void drawFastHLine(uint8_t x0, uint8_t y0, uint8_t length, uint16_t color); void drawFastVLine(uint16_t x0, uint16_t y0, uint16_t length, uint16_t color);
void drawFastHLine(uint8_t x0, uint8_t y0, uint8_t length, uint16_t color);
矩形
接下来,可以使用以下步骤绘制和填充矩形和正方形。每个矩形均接受X,Y对,矩形的宽度和高度(以像素为单位)以及color.drawRect()表示矩形的框(轮廓),内部不受影响,而fillRect ()使用给定的颜色填充整个区域:
下载:文件
复制代码
void drawRect(uint16_t x0, uint16_t y0, uint16_t w, uint16_t h, uint16_t color);
void fillRect(uint16_t x0, uint16_t y0, uint16_t w, uint16_t h, uint16_t color); void drawRect(uint16_t x0, uint16_t y0, uint16_t w, uint16_t h, uint16_t color);
void fillRect(uint16_t x0, uint16_t y0, uint16_t w, uint16_t h, uint16_t color);
要创建轮廓鲜明的实心矩形,请先使用fillRect(),然后在其上使用drawRect()。
圆
同样,对于圆,您可以绘制和填充。每个函数均接受X,Y对作为中心点,半径(以像素为单位)和颜色:
下载:文件
复制代码
void drawCircle(uint16_t x0, uint16_t y0, uint16_t r, uint16_t color);
void fillCircle(uint16_t x0, uint16_t y0, uint16_t r, uint16_t color); void drawCircle(uint16_t x0, uint16_t y0, uint16_t r, uint16_t color);
void fillCircle(uint16_t x0, uint16_t y0, uint16_t r, uint16_t color);
圆角矩形
对于具有圆角的矩形,绘制和填充功能均可用。每个都以X,Y,宽度和高度(就像普通矩形一样)开头,然后是拐角半径(以像素为单位),最后是颜色值:
下载:文件
复制代码
void drawRoundRect(uint16_t x0, uint16_t y0, uint16_t w, uint16_t h, uint16_t radius, uint16_t color);
void fillRoundRect(uint16_t x0, uint16_t y0, uint16_t w, uint16_t h, uint16_t radius, uint16_t color); void drawRoundRect(uint16_t x0, uint16_t y0, uint16_t w, uint16_t h, uint16_t radius, uint16_t color);
void fillRoundRect(uint16_t x0, uint16_t y0, uint16_t w, uint16_t h, uint16_t radius, uint16_t color);
额外的技巧:由于圆函数总是相对于中心像素绘制的,因此生成的圆直径将始终是奇数个像素。如果需要一个偶数大小的圆(会将中心点放置在像素之间),则可以使用以下一个圆角矩形函数来实现:传递相同的宽度和高度(即偶数),并拐角半径恰好是此值的一半。
三角形
对于三角形,再次具有绘制和填充功能。每个参数都需要完整的七个参数:定义三角形的三个角点的X,Y坐标,然后是颜色:
下载:文件
复制代码
void drawTriangle(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, uint16_t color);
void fillTriangle(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, uint16_t color); void drawTriangle(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, uint16_t color);
void fillTriangle(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, uint16_t color);
字符和文本
有两种基本的字符串绘制过程可用于添加文本。第一个仅用于单个字符。您可以将此字符放置在任何位置,可以使用任何颜色。只能使用一种字体(以节省空间),它的大小为5x8像素,但可以传递一个可选的size参数,该参数将字体按此因子缩放(例如size = 2将以每个字符10x16像素呈现文本)。有点块状,但只有一种字体有助于减小程序的大小。
下载:文件
复制代码
void drawChar(uint16_t x, uint16_t y, char c, uint16_t color, uint16_t bg, uint8_t size); void drawChar(uint16_t x, uint16_t y, char c, uint16_t color, uint16_t bg, uint8_t size);
文本非常灵活,但操作方式略有不同。无需执行一个过程,而是在单独的函数中设置文本大小,颜色和位置,然后使用print()函数-这使它变得容易,并提供了熟悉的Serial.print()的所有相同的字符串和数字格式设置功能。 )功能!
下载:文件
复制代码
void setCursor(uint16_t x0, uint16_t y0);
void setTextColor(uint16_t color);
void setTextColor(uint16_t color, uint16_t backgroundcolor);
void setTextSize(uint8_t size);
void setTextWrap(boolean w); void setCursor(uint16_t x0, uint16_t y0);
void setTextColor(uint16_t color);
void setTextColor(uint16_t color, uint16_t backgroundcolor);
void setTextSize(uint8_t size);
void setTextWrap(boolean w);
从setCursor(x,y)开始,它将随便放置文本的左上角。最初将其设置为(0,0)(屏幕的左上角)。然后使用setTextColor(color)设置文本颜色-默认情况下为白色。文本通常以“清晰”的形式绘制-每个字符的开放部分显示原始背景内容,但是如果您希望文本遮挡其下方内容,则可以将背景色指定为可选的第二个参数tosetTextColor()。最后,setTextSize(size)将文本的比例乘以给定的整数因子。在下面您可以看到缩放比例分别为1(默认值),2和3。在较大的尺寸下,它看起来像块状的,因为我们只使用一种简单的字体来提供该库,以节省空间。
请注意,自定义字体不支持文本背景色。对于这些,您将需要确定文本范围并在绘制文本之前显式绘制一个填充的矩形。
设置完所有内容后,就可以像使用Serial一样使用print()或println()-例如,要打印字符串,请使用print(“ Hello world”)-这是上面图像的第一行。您还可以将print()用于数字和变量-上面的第二行是print(1234.56)的输出,第三行是print(0xDEADBEEF,HEX)。
默认情况下,长文本行设置为自动“包装”回最左侧的列。要覆盖此行为(因此文本将在显示的右侧溢出,对滚动字幕效果很有用),请使用setTextWrap(false)。可以使用setTextWrap(true)恢复正常的换行行为。
有关最新GFX库中的其他文本功能,请参见“使用字体”页面。
位图
您可以绘制小的单色(单色)位图,非常适合精灵和其他迷你动画或图标:
下载:文件
复制代码
void drawBitmap(int16_t x, int16_t y, uint8_t *bitmap, int16_t w, int16_t h, uint16_t color); void drawBitmap(int16_t x, int16_t y, uint8_t *bitmap, int16_t w, int16_t h, uint16_t color);
这会将连续的位块发送到显示器,其中每个“ 1”位将相应的像素设置为“颜色”,而每个“ 0”位被跳过。 x,y是绘制位图的左上角,w,h是宽度和高度(以像素为单位)。
位图数据必须使用以下命令保存在程序存储器中PROGMEM指令。这是一个有点高级的功能,建议初学者稍后再讲。有关介绍,请参见有关PROGMEM使用的Arduino教程。
这是一个方便的Web工具,用于生成位图-》内存映射
清除或填充屏幕
fillScreen()函数会将整个显示设置为给定的颜色,从而擦除所有现有内容:
下载:文件
复制代码
void fillScreen(uint16_t color); void fillScreen(uint16_t color);
旋转显示
您还可以旋转图形。请注意,这将不旋转您已经绘制的内容,但是它将更改任何新图形的坐标系。如果您必须将板子或显示器侧向或上下翻转以适合特定的机箱,这将非常方便。在大多数情况下,只需在setup()内部执行一次即可。
我们只能旋转0、90、180或270度-硬件上无法进行其他任何操作,因此Arduino难以计算软件
下载:文件
复制代码
void setRotation(uint8_t rotation); void setRotation(uint8_t rotation);
旋转参数可以是0、1、2或3。对于属于Arduino屏蔽的显示器,旋转值0会将显示设置为 portrait (高)模式,USB插孔位于右上方。旋转值2也是纵向模式,USB插孔位于左下方。旋转1是 landscape (宽屏)模式,USB插孔在右下方,而旋转3也是水平,但USB插孔在左上方。
其他显示器,请尝试所有4次旋转以弄清它们最终如何旋转,因为对齐方式会因每个显示器而异,通常旋转会逆时针移动
旋转时,原点(0,0)发生了变化-想法是应该将其布置在显示器的左上方,以使其他图形功能具有一致的意义(并与上面的所有功能描述相匹配)。
如果您需要引用屏幕的大小(将在纵向和横向模式之间更改),使用width()和height()。
下载:文件
复制代码
uint16_t width();
uint16_t height(); uint16_t width();
uint16_t height();
每个返回对应轴的尺寸(以像素为单位),已针对显示器的当前旋转设置进行调整。
使用字体
较新版本的Adafruit GFX库提供了除了内置一个标准的固定大小和等宽字体外还可以使用其他字体的能力。包括在内,还有添加新功能的能力。
所包含的字体源自GNU FreeFontproject。共有三张面孔:“塞里夫(Serif)”(让人联想到时代的新罗马时代),“桑斯”(Sans)(让人联想到Helvetica或Arial)和“莫诺”(Mono)(让人联想到信使)。每种都有几种样式(粗体,斜体等)和尺寸。包含的字体采用位图格式,而不是可缩放的矢量,因为它需要在小型微控制器的限制内工作。
位于Adafruit_GFX内“ Fonts”文件夹内,包括的文件(截至撰写本文时)为:
下载:文件
复制代码
FreeMono12pt7b.h FreeSansBoldOblique12pt7b.h
FreeMono18pt7b.h FreeSansBoldOblique18pt7b.h
FreeMono24pt7b.h FreeSansBoldOblique24pt7b.h
FreeMono9pt7b.h FreeSansBoldOblique9pt7b.h
FreeMonoBold12pt7b.h FreeSansOblique12pt7b.h
FreeMonoBold18pt7b.h FreeSansOblique18pt7b.h
FreeMonoBold24pt7b.h FreeSansOblique24pt7b.h
FreeMonoBold9pt7b.h FreeSansOblique9pt7b.h
FreeMonoBoldOblique12pt7b.h FreeSerif12pt7b.h
FreeMonoBoldOblique18pt7b.h FreeSerif18pt7b.h
FreeMonoBoldOblique24pt7b.h FreeSerif24pt7b.h
FreeMonoBoldOblique9pt7b.h FreeSerif9pt7b.h
FreeMonoOblique12pt7b.h FreeSerifBold12pt7b.h
FreeMonoOblique18pt7b.h FreeSerifBold18pt7b.h
FreeMonoOblique24pt7b.h FreeSerifBold24pt7b.h
FreeMonoOblique9pt7b.h FreeSerifBold9pt7b.h
FreeSans12pt7b.h FreeSerifBoldItalic12pt7b.h
FreeSans18pt7b.h FreeSerifBoldItalic18pt7b.h
FreeSans24pt7b.h FreeSerifBoldItalic24pt7b.h
FreeSans9pt7b.h FreeSerifBoldItalic9pt7b.h
FreeSansBold12pt7b.h FreeSerifItalic12pt7b.h
FreeSansBold18pt7b.h FreeSerifItalic18pt7b.h
FreeSansBold24pt7b.h FreeSerifItalic24pt7b.h
FreeSansBold9pt7b.h FreeSerifItalic9pt7b.h FreeMono12pt7b.h FreeSansBoldOblique12pt7b.h
FreeMono18pt7b.h FreeSansBoldOblique18pt7b.h
FreeMono24pt7b.h FreeSansBoldOblique24pt7b.h
FreeMono9pt7b.h FreeSansBoldOblique9pt7b.h
FreeMonoBold12pt7b.h FreeSansOblique12pt7b.h
FreeMonoBold18pt7b.h FreeSansOblique18pt7b.h
FreeMonoBold24pt7b.h FreeSansOblique24pt7b.h
FreeMonoBold9pt7b.h FreeSansOblique9pt7b.h
FreeMonoBoldOblique12pt7b.h FreeSerif12pt7b.h
FreeMonoBoldOblique18pt7b.h FreeSerif18pt7b.h
FreeMonoBoldOblique24pt7b.h FreeSerif24pt7b.h
FreeMonoBoldOblique9pt7b.h FreeSerif9pt7b.h
FreeMonoOblique12pt7b.h FreeSerifBold12pt7b.h
FreeMonoOblique18pt7b.h FreeSerifBold18pt7b.h
FreeMonoOblique24pt7b.h FreeSerifBold24pt7b.h
FreeMonoOblique9pt7b.h FreeSerifBold9pt7b.h
FreeSans12pt7b.h FreeSerifBoldItalic12pt7b.h
FreeSans18pt7b.h FreeSerifBoldItalic18pt7b.h
FreeSans24pt7b.h FreeSerifBoldItalic24pt7b.h
FreeSans9pt7b.h FreeSerifBoldItalic9pt7b.h
FreeSansBold12pt7b.h FreeSerifItalic12pt7b.h
FreeSansBold18pt7b.h FreeSerifItalic18pt7b.h
FreeSansBold24pt7b.h FreeSerifItalic24pt7b.h
FreeSansBold9pt7b.h FreeSerifItalic9pt7b.h
每个文件名均以面部名称开头(“ FreeMono ”,“ FreeSerif”等),然后是样式(“ Bold”,“ Oblique”,none等),字体大小(以磅为单位)(目前提供9、12、18和24磅)和“ 7b”表示它们包含7位字符(ASCII码“”至“〜”); 尚未提供8位字体(支持符号和/或国际字符),但可能稍后发布。
在Arduino草图中使用GFX字体
在#包含Adafruit_GFX和特定于显示的库之后,包括字体文件( s)您打算在草图中使用。例如:
下载:文件
复制代码
#include // Core graphics library
#include // Hardware-specific library
#include
#include #include // Core graphics library
#include // Hardware-specific library
#include
#include
每种字体占用程序空间;较大的字体通常需要更多空间。这是一种有限的资源(在Arduino Uno上最大为32K,用于字体数据和所有您的素描代码),因此请谨慎选择。太大,代码将拒绝编译(或在某些情况下,可能会编译,但随后将不会上传到开发板上)。如果发生这种情况,请使用较少或较小的字体,或使用标准的内置字体。
在这些.h文件中有几种数据结构,包括一种主要的字体结构,它将通常与字体文件具有相同的名称(减去.h)。要为后续图形操作选择字体,请使用setFont()函数,并传递此结构的地址,例如:
下载:文件
复制代码
tft.setFont(&FreeMonoBoldOblique12pt7b); tft.setFont(&FreeMonoBoldOblique12pt7b);
后续调用tft.print()现在将使用此字体。以前与内置字体(颜色,大小等)一起使用的大多数其他属性在这里的工作方式都与此类似。
要返回标准的固定大小字体,请调用setFont(),传递NULL或没有参数:
下载:文件
复制代码
tft.setFont(); tft.setFont();
这些新字体的某些文本属性的行为略有不同。不想破坏与现有代码的兼容性,“经典”字体仍然像以前一样工作。
例如,而使用经典字体打印时的光标位置标识了左上角《字符单元格的/em》,使用新字体,光标位置指示后续文本的基线(最底行)。字符的大小和宽度可能有所不同,并且不一定从确切的光标列开始(如下所示,此字符从光标的左开始一个像素,但其他字符可能位于光标的右上方
在内置字体和自定义字体之间切换时,该库将根据需要自动将光标位置上下移动6个像素,以沿着相同的基线继续。
一个“陷阱”注意使用新字体:没有“背景”颜色选项…您可以设置此值,但是它将被忽略。
背景颜色功能通常与“经典”字体一起使用,以用新数据覆盖旧屏幕内容。这仅是有效的,因为这些字符大小一致。使用大小可变(且可能重叠)的字符按比例隔开的字体不是明智的选择。
要在使用自定义字体时替换以前绘制的测试,请使用getTextBounds()函数确定包含字符串的最小矩形,使用fillRect()擦除区域,然后绘制新文本。
下载:文件
复制代码
int16_t x1, y1;
uint16_t w, h;
tft.getTextBounds(string, x, y, &x1, &y1, &w, &h); int16_t x1, y1;
uint16_t w, h;
tft.getTextBounds(string, x, y, &x1, &y1, &w, &h);
getTextBounds需要一个字符串,即起始光标X&Y位置(当前光标位置将不会更改),以及两个有符号和两个无符号16位整数的地址。然后,这最后四个值将包含该文本所覆盖区域的左上角以及宽度和高度-然后可以将这些值直接作为参数传递给fillRect()。
不幸的是,这将“闪烁”擦除和重画时,文字是不可避免的。在同一遍中绘制背景像素的旧方案只会带来新的问题。
添加新字体
如果您要创建库中未包含的新字体大小,或改编全新字体,我们提供了一个命令行工具( “ fontconvert”文件夹)。它可以在许多类似Linux或UNIX的系统上运行(Raspberry Pi,Mac OS X,也许还有Windows的Cygwin等)。
构建此工具需要gcc编译器和FreeTypelibrary。大多数Linux发行版默认都包含这两个版本。对于其他用户,您可能需要安装开发人员工具,并从源代码下载并构建FreeType。然后在调用“ make”之前,编辑Makefile以使其与您的设置匹配。
fontconvert 至少需要两个参数:字体文件名(例如可缩放TrueType矢量字体)和大小(以磅为单位)(72磅= 1英寸;代码假定屏幕分辨率类似于Adafruit 2.8英寸TFT显示屏)。输出应重定向到.h文件。..您可以使用任何名称就像,但我会尽量描述一下:
下载:文件
复制代码
。/fontconvert myfont.ttf 12 》 myfont12pt7b.h 。/fontconvert myfont.ttf 12 》 myfont12pt7b.h
GNU FreeFont文件不包含在库中,但易于下载,或者您可以转换大多数喜欢的字体
在此文件中分配给字体结构的名称是基于输入文件名和字体大小,而不是输出。这就是为什么我建议使用描述性的文件名,其中包含字体基本名称,大小和“ 7p”,然后是.hfilename和字体结构名称可以匹配。
可以将生成的.h文件复制到Adafruit_GFX/Fonts文件夹中,也可以使用Sketch→Add File…命令将其作为Arduino草图中的新选项卡导入。
p》
如果在Fonts文件夹中,则在#包括文件时使用以下语法:
下载:文件
复制代码
#include #include
如果草图中的选项卡,请使用以下语法:
下载:文件
复制代码
#include “myfont12pt7b.h” #include “myfont12pt7b.h”
加载图像
从 SD卡(或Adafruit“ Express”板上的闪存芯片)加载.BMP图像是我们大多数彩色显示器的一种选择。..尽管它不是Adafruit_GFX内置的,并且必须单独安装。
Adafruit_ImageReader 库可以完成此任务。可以通过Arduino库管理器安装(草图→包含库→管理库…)。在搜索字段中输入“ imageread”,该库很容易发现:
那是“ imageread”,而不是“ ermahgerd”。
在这里的同时,还要查找 Adafruit_SPIFlash 库并进行类似安装。
还需要一个库,但无法通过库管理器安装。需要将 SdFat 库的 Adafruit分支下载为.ZIP文件,并进行解压缩并安装老式的Arduino库。
下载SdFat(Adafruit fork)Arduino库
Adafruit_ImageReader库
使用该库(以及上面的单独安装)的语法公认有点 peculiar ………这是它的副作用Arduino处理库的方式。我们有目的地并没有将其放入Adafruit_GFX,因为SD卡库的任何提及都将导致该库相当大的内存需求全部 。.. 即使一个人的草图根本不使用SD卡!大多数图形项目都是独立的,并且不引用卡中的文件……并非每个人都需要此功能。
Adafruit_ImageReader/examples文件夹中有几个示例草图。建议您剖析这些内容,以获取有关如何在自己的项目中使用该库的想法。
它们都以几个#includes开头。..
下载:文件
复制代码
#include // Core graphics library
#include // Hardware-specific library
#include // SD card & FAT filesystem library
#include // SPI / QSPI flash library
#include // Image-reading functions #include // Core graphics library
#include // Hardware-specific library
#include // SD card & FAT filesystem library
#include // SPI / QSPI flash library
#include // Image-reading functions
这些示例之一可能会因一个示例而异,具体取决于该示例所支持的显示硬件。在上方,我们看到它与Adafruit_ILI9341显示库配合使用,某些屏蔽罩,FeatherWings或分线板需要该显示库。其他示例引用了Adafruit_HX8357,Adafruit_ST7735或其他彩色TFT或OLED显示库…对您的硬件使用正确的库。
大多数示例都可以在 SD卡,或某些Adafruit“ Express”板上的小型闪存驱动器。用于初始化一个或另一个的代码略有不同,这些示例检查是否已定义 USE_SD_CARD 以选择一种方法与另一种方法。如果您知道一个事实您自己的项目只需要在一种或另一种类型上运行,那么您实际上只需要进行相应的初始化即可。
对于SD卡,这两个全局变量声明为:
下载:文件
复制代码
SdFat SD; // SD card filesystem
Adafruit_ImageReader reader(SD); // Image-reader object, pass in SD filesys SdFat SD; // SD card filesystem
Adafruit_ImageReader reader(SD); // Image-reader object, pass in SD filesys
对于Flash文件系统,有一些特殊的声明可以帮助我们在不同的Express板上定位Flash设备,然后声明三个全局变量:
下载:文件
复制代码
// SPI or QSPI flash filesystem (i.e. CIRCUITPY drive)
#if defined(__SAMD51__) || defined(NRF52840_XXAA)
Adafruit_FlashTransport_QSPI flashTransport(PIN_QSPI_SCK, PIN_QSPI_CS,
PIN_QSPI_IO0, PIN_QSPI_IO1, PIN_QSPI_IO2, PIN_QSPI_IO3);
#else
#if (SPI_INTERFACES_COUNT == 1)
Adafruit_FlashTransport_SPI flashTransport(SS, &SPI);
#else
Adafruit_FlashTransport_SPI flashTransport(SS1, &SPI1);
#endif
#endif
Adafruit_SPIFlash flash(&flashTransport);
FatFileSystem filesys;
Adafruit_ImageReader reader(filesys); // Image-reader, pass in flash filesys // SPI or QSPI flash filesystem (i.e. CIRCUITPY drive)
#if defined(__SAMD51__) || defined(NRF52840_XXAA)
Adafruit_FlashTransport_QSPI flashTransport(PIN_QSPI_SCK, PIN_QSPI_CS,
PIN_QSPI_IO0, PIN_QSPI_IO1, PIN_QSPI_IO2, PIN_QSPI_IO3);
#else
#if (SPI_INTERFACES_COUNT == 1)
Adafruit_FlashTransport_SPI flashTransport(SS, &SPI);
#else
Adafruit_FlashTransport_SPI flashTransport(SS1, &SPI1);
#endif
#endif
Adafruit_SPIFlash flash(&flashTransport);
FatFileSystem filesys;
Adafruit_ImageReader reader(filesys); // Image-reader, pass in flash filesys
“阅读器”对象稍后将用于访问图像加载功能。
然后……我们以通常的方式声明一个显示对象(在大多数示例中称为“ tft”)……例如,使用Arduino的2.8英寸TFT触摸屏,它是:
下载:文件
复制代码
#define SD_CS 4 // SD card select pin
#define TFT_CS 10 // TFT select pin
#define TFT_DC 9 // TFT display/command pin
Adafruit_ILI9341 tft = Adafruit_ILI9341(TFT_CS, TFT_DC); #define SD_CS 4 // SD card select pin
#define TFT_CS 10 // TFT select pin
#define TFT_DC 9 // TFT display/command pin
Adafruit_ILI9341 tft = Adafruit_ILI9341(TFT_CS, TFT_DC);
这一切都发生在全局变量部分,甚至在setup()函数之前。
现在我们需要在setup()中做一些工作,而且SD卡和Flash还是不同的文件系统…
要使用SD卡,可能看起来像这样:
下载:文件
复制代码
if(!SD.begin(SD_CS, SD_SCK_MHZ(25))) { // ESP32 requires 25 MHz limit
Serial.println(F(“SD begin() failed”));
for(;;); // Fatal error, do not continue
} if(!SD.begin(SD_CS, SD_SCK_MHZ(25))) { // ESP32 requires 25 MHz limit
Serial.println(F(“SD begin() failed”));
for(;;); // Fatal error, do not continue
}
此示例提供了一些非常基本的错误处理…检查返回值SD.begin()的状态并在出现问题时将消息打印到串行监视器。
使用闪存文件系统需要两个步骤:
下载:文件
复制代码
if(!flash.begin()) {
Serial.println(F(“flash begin() failed”));
for(;;);
}
if(!filesys.begin(&flash)) {
Serial.println(F(“filesys begin() failed”));
for(;;);
} if(!flash.begin()) {
Serial.println(F(“flash begin() failed”));
for(;;);
}
if(!filesys.begin(&flash)) {
Serial.println(F(“filesys begin() failed”));
for(;;);
}
现在,无论使用SD卡还是闪存,所有其他代码都相同。要么/或设置都需要一些额外的步骤,但是现在一切都很顺利……
之后SD(或闪存)和TFT的begin()函数已被调用,然后可以调用reader.drawBMP()将从卡中加载BMP图像到屏幕:
下载:文件
复制代码
ImageReturnCode stat;
stat = reader.drawBMP(“/purple.bmp”, tft, 0, 0); ImageReturnCode stat;
stat = reader.drawBMP(“/purple.bmp”, tft, 0, 0);
这接受四个参数:
“ 8.3”格式的文件名(您不需要 提供绝对路径(前导“/”),但是SD库在某些方面存在一些问题边缘板(如ESP32),因此请继续使用,以备不时之需。)
将在其中绘制图像的显示对象(例如, “ tft”)。 这是前面提到的怪异语法……因为原因,它不是tft.drawBMP(),而是reader.drawBMP(tft)。
X和Y坐标在顶部定位图像的左上角(此位置不必在屏幕范围内……库将在加载图像时裁剪图像)。 0,0将在左上角绘制图像。..因此,如果图像尺寸与屏幕尺寸匹配,它将填充整个屏幕。
此函数返回类型为ImageReturnCode,您可以忽略或使用它来提供某些诊断功能。可能的值为:
IMAGE_SUCCESS -图像加载成功(或完全从屏幕上剪切下来,因为没有错误,仍被认为是“成功”)。
IMAGE_ERR_FILE_NOT_FOUND-无法打开请求的文件(检查拼写,确认卡上确实存在文件,确保文件符合“ 8.3”文件命名约定(例如“ filename.bmp”) )。
IMAGE_ERR_FORMAT -不支持的图像格式。目前仅支持未压缩的24位彩色BMP (随着时间的推移,可能会添加更多)
IMAGE_ERR_MALLOC -无法为操作分配内存(drawBMP()不会生成此错误,但其他ImageReader函数可能会)。
您可以选择调用一个函数以向串行控制台显示基本诊断消息,而不必自己处理这些值:
下载:文件
复制代码
reader.printStatus(stat); reader.printStatus(stat);
I如果您需要了解BMP图片的 size 而不实际加载它,有bmpDimensions()函数:
下载:文件
复制代码
int32_t width, height;
stat = reader.bmpDimensions(“/parrot.bmp”, &width, &height); int32_t width, height;
stat = reader.bmpDimensions(“/parrot.bmp”, &width, &height);
这接受三个参数:
文件名,与drawBMP()函数的规则相同。
指针指向两个 32位整数。成功完成后,它们的内容将设置为以像素为单位的图像宽度和高度。发生任何错误时,这些值都应忽略(不进行初始化)。
此函数返回一个ImageReturnCode,如上面的drawBMP()函数所述。
在RAM中加载和使用图像
取决于图像大小和其他因素,将图像从SD卡加载到屏幕可能需要几秒钟。小图像……那些完全可以放入RAM的图像……可以一次加载并重复使用。这对于经常使用的图标或sprite可能很方便,因为它通常比直接将图像作为数组转换并嵌入到数组中更容易……这是一个可怕的过程。
这引入了另一个ImageReader函数以及一个新功能。对象类型,Adafruit_Image:
下载:文件
复制代码
Adafruit_Image img;
stat = reader.loadBMP(“/wales.bmp”, img); Adafruit_Image img;
stat = reader.loadBMP(“/wales.bmp”, img);
loadBMP()接受两个参数:
文件名,规则与以前的功能相同。
一个Adafruit_Image对象。这种类型比GFX库中一些绘图功能使用的位图稍微灵活一些。
这将返回一个ImageReturnCode,如前所述。如果图像太大而无法容纳在可用RAM中,则将返回IMAGE_ERR_MALLOC的值。彩色图像每像素需要两个字节…例如,一个100x25像素图像将需要100 * 25 * 2 = 5,000字节RAM。
成功后,img对象将图像包含在RAM中
loadBMP()函数仅在具有大量RAM的微控制器(例如Adafruit的“ M0”和“ M4”板或ESP32)上有用。像Arduino Uno这样的小型设备无法切割。在具有很小图像的Arduino Mega上,边缘可能有用。
加载后,使用img.draw()函数在屏幕上显示图像:
下载:文件
复制代码
img.draw(tft, x, y); img.draw(tft, x, y);
这接受三个参数:
显示对象(例如,大多数示例中为“ tft”) ,类似于drawBMP()的工作方式。
屏幕上图像左上角的X和Y坐标,再次类似于drawBMP()。
我们使用img.draw(tft,…)而不是tft.drawRGBBitmap(…)(或Adafruit_GFX库中的其他位图绘制函数),因为将来我们计划在图像文件格式和类型方面增加更多灵活性。 Adafruit_Image对象对所加载的图像有一些“了解”,并会自动调用相应的位图渲染功能,您不必自己处理每种情况。
如果图像由于某种原因无法加载,仍然可以调用img.draw(),它将不执行。但是至少草图不会崩溃。
责任编辑:wv
全部0条评论
快来发表一下你的评论吧 !