概述
用于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
-
Arduino
+關注
關注
187文章
6464瀏覽量
186681
發布評論請先 登錄
相關推薦
評論