1)实验平台:正点原子stm32f103战舰开发板V4
2)平台购买地址:https://detail.tmall.com/item.htm?id=609294757420
3)全套实验源码+手册+视频下载地址: http://www.openedv.com/thread-340252-1-1.html##
第五十二章 图片显示实验
本章将介绍使用APM32F407软件解码BMP、JPG和GIF等格式的图片,并在LCD进行显示。通过本章的学习,读者将学习到图片解码库的使用。
52.1 硬件设计
52.2 程序设计
52.3 下载验证
52.1 硬件设计
52.1.1 例程功能
- 程序运行后,会显示SD卡中PICTURE文件夹中的第一张图片(支持bmp、jpg、jpeg或gif格式)
- 按下KEY0或KEY_UP按键,可分别进行切换上一张图片和切换下一张图片的操作
- 可通过USMART操作解码任意路径下的图片
- LED0闪烁,指示程序正在运行
52.1.2 硬件资源 - LED
LED0 - PF9 - 按键
KEY0 - PE4
KEY_UP - PA0 - USART1(PA9、PA10连接至板载USB转串口芯片上)
- 正点原子 2.8/3.5/4.3/7/10寸TFTLCD模块(仅限MCU屏,16位8080并口驱动)
- SD卡(SDIO驱动)
- NOR Flash(SPI驱动)
52.1.3 原理图
本章实验使用的图片解码库为软件库,因此没有对应的连接原理图。
52.2 程序设计
52.2.1 图片解码库的使用
正点原子提供的图片解码库包含了九个文件,分别为:piclib.c、piclib.h、bmp.c、bmp.h、gif.c、gif.h、tjpgd.c、tjpgd.h、tjpgdcnf.h,这几个文件的描述,如下表所示:
文件 描述
piclib.c
piclib.h 正点原子图片解码库文件,主要提供图片解码库和画图的初始化和根据文件类型自动解码并画图的函数等
bmp.c
bmp.h 正点原子BMP图片编解码库,主要用于解码BMP图片文件
gif.c
gif.h 正点原子GIF图片解码库,主要用于解码GIF图片文件
tjpgd.c
tjpgd.h
tjpgdcnf.h TjpgDec(JPEG图片解码库)的源文件和配置文件,为了方便使用,添加了用于正点原子图片解码库的函数
表52.2.1.1 图片解码库各文件描述
以上图片解码库的九个文件,在本章实验配套的实验例程中都已提供,并且针对正点原子APM32F407最小系统板软硬件进行了移植适配,用户在使用时,仅需将这九个文件添加到自己的工程即可,如下所示:
图52.2.1.1 正点原子图片解码库文件
52.2.2 实验应用代码
本章实验的应用代码,如下所示:
int main(void)
{
uint8_t res;
DIR picdir;
uint16_t totpicnum;
FILINFO *picfileinfo;
char *pname;
uint32_t *picoffsettbl;
uint16_t curindex;
uint16_t temp;
uint8_t t = 0;
uint8_t key;
NVIC_ConfigPriorityGroup(NVIC_PRIORITY_GROUP_3); /* 设置中断优先级分组为组3 */
sys_apm32_clock_init(336, 8, 2, 7); /* 配置系统时钟 */
delay_init(168); /* 初始化延时功能 */
usart_init(115200); /* 初始化串口 */
usmart_dev.init(84); /* 初始化USMART */
led_init() /* 初始化LED */
key_init() /* 初始化按键 */
lcd_init() /* 初始化LCD */
my_mem_init(SRAMIN); /* 初始化内部SRAM内存池 */
my_mem_init(SRAMCCM); /* 初始化CCM内存池 */
exfuns_init() /* 为exfuns申请内存 */
f_mount(fs[0], "0:", 1); /* 挂载SD卡 */
f_mount(fs[1], "1:", 1); /* 挂载NOR Flash */
while (sd_init() != SD_OK) /* 初始化SD卡 */
{
/* SD卡初始化失败,代码省略 */
}
/* 检查字库,代码省略 */
text_show_string(30, 50, 200, 16, "正点原子APM32开发板", 16, 0, RED);
text_show_string(30, 70, 200, 16, "图片显示实验", 16, 0, RED);
text_show_string(30, 90, 200, 16, "KEY0: PREV", 16, 0, RED);
text_show_string(30, 110, 200, 16, "KEY_UP: NEXT", 16, 0, RED);
text_show_string(30, 130, 200, 16, "正点原子@ALIENTEK", 16, 0, RED);
/* 打开图片文件夹 */
while (f_opendir(&picdir, "0:/PICTURE") != FR_OK)
{
/* PICTURE文件夹错误,代码省略 */
}
/* 获取有效图片文件数量 */
totpicnum = pic_get_tnum("0:/PICTURE");
while (totpicnum == 0)
{
/* 没有图片文件,代码省略 */
}
/* 申请内存 */
picfileinfo = (FILINFO *)mymalloc(SRAMIN, sizeof(FILINFO));
pname = (char *)mymalloc(SRAMIN, FF_MAX_LFN * 2 + 1);
picoffsettbl = (uint32_t *)mymalloc(SRAMIN, 4 * totpicnum);
while ((picfileinfo == NULL) || (pname == NULL) || (picoffsettbl == NULL))
{
/* 内存申请失败,代码省略 */
}
/* 打开目录 */
res = (uint8_t)f_opendir(&picdir, "0:/PICTURE");
if (res == 0)
{
curindex = 0;
while (1)
{
temp = picdir.dptr; /* 记录当前dptr偏移 */
res = (uint8_t)f_readdir(&picdir, picfileinfo);/* 读取下一个文件 */
if ((res != 0) || (picfileinfo->fname[0] == 0))/* 错误或到末尾,退出 */
{
break;
}
res = exfuns_file_type(picfileinfo->fname);
if ((res & 0xF0) == 0x50) /* 是图片文件 */
{
picoffsettbl[curindex] = temp; /* 记录索引 */
curindex++;
}
}
}
text_show_string(30, 150, 240, 16, "开始显示...", 16, 0, RED);
delay_ms(1500);
piclib_init(); /* 初始化画图 */
curindex = 0; /* 从0开始显示 */
/* 打开目录 */
res = (uint8_t)f_opendir(&picdir, (const TCHAR *)"0:/PICTURE");
while (res == 0)
{
/* 改变当前目录索引 */
dir_sdi(&picdir, picoffsettbl[curindex]);
/* 读取目录的下一个文件 */
res = (uint8_t)f_readdir(&picdir, picfileinfo);
/* 错误或到末尾,退出 */
if ((res != 0) || (picfileinfo->fname[0] == 0))
{
break;
}
/* 复制路径(目录) */
strcpy((char *)pname, "0:/PICTURE/");
/* 将文件名接在后面 */
strcat((char *)pname, (const char *)picfileinfo->fname);
lcd_clear(BLACK);
/* 显示图片 */
piclib_ai_load_picfile(pname, 0, 0, lcddev.width, lcddev.height, 1);
/* 显示图片名字 */
text_show_string(2, 2, lcddev.width, 16, (char *)pname, 16, 1, RED);
while (1)
{
t++;
key = key_scan(0);
if (key == KEY0_PRES) /* 上一张 */
{
if (curindex != 0)
{
curindex--;
}
else
{
curindex = totpicnum - 1;
}
break;
}
else if (key == WKUP_PRES) /* 下一张 */
{
curindex++;
if (curindex >= totpicnum)
{
curindex = 0;
}
break;
}
if (t == 20)
{
LED0_TOGGLE();
t = 0;
}
delay_ms(10);
}
}
/* 释放内存 */
myfree(SRAMIN, picfileinfo);
myfree(SRAMIN, pname);
myfree(SRAMIN, picoffsettbl);
while (1);
}
从上面的代码中可以看出,本实验的应用代码中,在完成文件系统、SD卡等一些列必要的初始化后,便会统计SD卡中PICTURE文件夹下图片的数量和路径,然后根据KEY0和KEY_UP按键,调用函数piclib_ai_load_picfile()切换显示SD卡PICTURE文件夹中的图片文件至LCD上。
本章实验所需的图片文件可以在A盘5,SD卡根目录文件PICTURE中找到,建议将A盘5,SD卡根目录文件中的所有文件按照该目录的目录结构复制进SD卡,方便后续实验的使用。
52.3 下载验证
在完成编译和烧录操作后,将根目录存放了A盘5,SD卡根目录文件中文件的SD卡插入开发板板载的SD卡卡座后,便能看到LCD上显示了SD卡PICTURE文件夹中的图片,并且按下KEY0按键或KEY_UP按键可以切换LCD显示SD卡PICTURE文件夹中的上一张或下一张图片。