一、总体架构
SD 卡 (FATFS)
↓
JPEG 文件
↓
TJpgDec(轻量 JPEG 解码库)
↓
RGB565 像素缓冲
↓
TFT LCD(DMA 刷新)
优点
- 内存占用极小(几 KB)
- 解码速度快
- 适合 STM32F1 / F4 / G0 / H7
二、硬件要求
| 模块 | 建议 |
|---|---|
| MCU | STM32F407 / F429 / H743(带 FSMC / LTDC 更好) |
| SD 卡 | SPI 或 SDIO |
| LCD | ILI9341 / ILI9488 / ST7789 |
| RAM | ≥ 32KB(解码缓冲) |
STM32F103 只能显示小分辨率 JPEG(≤ 320×240)
三、软件组件选型
| 功能 | 库 |
|---|---|
| 文件系统 | FatFs |
| JPEG 解码 | TJpgDec(官方轻量库) |
| 显示驱动 | 自定义 LCD 驱动 |
| 刷新方式 | DMA + RGB565 |
四、关键数据结构
c
#define LCD_WIDTH 320
#define LCD_HEIGHT 240
uint16_t lcd_buf[LCD_WIDTH]; // 一行像素缓冲
五、FatFs + SD 卡初始化
c
#include "ff.h"
#include "diskio.h"
FATFS fs;
FIL file;
void SD_Init(void)
{
f_mount(&fs, "", 0);
}
六、TJpgDec 移植(核心)
1、下载 TJpgDec
官网:http://elm-chan.org/fsw/tjpgd/
2、实现输入函数(从 SD 卡读数据)
c
#include "tjpgd.h"
UINT jpeg_read(JDEC* jd, BYTE* buff, UINT nbyte)
{
UINT br;
FIL *fp = (FIL*)jd->device;
f_read(fp, buff, nbyte, &br);
return br;
}
3、实现输出函数(写 LCD)
c
UINT jpeg_write(JDEC* jd, void* bitmap, JRECT* rect)
{
uint16_t* src = (uint16_t*)bitmap;
uint16_t x, y;
for (y = rect->top; y <= rect->bottom; y++) {
for (x = rect->left; x <= rect->right; x++) {
LCD_DrawPixel(x, y, *src++);
}
}
return 1;
}
更高效版本(推荐) :
使用 LCD_DrawBitmap(x, y, w, h, buf) + DMA
七、JPEG 解码并显示
c
void Show_JPEG(char *filename)
{
JDEC jdec;
JRESULT res;
uint8_t work[3100]; // 解码工作缓冲(≥ 3100)
f_open(&file, filename, FA_READ);
res = jd_prepare(&jdec, jpeg_read, work, sizeof(work), &file);
if (res != JDR_OK) {
f_close(&file);
return;
}
res = jd_decomp(&jdec, jpeg_write, 0); // 0 = 原尺寸
f_close(&file);
}
八、TFT LCD 显示接口(示例)
c
void LCD_DrawPixel(uint16_t x, uint16_t y, uint16_t color)
{
LCD_SetCursor(x, y);
LCD_WriteData(color);
}
DMA 刷新(大幅提升速度)
c
void LCD_DrawBitmap(uint16_t x, uint16_t y, uint16_t w, uint16_t h, uint16_t *buf)
{
LCD_SetWindow(x, y, w, h);
HAL_DMA_Start(&hdma_memtomem, (uint32_t)buf, (uint32_t)&LCD_RAM, w * h);
}
参考代码 stm32读取sd卡的jpeg图片,然后解码显示在tft液晶屏上面 www.youwenfan.com/contentcsu/69805.html
九、主函数流程
c
int main(void)
{
HAL_Init();
SystemClock_Config();
MX_SDIO_SD_Init();
MX_FATFS_Init();
LCD_Init();
SD_Init();
LCD_Clear(BLACK);
Show_JPEG("test.jpg");
while (1);
}