arduino使用oled代码_实用!Arduino平台最强大的“显卡”驱动:Adafruit GFX 图形库8000字详细使用指南...
概述
Arduino的Adafruit_GFX庫為我們所有的LCD和OLED顯示屏提供了通用語法和圖形功能集。這使得Arduino示例程序可以很容易地在不同類型的顯示屏之間進行調整,并且任何新特性、性能改進和錯誤修復都將立即應用于我們提供的完整的彩色顯示。
Adafruit_GFX庫可以使用Arduino庫管理器安裝……這是首選的方式。在Arduino IDE“工具”菜單中,選擇“管理庫…”
在搜索欄中輸入“gfx”可以快速找到它:
在這里,也要搜索并安裝Adafruit_BusIO庫(或者…新的Arduino IDE版本自動安裝這個依賴項)。
Adafruit_GFX庫總是與每個特定顯示驅動類型的附加庫一起工作——例如,ST7735 1.8英寸的彩色LCD需要安裝Adafruit_GFX、Adafruit_BusIO和Adafruit_ST7735庫。目前支持下面這些庫:
- RGBmatrixPanel, for our 16x32 and 32x32 RGB LED 矩陣面板。
- Adafruit_TFTLCD, for our 2.8" Arduino的觸屏盾板和TFT觸摸屏。
- Adafruit_HX8340B, for our 2.2" TFT 帶microSD存儲卡的顯示屏。
- Adafruit_ST7735, for our 2.2" TFT 帶microSD存儲卡的顯示屏。
- Adafruit_PCD8544, for the Nokia 5110/3310 單色LCD
- Adafruit-Graphic-VFD-Display-庫, for our 128x64 圖形VFD(真空熒光顯示器)。
Adafruit-SSD1331-OLED-Driver-Library 兼容arduino的0.96" 16位彩色OLED w/帶microSD卡槽。
- Adafruit_SSD1306,用于單色128x64 和128x32 OLED顯示屏。
這些庫是為Arduino用c++編寫的,但是可以通過重寫底層pin訪問功能輕松地移植到任何微控制器。
坐標系和單位
像素—圖像元素,組成數字圖像的塊——通過它們的水平(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對于單色顯示,顏色總是簡單地指定為1 (set)或0 (clear)。set/clear的語義是特定于顯示類型的:像發光的OLED顯示,“set”像素是發光的,而反光的LCD顯示,“set”像素通常是暗的。可能會有例外,但通常您可以期望0 (clear)表示新初始化的顯示的默認背景狀態,無論結果如何。
基本圖形
每個用于特定顯示屏的顯示庫都有自己的構造函數和初始化函數。這些在每個顯示屏類型的單獨教程中都有記錄,或者通常在特定的庫頭文件中有說明。本教程的其余部分將介紹與顯示類型無關的通用圖形函數。
下面的函數描述只是原型—假設顯示對象是由特定于設備的庫根據需要聲明和初始化的。查看每個庫的示例代碼,了解它的實際使用情況。例如,在我們顯示print(1234.56)的地方,你的實際代碼會把對象名稱放在這之前,例如,它可能會讀做screen.print(1234.56)(如果你已經聲明了顯示對象的名稱為:screen)。
- 繪制像素(點)
首先是最基本的像素推送器。你可以調用它,并指定參數:X Y坐標和一種顏色,它會在屏幕上生成一個點:
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 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對、寬度和高度(以像素為單位)以及顏色。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);要創建具有對比輪廓的實線矩形,首先使用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);- 繪制圓角矩形
對于圓角矩形,繪制和填充功能都是可用的。每個矩形都以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);這里還有一個額外的小技巧:因為畫圓函數總是相對于一個中心點像素繪制的,所以最終的圓直徑將總是一個奇數像素。如果需要一個均勻大小的圓(這將在像素之間放置中心點),可以使用一個圓角矩形函數來實現:傳遞相同的寬度和高度(均為偶數),以及剛好為該值一半的角半徑。
- 繪制三角形
對于三角形,同樣有繪制和填充函數。每個函數都需要七個參數:定義三角形的三個角點的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);- 輸出字符和文本
輸出文本有兩個基本的字符串繪制過程。第一個只是針對一個字符。你可以把這個字符放在任何位置并使用任意顏色。只有一種字體(為了節省空間),它應該是5x8像素,但是可以傳遞一個可選的大小參數,根據這個因素來縮放字體(例如size=2將渲染文本為每個字符10x16像素)。它是一個小塊狀,但只有一個字體有助于保持程序代碼的占用空間。
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);從setCursor(x,y)開始,它將把文本的左上角放在您需要的任何位置。 最初將其設置為(0,0)(屏幕的左上角)。 然后使用setTextColor(color)設置文本顏色-默認情況下為白色。 文本通常以“清晰”的形式繪制-每個字符的開放部分均顯示原始背景內容,但是如果您希望文本遮擋下面的內容,則可以將背景色指定為可選的第二個參數tosetTextColor()。 最后,setTextSize(size)將文本的比例乘以給定的整數因子。 在下面,您可以看到1(默認),2和3的比例尺。在較大的尺寸下,它看起來像塊狀的,因為我們僅以單一的簡單字體提供了該庫,以節省空間。
!注意,自定義字體不支持文本背景色。對于這些,您需要確定文本范圍,并在繪制文本之前顯式地繪制一個填充矩形。
在設置好所有內容之后,您可以使用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);這將向顯示器發送一個連續的位塊數據,其中每個“1”位將相應的像素設置為“color”指定的顏色,而跳過每個“0”位。x, y是繪制位圖的左上角,w, h是以像素為單位的寬度和高度。
位圖數據必須使用PROGMEM指令定位在程序內存中。這是一個比較高級的函數,建議初學者稍后再來使用。有關PROGMEM用法的介紹,請參閱Arduino教程。
可以使用一些工具來生成位圖數據。
- 清理或填充屏幕
fillScreen()函數將把整個顯示設置為給定的顏色,刪除所有顯示屏現有的內容:
void fillScreen(uint16_t color);你也可以旋轉你的繪圖。注意,這不會旋轉你已經繪制的內容,但會改變任何新繪制的坐標系統。如果你必須把你的電路板或橫向顯示或倒置來適應一個特定的外殼,這是非常方便的。在大多數情況下,這只需要在setup()函數中執行一次。
我們只能旋轉0,90,180或270度——其他角度的在硬件上是不可能的,而且對于Arduino來說在軟件上計算太費力了。
void setRotation(uint8_t rotation);旋轉參數可以是0、1、2或3。對于屬于Arduino屏蔽的顯示,旋轉值0將顯示設置為豎屏(高)模式,USB插孔位于右上方。旋轉值2也是縱向模式,USB插孔在左下角。旋轉1是橫屏模式,USB插孔在右下方,而旋轉3也是橫屏模式,但USB插孔在左上方。
對于其他的類型的顯示屏,請嘗試所有的4個方向,來弄清楚他們如何結束旋轉,因為對齊將會根據每個顯示器有所不同,一般來說旋轉是逆時針的。
當旋轉時,原點(0,0)會發生變化——其思想是,它應該被安排在顯示器的左上方,以使其他圖形函數具有一致的意義(并與上面所有的函數描述相匹配)。
如果您需要引用屏幕的大小(它會在縱向和橫向模式之間變化),請使用width()和height()。
uint16_t width(); uint16_t height();每個返回對應軸的尺寸(以像素為單位),該尺寸根據顯示器的當前旋轉設置進行了調整。
Adafruit GFX庫的最新版本提供了使用備用字體的能力,除了內置的標準的固定大小和間隔字體之外。包括幾種備用字體,而且還可以添加新的字體。
所包含的字體來自GNU FreeFont項目。字體有三種:“Serif”(讓人聯想到Times New Roman)、“Sans”(讓人聯想到Helvetica或Arial)和“Mono”(讓人聯想到Courier)。每種都有幾種樣式(粗體、斜體等)和大小可供選擇。所包括的字體是位圖格式,而不是可伸縮的矢量,因為它是運行在一個小型微控制器里。
位于Adafruit_GFX的“字體”文件夾中,包含的文件(截至撰寫本文時)如下:
位于Adafruit_GFX的“字體”文件夾中,包含的文件(截至撰寫本文時)如下:
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”等)開頭,然后是樣式(“粗體”、“斜體”、“無”等)、點字體大小(目前提供了9、12、18和24點大小)和“7b”,表示這些文件包含7位字符(ASCII碼“ ”到“~”);8位字體(支持符號和/或國際字符)尚未提供,但可能稍后提供。
- 在Arduino示例程序中使用GFX字體
在#including 后面指示Adafruit_GFX和特定于顯示的庫,包括你計劃在程序中使用的字體文件。例如:
#include <Adafruit_GFX.h> // Core graphics library #include <Adafruit_TFTLCD.h> // Hardware-specific library #include <Fonts/FreeMonoBoldOblique12pt7b.h> #include <Fonts/FreeSerif9pt7b.h>每種字體都會占用一些程序存儲空間;較大的字體通常需要更多的空間。這是一個有限的資源(對于字體數據和所有示例代碼,在Arduino Uno上最大大約為32K),所以要仔細選擇。太大,代碼將拒絕編譯(或者在某些邊緣情況下,可能會編譯,但不會上傳到開發板)。如果出現這種情況,使用更少或更小的字體,或使用標準的內置字體。
在這些these.h文件中有幾個數據結構,包括一個主字體結構,它通常與字體文件同名(去掉 .h)。要為后續的圖形操作選擇一種字體,使用setFont()函數,傳遞該結構的地址,例如:
tft.setFont(&FreeMonoBoldOblique12pt7b);對tft.print()的后續調用,現在將使用這種字體。以前使用內置字體的大多數其他屬性(顏色、大小等)在這里也是類似的。
要返回標準的固定大小的字體,調用setFont(),傳遞NULL或no參數:
tft.setFont();一些文本屬性的行為與這些新字體略有不同。不想破壞與現有代碼的兼容性,“經典”字體繼續像以前一樣工作。
例如,使用經典字體打印時,光標位置標識在字符單元格的左上角,而使用新字體時,光標位置表示后續文本的基線——最下面一行。字符的大小和寬度可能不同,而且不一定是從光標列開始的(如下所示,該字符從光標左邊的一個像素開始,但其他字符可能在它的右邊或上面)。
有一個新字體需要注意的“缺陷”,沒有background顏色選項……你可以設置這個值,但它會被忽略。
這是有意而為之的。
背景顏色特性有時與“經典”字體一起使用,用于用新數據覆蓋舊屏幕內容。這之所以有效,是因為這些字符的大小是一致的;這不適用于比例間距的字體,在這種字體中,可能會有數量不確定的字符重疊在同一區域。字符繪制函數并不是這樣設置的(在AVRs上,它在內存和速度上都是禁止的,而庫仍然支持它)。
使用自定義字體時,可以替換之前繪制的測試:
使用getTextBounds()確定包含字符串的最小矩形,使用fillRect()擦除該區域,然后繪制新的文本:
int16_t x1, y1; uint16_t w, h; tft.getTextBounds(string, x, y, &x1, &y1, &w, &h);getTextBounds需要一個字符串、初始光標的X&Y位置(當前光標的位置不會被改變)以及兩個有符號和兩個無符號16位整數的地址。最后四個值將包含文本所覆蓋區域的左上角和寬度和高度——這些可以作為參數直接傳遞給fillRect()。
在擦除和重繪時,將會導致文本“閃爍”,但這是不可避免的。在同一通道中繪制背景像素的舊方案只會產生一系列新的問題。
或者:
為固定大小的區域創建一個GFXcanvax1對象(屏幕外位圖),在其中繪制自定義文本并使用drawBitmap()復制到屏幕上。
// In global declarations: GFXcanvas1 canvas(128, 32); // 128x32 pixel canvas // In code later: canvas.println("I like cake"); tft.drawBitmap(x, y, canvas, 128, 32, foreground, background); // Copy to screen這將是無閃爍的,但需要更多的RAM(對于上面顯示的128x32像素的畫布,大約512字節),所以在2K的AVR板上并不都是是可用的。Arduino Mega或任何其它32位處理器的開發板應該可以管理。
添加新字體
如果您想要創建庫中沒有包含的新字體尺寸,或者修改全新的字體,我們有一個命令行工具(在“fontconvert”文件夾中)可以實現此目的。它應該可以在許多類似Linux或unix的系統上工作(覆蓋了Pi, Mac OS X,也許是用于Windows的Cygwin,等等)。
構建這個工具需要gcc編譯器和FreeType庫。大多數Linux發行版默認情況下都包含這兩種內容。對于其他人,可能需要安裝開發人員工具并從源代碼下載和構建FreeType。然后在調用“make”之前編輯Makefile以匹配您的設置。
fontconvert需要至少兩個參數:一個字體文件名(例如一個可伸縮的TrueType矢量字體)和一個大小,以點為單位(72點= 1英寸;代碼假設屏幕分辨率類似于Adafruit 2.8” TFT顯示)。輸出應該被重定向到一個。h文件…你可以叫它任何你喜歡人名字,但應具用一定的描述性:
./fontconvert myfont.ttf 12 > myfont12pt7b.hGNU FreeFont文件并不包含在庫存儲庫中,但是很容易下載。或者你可以轉換任何你喜歡的字體。
該文件中分配給字體結構的名稱基于輸入文件名和字體大小,而不是輸出。這就是為什么我建議使用包含字體基名、大小和“7p”的描述性文件名。然后。h文件名和字體結構名稱可以匹配。
生成的.h文件可以復制到Adafruit_GFX/Fonts文件夾中,或者您可以使用sketch→Add file…命令在Arduino示例中導入該文件作為新選項卡。
如果在字體文件夾中,請在#include文件時使用以下語法:
#include <Fonts/myfont12pt7b.h>如果在你的sketch中有一個標簽,使用以下語法:
#include "myfont12pt7b.h"載入圖像
從SD卡(或Adafruit“Express”板上的閃存芯片)加載。bmp圖像是我們大多數彩色顯示器的選項……盡管它不是內置在Adafruit_GFX中,必須單獨安裝。
Adafruit_ImageReader庫處理此任務。可以通過Arduino庫管理器安裝(在Arduino IDE“工具”菜單中,選擇“管理庫…”)在搜索框中輸入“imageread”,庫就很容易找到。
當你在那里,也尋找Adafruit_SPIFlash庫并安裝它類似。
還需要一個庫,但是不能通過庫管理器安裝它。SdFat庫的Adafruit分支需要以. zip文件的形式下載,解壓縮后用Arduino老的安裝庫方式安裝。
鏈接:https://pan.baidu.com/s/1e0F_if19k9J8gz-SFyhpAQ
提取碼:l6o1
使用Adafruit_ImageReader庫
使用這個庫(以及上面的獨立安裝)的語法確實有點奇怪……這是Arduino處理庫方式的副作用。我們故意沒有把它放到Adafruit_GFX中,因為只要提到一個SD卡庫,就會引起該庫相當大的內存需求……即使一個人的程序中根本不用SD卡!大多數圖形項目都是獨立的,不需要從卡上引用文件…不是每個人都需要這個功能。
在Adafruit_ImageReader/examples文件夾中有幾個示例程序。建議您仔細分析這些內容,了解如何在自己的項目中使用庫。
它們都以幾個#includes…開頭
#include <Adafruit_GFX.h> // Core graphics library #include <Adafruit_ILI9341.h> // Hardware-specific library #include <SdFat.h> // SD card & FAT filesystem library #include <Adafruit_SPIFlash.h> // SPI / QSPI flash library #include <Adafruit_ImageReader.h> // Image-reading functions在不同的示例中,其中一行可能會有所不同,這取決于它編寫用來支持的顯示硬件。上面我們看到它和Adafruit_ILI9341顯示屏庫一起使用,這些顯示庫需要特定的套件,FeatherWings 系例板子或轉接板。其他例子參考Adafruit_HX8357, Adafruit_ST7735,或其他彩色TFT或OLED顯示庫…使用你有的正確硬件。
大多數示例都可以在SD卡或Adafruit“Express”板上的小型閃存驅動器上使用。初始化一個方法或另一個方法的代碼略有不同,這些示例將檢查USE_SD_CARD是被#定義來選擇一個方法還是選擇另一個方法。如果您知道您自己的項目只需要在一種或另一種類型上運行,那么您實際上只需要相應的初始化
使用SD卡時,聲明以下兩個全局變量:
SdFat SD; // SD card filesystemAdafruit_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);#elseAdafruit_FlashTransport_SPI flashTransport(SS1, &SPI1);#endif#endifAdafruit_SPIFlash flash(&flashTransport);FatFileSystem filesys;Adafruit_ImageReader reader(filesys); // Image-reader, pass in flash filesys“reader”對象稍后將用于訪問圖像加載函數。
然后…我們按照通常的方式聲明一個顯示對象(大多數例子中稱為“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);這一切都發生在全局變量部分,甚至在setup()函數之前。
現在我們需要在setup()中做一些工作,同樣,SD卡和flash文件系統是不同的……
使用SD卡時,它可能是這樣的:
if(!SD.begin(SD_CS, SD_SCK_MHZ(25))) { // ESP32 requires 25 MHz limitSerial.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(;;);}所有其他代碼現在是相同的,不管使用的是SD卡還是閃存。設置需要一些額外的步驟,但現在一切順利……
在SD(或flash)和TFT的begin()函數被調用后,你可以調用reader.drawBMP()將一個BMP圖像從卡上加載到屏幕上:
ImageReturnCode stat; stat = reader.drawBMP("/purple.bmp", tft, 0, 0);這里可以接收4個參數:
一個“8.3”格式的文件名(你不需要提供一個絕對路徑(前面的“/”),但是在一些前沿的板(比如ESP32)上,SD庫存在一些問題,所以你還是繼續這樣做吧,包括現在這個)。
將繪制圖像的顯示對象(例如“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位彩色BMPs (后續可能會添加更多)。
IMAGE_ERR_MALLOC -無法為操作分配內存(drawBMP()不會生成此錯誤,但其他ImageReader函數可能會)。
你可以選擇調用一個函數來顯示一個基本的診斷消息到串行控制臺,而不是自己處理這些值:
reader.printStatus(stat);如果你需要知道一個BMP圖像的大小而不實際加載它,有bmpDimensions()函數:
int32_t width, height; stat = reader.bmpDimensions("/parrot.bmp", &width, &height);這個函數可以接收3個參數:
文件名,與drawBMP()函數的規則相同。
指向兩個32位整數的指針。成功完成后,它們的內容將被設置為圖像的寬度和高度(以像素為單位)。發生任何錯誤時,這些值都應該被忽略(它們沒有初始化)。
這個函數返回ImageReturnCode,正如上面的drawBMP()函數所解釋的那樣。
在RAM中加載和使用圖像
根據圖像大小和其他因素,從SD卡加載圖像到屏幕可能需要幾秒鐘。小的圖片,可以完全裝進內存,可以載入一次并重復使用。這對于經常使用的圖標或精靈來說非常方便,因為它通常比轉換并將圖像作為數組直接嵌入到代碼中要容易得多……這是一個可怕的過程。
這引入了另一個ImageReader函數和一個新的對象類型Adafruit_Image:
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);這個函數有3個參數:
- 一個顯示對象(例如大多數例子中的“tft”),類似于drawBMP()的工作方式。
- 屏幕上圖像左上角的X和Y坐標,同樣類似于drawBMP()。
我們使用img.draw(tft,…)而不是tft. drawrgbbitmap(…)(或Adafruit_GFX庫中的其他位圖繪制函數),因為我們計劃在圖像文件格式和類型方面增加更多的靈活性。Adafruit_Image對象“understands”已加載的圖像的一些信息,并將自動調用適當的位圖渲染函數,您不必自己處理每個單獨的情況。
如果圖片因為任何原因加載失敗,im .draw()仍然可以被調用,它只是不會做任何事情。但至少這個示例程序不會崩潰。
總結
以上是生活随笔為你收集整理的arduino使用oled代码_实用!Arduino平台最强大的“显卡”驱动:Adafruit GFX 图形库8000字详细使用指南...的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: linux php版本升级_玩转Linu
- 下一篇: stm32呼吸灯程序_学习STM32从点