TJpgDec簡介
TJpgDec是一個為小型嵌入式系統高度優化的創建JPEG圖像的解碼軟件。它工作時占用的內存非常低,以便它可以集成到微控芯片,如AVR, 8051, PIC, Z80, Cortex-M0等。不依賴于具體的硬件平臺,使用ANSI-C編寫,易于使用的操作模式,完全可重入的體系結構,非常小的內存占用(獨立于圖像尺寸的3KB SRAM。3.5-8.5KB的代碼空間)。輸出格式可以是縮放比例為1/1、1/2、1/4或1/8可選,像素格式可以是RGB888或RGB565。
TJpgDec組件是一個免費開放的軟件,可用于教育、科研和商業開發。用戶可以在包含TJpgDec的個人項目和商業產品中改寫和重新發布該組件。
TJpgDec組件在用戶的應用中僅需要調用2個API。
jd_prepare() - 準備解碼JPEG圖像
jd_prepare
分析JPEG數據并創建一個解碼對象用于隨后的解碼過程。
jd_prepare
函數是JPEG解碼過程的第一階段。它接收用戶傳入的數據流(需要通過傳入的回調函數操作數據流),分析JPEG圖像和創建解碼參數表。函數成功后,會話準備好在jd_decomp
函數解碼JPEG圖像。應用程序可以參考JPEG解碼對象中存儲的尺寸大小。這個信息將用于在后續的解碼階段配置輸出設備和參數。
JRESULT jd_prepare (
JDEC* jdec, /* Pointer to blank decompression object */
UINT(*infunc)(JDEC*,BYTE*,UINT), /* Pointer to input function */
void* work, /* Pointer to work area */
UINT sz_work, /* Size of the work area */
void* device /* Device identifier for the session */
);
輸入參數:
jdec
- 輸出,一個空的JDEC結構體對象,初始化一個解碼對象。需要用戶先創建JPEC對象的內存,然后本函數在執行過程中會向其中填充有效信息,這個解碼對象也將用于后續的解碼操作。infunc
- 輸入,指定一個為解碼算法提供輸入數據的回調函數。實際上,這個方法也是關聯具體平臺的,不僅僅是提供一個讀數的方法,更確切是提供一個具體的數據流。這個infunc函數也是需要在具體平臺適配過程中需要用戶自行實現的。具體寫法可以看原作者給的應用說明,也可以參見本文中的基于具體微控制器平臺的實現。work
- 輸入,指定一個內存塊,給解碼器內部運行算法的工作空間。sz_work
- 輸入,指定work
參數指定工作空間的 size,以字節為單位。TJpgDec至多需要3092字節的工作區域,這依賴于JPEG圖像的內置參數表。通常情況下是3092字節工作區域。device
- 輸入,指定用戶自定義的會話設備標識。它保存在解碼對象jdec
的字段device
中。它可以用于I/O函數去識別當前會話。當I/O device固定在project或者不需要這個功能,設置為NULL并忽略它。device參數可以作為回調函數中訪問綁定硬件的傳參。
返回值:
JDR_OK
- 函數執行成功,且編碼對象是有效的。JDR_INP
- 一個錯誤發生在input函數,由于硬件錯誤或者流終止。JDR_MEM1
- 工作空間不足解碼這個JPEG圖像。JDR_MEM2
- 工作空間不足解碼這個JPEG圖像。可能更小。JDR_PAR
- 參數錯誤。傳入工作空間的指針為NULL。JDR_FMT1
- 數據格式錯誤。JPEG數據損壞。JDR_FMT2
- 格式正確,但不支持。也許是一個灰度圖像。JDR_FMT3
- 不支持JPEG標準,也許是一個后續版本的JPEG圖像。
jd_decomp() - 執行解碼JPEG圖像
jd_decomp()
函數解碼JPEG圖像并輸出RGB
數據。
jd_decomp()
是JPEG解碼過程的第二階段。它進一步執行解碼JPEG圖像的過程,并通過用戶定義的輸出函數輸出數據,但同時也繼續使用在jd_prepare()
傳入的輸入數據流的函數。在它之后,解碼對象將不在有效。
在解碼時指定的比例因子,它將JPEG圖像按1/2、1/4或1/8比例縮放尺寸。例如,當解碼一個1024x768大小JPEG圖像在1/4比例,它將輸出256x192大小。相比不縮放,1/2和1/4的縮放由于求均值,解碼速度略有下降。但是1/8縮放相比不縮放是2-3倍的速度輸出,因為每個塊IDCT和求均值可以跳過,這一特點適合創建縮略圖。
JRESULT jd_decomp (
JDEC* jdec, /* Pointer to valid decompressor object */
UINT(*outfunc)(JDEC*,void*,JRECT*), /* Pointer to output function */
BYTE scale /* Scaling factor */
);
輸入參數:
jdec
- 輸入,指定有效的解碼對象。其實就是之前在jd_prepare()函數中準備好的JDEC對象。outfunc
- 輸入,指定用戶定義的JPEG解碼過程輸出數據流的回調函數。jd_decomp()
調用這個函數去輸出解碼JPEG圖像的RGB形式數據流。具體寫法可以看原作者給的應用說明,也可以參見本文中的基于具體微控制器平臺的實現。scale
- 輸入,指定輸出縮放值N。輸出圖像的縮小比例為1/2^N
(N = 0 to 3)。當不使用縮放功能時(JD_USE_SCALE == 0),可以指定為0。
返回值
JDR_OK
- 函數執行成功。JDR_INTR
- 解碼過程在輸出函數中斷。JDR_INP
- 一個錯誤發生在input函數,由于硬件錯誤或者流終止。JDR_PAR
- 參數錯誤。給定的縮放值無效。JDR_FMT1
- 數據格式錯誤。JPEG數據損壞。
tjpgdcnf.h - 配置文件
早期版本的TjpgDec源碼中并沒有tjpgdcnf.h
文件。我試著找了一下tjpgdec項目的changelog,沒有直接找到關于版本更新的詳情內容,但是遍歷了到目前為止tjpgd所有發布版本的軟件包,確定了tjpgdcnf.h首次出現的版本是2021年5月8日發布的R0.02版本。在這個文件中,更細化地提取了一些對TJpgDec軟件配置和裁剪的一些選項,在當前最新的R0.03版本中源碼如下(原作者非常貼心地注釋了可用的選項和對應的解釋):
/*----------------------------------------------*/
/* TJpgDec System Configurations R0.03 */
/*----------------------------------------------*/
#define JD_SZBUF 512
/* 指定在輸入數據流中每次讀取的字節數,512、1024、2048等等均可。*/
#define JD_FORMAT 0
/* Specifies output pixel format.
/ 0: RGB888 (24-bit/pix)
/ 1: RGB565 (16-bit/pix)
/ 2: Grayscale (8-bit/pix)
*/
#define JD_USE_SCALE 1
/* Switches output descaling feature.
/ 0: Disable
/ 1: Enable
*/
#define JD_TBLCLIP 1
/* Use table conversion for saturation arithmetic. A bit faster, but increases 1 KB of code size.
/ 0: Disable
/ 1: Enable
*/
#define JD_FASTDECODE 0
/* Optimization level
/ 0: Basic optimization. Suitable for 8/16-bit MCUs.
/ 1: + 32-bit barrel shifter. Suitable for 32-bit MCUs.
/ 2: + Table conversion for huffman decoding (wants 6 < < HUFF_BIT bytes of RAM)
*/
針對使用ARM Cortex-MC1處理器內核和FSMC驅動的16位并口屏幕的MM32F5微控制器,這里需要改寫:
#define JD_FORMAT 1 /* 1: RGB565 (16-bit/pix) */
#define JD_FASTDECODE 1 /* 1: + 32-bit barrel shifter. Suitable for 32-bit MCUs. */
注意,這里似乎還藏了一個彩蛋。同時支持RGB888、RGB565和灰度圖像,這意味著TJpgDec軟件內部的源碼內部包含了原始RGB888轉RGB565和灰度圖像的算式,這個在純輸出的GUI應用開發中講會用到,屆時可以直接復制驗證過的代碼片段,而不用我們再自行編寫調試啦。
關于TJpgDec的軟件許可證
這是一份包含在源代碼TJpgDec中的許可聲明。
/*----------------------------------------------------------------------------/
/ TJpgDec - Tiny JPEG Decompressor R0.xx (C)ChaN, 20xx
/-----------------------------------------------------------------------------/
/ The TJpgDec is a generic JPEG decompressor module for tiny embedded systems.
/ This is a free software that opened for education, research and commercial
/ developments under license policy of following terms.
/
/ Copyright (C) 20xx, ChaN, all right reserved.
/
/ * The TJpgDec module is a free software and there is NO WARRANTY.
/ * No restriction on use. You can use, modify and redistribute it for
/ personal, non-profit or commercial products UNDER YOUR RESPONSIBILITY.
/ * Redistributions of source code must retain the above copyright notice.
/
/----------------------------------------------------------------------------*/
TJpgDec許可是BSD風格的,但存在一些差異。因為TJpgDec是嵌入式項目,對以二進制形式的分發,如嵌入式代碼,hex文件或二進制庫,未指定以增加其可用性。分發的文檔不強制包含關于tjpgdec及其授權文件。TJpgDec是基于GNU GPL兼容的項目。當有任何修改下重新分發,許可證也可以改為GNU GPL或BSD許可證。
應用接口解析
TJpgDec組件的移植過程僅需要實現兩個函數,輸入數據和輸出數據。但從嚴格意義上講,這兩個函數都只是以約定的方式將數據流傳入到TJpgDec組件,或者從TJpgDec組件中傳出到指定存儲空間,因為完全是內存到內存的操作,不涉及到任何與具體硬件平臺相關綁定關系,所以也算不上移植。甚至在原作者的用戶使用文檔中,也是以應用筆記(TJpgDec Application Note)作為文檔的名字,而不是移植指南。
原作者在《TJpgDec Module Application Note》中講述了在應用中使用TJpgDec組件的操作步驟。建議用戶先試著構建和運行原作者提供的示例程序。
解碼會話分為兩個階段。第一階段是分析JPEG圖像,第二階段是解碼。
- 初始化輸入流。(例如打開一個文件)
- 分配JPEG解碼對象和工作區域。
- 調用
jd_prepare()
指定輸入數據流,并執行分析和準備壓縮的JPEG圖像。 - 使用解碼對象中的圖像信息初始化輸出設備。
- 調用
jd_decomp()
指定輸出數據流,解碼JPEG圖像并輸出。
圖x 在應用中使用TJpgDec組件的調用關系圖
這是原作者提供的一段參考源碼,描述了如何使用TJpgDec模塊。
/*------------------------------------------------*/
/* TJpgDec Quick Evaluation Program for PCs */
/*------------------------------------------------*/
#include < stdio.h >
#include < string.h >
#include "tjpgd.h"
/* 用戶定義設備標識 */
typedefstruct {
FILE *fp; /* 用于輸入函數的文件指針 */
BYTE *fbuf; /* 用于輸出函數的幀緩沖區的指針 */
UINT wfbuf; /* 幀緩沖區的圖像寬度[像素] */
} IODEV;
/*------------------------------*/
/* 用戶定義input funciton */
/*------------------------------*/
UINT in_func (JDEC* jd, BYTE* buff, UINT nbyte)
{
IODEV *dev = (IODEV*)jd- >device; /* Device identifier for the session (5th argument of jd_prepare function) */
if (buff) {
/* 從輸入流讀取一字節 */
return (UINT)fread(buff, 1, nbyte, dev- >fp);
} else {
/* 從輸入流移除一字節 */
return fseek(dev- >fp, nbyte, SEEK_CUR) ? 0 : nbyte;
}
}
/*------------------------------*/
/* 用戶定義output funciton */
/*------------------------------*/
UINT out_func (JDEC* jd, void* bitmap, JRECT* rect)
{
IODEV *dev = (IODEV*)jd- >device;
BYTE *src, *dst;
UINT y, bws, bwd;
/* 輸出進度 */
if (rect- >left == 0) {
printf("r%lu%%", (rect- >top < < jd- >scale) * 100UL / jd- >height);
}
/* 拷貝解碼的RGB矩形范圍到幀緩沖區(假設RGB888配置) */
src = (BYTE*)bitmap;
dst = dev- >fbuf + 3 * (rect- >top * dev- >wfbuf + rect- >left); /* 目標矩形的左上 */
bws = 3 * (rect- >right - rect- >left + 1); /* 源矩形的寬度[字節] */
bwd = 3 * dev- >wfbuf; /* 幀緩沖區寬度[字節] */
for (y = rect- >top; y <= rect- >bottom; y++) {
memcpy(dst, src, bws); /* 拷貝一行 */
src += bws; dst += bwd; /* 定位下一行 */
}
return1; /* 繼續解碼 */
}
/*------------------------------*/
/* 主程序 */
/*------------------------------*/
int main (int argc, char* argv[])
{
void *work; /* 指向解碼工作區域 */
JDEC jdec; /* 解碼對象 */
JRESULT res; /* TJpgDec API的返回值 */
IODEV devid; /* 用戶定義設備標識 */
/* 打開一個JPEG文件 */
if (argc < 2) return-1;
devid.fp = fopen(argv[1], "rb");
if (!devid.fp) return-1;
/* 分配一個用于TJpgDec的工作區域 */
work = malloc(3500);
/* 準備解碼 */
res = jd_prepare(&jdec, in_func, work, 3500, &devid);
if (res == JDR_OK) {
/* 準備好解碼。圖像信息有效 */
printf("Image dimensions: %u by %u. %u bytes used.n", jdec.width, jdec.height, 3100 - jdec.sz_pool);
devid.fbuf = malloc(3 * jdec.width * jdec.height); /* 輸出圖像的幀緩沖區(假設RGB888配置) */
devid.wfbuf = jdec.width;
res = jd_decomp(&jdec, out_func, 0); /* 開始1/1縮放解碼 */
if (res == JDR_OK) {
/* 解碼成功。你在這里已經解碼圖像到幀緩沖區 */
printf("rOK n");
} else {
printf("Failed to decompress: rc=%dn", res);
}
free(devid.fbuf); /* 釋放幀緩沖區 */
} else {
printf("Failed to prepare: rc=%dn", res);
}
free(work); /* 釋放工作區域 */
fclose(devid.fp); /* 關閉JPEG文件 */
return res;
}
這里詳細說明兩個回調函數的寫法。
in_func() - 輸入數據流回調函數
用戶需要在輸入數據流的回調函數in_func()
中讀取JPEG數據存入傳參指針buff
中。在jd_prepare()函數中傳入數據流到TJpgDec模塊。
UINT in_func (
JDEC* jdec, /* Pointer to the decompression object */
BYTE* buff, /* Pointer to buffer to store the read data */
UINT ndata /* Number of bytes to read */
);
輸入參數:
jdec
- 輸入,當前服務的jdec對象的handler。通過這個handler可以訪問到當前服務的jdec對象的所有資源。buff
- 輸出,一塊內存區,從介質中讀取指定數量的字節數據后,存放到這塊內存區,交給調用者。但如果buff
的值為NULL
,就表示跳過ndata
參數指定數量的數據。ndata
- 輸入,調用者希望從輸入數據流中讀到的字節數量,即buff
的大小。或者當buff
的值為NULL
時,此處參數指定為需要在輸入數據流中跳過讀取的字節數量。
實際上,這里還有一個隱形的參數,即出現在tjpgdcnf.h文件中的JD_SZBUF
,它約定的應該是每次從輸入流讀取的最大字節數量,即ndata
的最大值。
返回值:
- 返回實際讀取或移除的字節數。若返回0,
jd_prepare()
和jd_decomp()
函數將終止并返回JDR_INP
。
out_func() - 輸出數據流回調函數
用戶可指定解碼出來的像素輸出到具體的存儲區,這個存儲區可以是一塊內存,或者映射到顯存的地址空間。用戶需要在out_func()
函數內部,在rect
參數執行的矩形區域中填充bitmap
參數指定的像素信息。
UINT out_func (
JDEC* jdec, /* Pointer to the decompression object */
void* bitmap, /* RGB bitmap to be output */
JRECT* rect /* Rectangular region to output */
);
輸入參數:
jdec
- 輸入,當前服務的jdec對象的handler。通過這個handler可以訪問到當前服務的jdec對象的所有資源。bitmap
- 像素數據流。是按照tjpgdcnf.h
文件中JD_FORMAT
選項指定的格式組織,可以是3字節表示的一個像素的RGB888格式,也可以是2字節表示一個像素的RGB565格式等。第一個像素是rect指定矩形區域的左上角,從左到右,從上到下,最后一個像素是右下角的位置。rect
- 輸入,執行顯示像素區域的矩形。JRECT
類型的結構體中,有Left
、Right
、Top
、Bottom
四個字段,指示當前解碼輸出的矩形區域。實際上,這個矩形的大小從1x1到16x16不等,取決于圖像的裁剪、縮放和采樣因子(JPEG信息)。
返回值:
- 通常返回1,以便TJpgDec繼續解碼過程。當它返回0,
jd_decomp
函數終止并返回JDR_INTR
。
輸入數據流可能時常發生變化,因為要讀取不同的jpg圖像文件。輸出數據流也是在應用中根據需要變化的,只不過因為在大多數微控制器應用中,顯示設備通常只有一個,所以統一輸出到這個顯示設備對應的顯存中。有一些對于輸出體驗有要求的場景,需要輸出到特定的存儲空間,為了進行二次渲染,或者多緩沖區的應用,此時就需要在應用根據程序執行的情況動態切換輸出了區域了。
關于工作區和幀緩沖區
在應用程序中調用jd_prepare()函數時,需要為TJpgDec指定一塊工作區,作為TJpgDec在內部運行解碼算法的臨時空間。TJpgDec至少需要3100字節用于JPEG圖像,這取決于解碼JPEG圖像使用怎樣的參數。3100字節是在默認輸入緩存(JD_SZBUF == 512)下的最大內存需求,并隨JD_SZBUF
和JD_FASTDECODE
的配置值變化。JD_SZBUF
定義每次從輸入流中讀取多少字節。TJpgDec
對齊每個讀請求緩沖區大小,512, 1024, 2048... 字節是從存儲設備讀取的理想大小。
在樣例代碼中,原作者使用了動態分配的內存作為工作區,這對于擁有海量存儲資源和完善內存管理機制的PC環境是合適的。但在資源受限的嵌入式系統平臺上,使用靜態內存會是更穩妥的選擇。
另外,樣例代碼中使用了幀緩沖區(devid結構體變量中的fbuf指定內存區,wfbuf指定寬度),在應用程序和out_func回調函數之間傳遞像素數據,但實際看起來有點莫名其妙。此處了解到以矩形方式傳送像素矩陣的模式之后,用戶也可以自行簡化代碼。
在MM32F5微控制器上應用
在MM32F5微控制器上適配TJpgDec時,我使用了FatFs文件系統作為JPEG圖像文件的來源,使用靜態內存作為工作區,簡化了對“幀緩沖區”的使用,并使用LCD模塊作為輸出設備。最終實現在微控制器系統中啟用JPEG圖像解碼器的功能。
在包含TJpgDec組件的plus-f5270_image_fatfs_tjpgdec_basic_mdk
工程中,我將打開圖像文件并解碼的過程封裝成bool app_fs_display_jpg_file(char * filepath)
函數,如此,在主循環中遍歷到文件系統中的jpg文件后,可以直接使用其文件路徑打開文件并顯示像素信息到LCD屏上。這個函數中,就使用到了靜態內存分配的工具區域app_tjpgdec_work_buff
。從代碼中可以看出,代碼的內容被簡化了不少。
#define APP_TJPGDEC_WORK_BUFF_SIZE 3500
uint8_t app_tjpgdec_work_buff[APP_TJPGDEC_WORK_BUFF_SIZE];
/* display a jpg file with its full filepath. */
bool app_fs_display_jpg_file(char * filepath)
{
JRESULT res; /* Result code of TJpgDec API */
JDEC jdec; /* Decompression object */
//void *work; /* Pointer to the work area */
//size_t sz_work = 3500; /* Size of work area */
IODEV devid; /* Session identifier */
FRESULT fres;
/* Initialize input stream */
devid.fp = &app_fs_file;
fres = f_open(devid.fp, filepath, FA_READ);
if (fres != FR_OK)
{
return-1;
}
/* Prepare to decompress */
//work = (void*)malloc(sz_work);
//res = jd_prepare(&jdec, in_func, work, sz_work, &devid);
res = jd_prepare(&jdec, in_func, app_tjpgdec_work_buff, APP_TJPGDEC_WORK_BUFF_SIZE, &devid);
if (res == JDR_OK)
{
/* It is ready to dcompress and image info is available here */
//printf("Image size is %u x %u.n%u bytes of work ares is used.n", jdec.width, jdec.height, sz_work - jdec.sz_pool);
/* Initialize output device */
//devid.fbuf = (uint8_t*)malloc(N_BPP * jdec.width * jdec.height); /* Create frame buffer for output image */
//devid.wfbuf = jdec.width;
res = jd_decomp(&jdec, out_func, 0); /* Start to decompress with 1/1 scaling */
if (res == JDR_OK)
{
/* Decompression succeeded. You have the decompressed image in the frame buffer here. */
printf("rDecompression succeeded.n");
} else {
printf("jd_decomp() failed (rc=%d)n", res);
}
//free(devid.fbuf); /* Discard frame buffer */
}
else
{
printf("jd_prepare() failed (rc=%d)n", res);
}
//free(work); /* Discard work area */
f_close(devid.fp); /* Close the JPEG file */
returntrue;
}
同時,在實現輸入輸出數據流的回調函數時,也有一些考究。
在實現輸入數據流的回調函數的過程中,由于使用了FatFs文件系統,其中很多類POSIX的接口同樣例代碼的行為并不完全一致,需要做一些轉接的工作。特別FatFs文件系統中的f_lseek()
函數是從文件開始計算偏移,而不是像通用的f_seek()
函數從當前位置算偏移,因此需要使用f_tell()
函數做一個適配。
size_t in_func ( /* Returns number of bytes read (zero on error) */
JDEC* jd, /* Decompression object */
uint8_t* buff, /* Pointer to the read buffer (null to remove data) */
size_t nbyte /* Number of bytes to read/remove */
)
{
IODEV *dev = (IODEV*)jd- >device; /* Session identifier (5th argument of jd_prepare function) */
UINT br;
if (buff) /* Read data from imput stream */
{
//return fread(dev- >fp, buff, 1, nbyte, dev- >fp);
return (FR_OK == f_read(dev- >fp, buff, nbyte, &br)) ? br : 0;
}
else/* Remove data from input stream */
{
//return f_seek(dev- >fp, nbyte, SEEK_CUR) ? 0 : nbyte;
return (FR_OK == f_lseek(dev- >fp, f_tell(dev- >fp) + nbyte)) ? nbyte : 0;
}
}
在實現輸出數據流的回調函數的過程中,可以直接對接到開發板上LCD屏的顯存中,直接顯示像素。
int out_func ( /* Returns 1 to continue, 0 to abort */
JDEC* jd, /* Decompression object */
void* bitmap, /* Bitmap data to be output */
JRECT* rect /* Rectangular region of output image */
)
{
/* Progress indicator */
if (rect- >left == 0)
{
printf("r%lu%%", (rect- >top < < jd- >scale) * 100UL / jd- >height);
}
/* 在LCD屏幕上顯示圖像信息. */
LCD_FillWindow(rect- >left, rect- >top, rect- >right, rect- >bottom, (uint16_t *)bitmap);
return1; /* Continue to decompress */
}
在Keil工程中編譯可執行文件,下載到plus-f5270開發板上,實物演示如圖x所示。
圖x 在plus-f5270開發板上運行TJpgDec
Code Size (-0):
==============================================================================
Total RO Size (Code + RO Data) 45096 ( 44.04kB)
Total RW Size (RW Data + ZI Data) 13032 ( 12.73kB)
Total ROM Size (Code + RO Data + RW Data) 45104 ( 44.05kB)
==============================================================================
其中,SRAM占用量是比較少的,總共13032字節,其中系統棧占用4KB,系統堆占用4KB,工作空間占用3500字節,還帶了個FatFs文件系統,這已經算是非常經濟的用量了。
一點思考
從實際演示效果來看,移植的樣例工程能夠完成JPEG解碼功能,驗證了TJpgDec組件能夠正常工作,這是非常不錯的。但由于從SD卡讀數、解碼、刷屏這些個步驟都是一小段一小段執行的,因此實際顯示圖像刷屏的速度不是很快(估計受讀取SD卡過程的影響較大)。一種改進的策略,是將解碼得到的圖像片段搜集到一塊大內存中,然后集中刷屏,這樣視覺效果會好很多。解碼完之后純刷屏的速度很快,解碼之前雖然有等待,但當前屏幕上還在放映之前解碼的圖片,參觀者不會感到無趣。
plus-f5270開發板上的MM32F5270微控制器僅有128KB的SRAM,不夠存放一整張圖(480x320),但是可以存放1/4個屏幕的圖片數據(75KB),可以考慮將屏幕分成四塊小屏來用,每次刷一塊。
-
微控制器
+關注
關注
48文章
7906瀏覽量
153695 -
解碼器
+關注
關注
9文章
1163瀏覽量
41697 -
RGB
+關注
關注
4文章
803瀏覽量
59586 -
回調函數
+關注
關注
0文章
88瀏覽量
11825 -
SRAM存儲器
+關注
關注
0文章
88瀏覽量
13580
發布評論請先 登錄
手工打造基于MM32F5微控制器的MicroPython開發板

基于MM32F5微控制器的FSMC接口外接SRAM存儲器的用法

應用AM3358,請問怎樣在硬件設計上外部連接解碼器芯片,實現對圖像數據的解碼?
基于MM32F5270開發板對MindSDK進行使用測評
高清解碼器的作用

靈動微電子發布高性能MM32F5系列MCU產品
靈動微電子高端MCU產品MM32F5系列正式量產
搭載安謀科技“星辰”STAR-MC1處理器MM32F5系列MCU量產
解碼器該怎么選?
MicroPython應用基礎-準備基于MM32F5的MicroPython開發板

評論