【正点原子STM32连载】 第五十二章 图片显示实验摘自【正点原子】APM32F407最小系统板使用指南

news2025/1/11 14:24:01

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 例程功能

  1. 程序运行后,会显示SD卡中PICTURE文件夹中的第一张图片(支持bmp、jpg、jpeg或gif格式)
  2. 按下KEY0或KEY_UP按键,可分别进行切换上一张图片和切换下一张图片的操作
  3. 可通过USMART操作解码任意路径下的图片
  4. LED0闪烁,指示程序正在运行
    52.1.2 硬件资源
  5. LED
    LED0 - PF9
  6. 按键
    KEY0 - PE4
    KEY_UP - PA0
  7. USART1(PA9、PA10连接至板载USB转串口芯片上)
  8. 正点原子 2.8/3.5/4.3/7/10寸TFTLCD模块(仅限MCU屏,16位8080并口驱动)
  9. SD卡(SDIO驱动)
  10. 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文件夹中的上一张或下一张图片。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1203660.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

c语言从入门到实战——初识指针

初识指针 前言1. 内存和地址1.1 内存1.2 究竟该如何理解编址 2. 指针变量和地址2.1 取地址操作符(&)2.2 指针变量和解引用操作符(*)2.2.1 指针变量2.2.2 如何拆解指针类型2.2.3 解引用操作符 2.3 指针变量的大小 3. 指针变量类…

Sprint Boot 学习路线 6

测试 Spring提供了一组测试工具,可以轻松地测试Spring应用程序的各个组件,包括控制器、服务、存储库和其他组件。它具有丰富的测试注释、实用程序类和其他功能,以帮助进行单元测试、集成测试等。 JPA测试 Spring JPA(Java Pers…

开放领域对话系统架构

开放领域对话系统是指针对非特定领域或行业的对话系统,它可以与用户进行自由的对话,不受特定领域或行业的知识和规则的限制。开放领域对话系统需要具备更广泛的语言理解和生成能力,以便与用户进行自然、流畅的对话。 与垂直领域对话系统相比…

从单服务设计看SLA保证

文章首发公众号:海天二路搬砖工 0. 引言 在微服务架构中,谈到SLA保证,我们更多是从宏观的角度来需求解决方案。比如,通过合理服务拆分来增加系统整体的可维护性;通过多实例部署来保证系统的灾备。但是单个服务是可靠…

2023NewStarCTF

目录 一、阳光开朗大男孩 二、大怨种 三、2-分析 四、键盘侠 五、滴滴滴 六、Include? 七、medium_sql 八、POP Gadget 九、OtenkiGirl 一、阳光开朗大男孩 1.题目给出了secret.txt和flag.txt两个文件,secret.txt内容如下: 法治自由公正爱国…

【JVM】类加载器 Bootstrap、Extension、Application、User Define 以及 双亲委派

以下环境为 jdk1.8 两大类 分类成员语言继承关系引导类加载器bootstrap 引导类加载器C/C无自定义类加载器extension 拓展类加载器、application 系统/应用类加载器、user define 用户自定义类加载器Java继承于 java.lang.ClassLoader 四小类 Bootstrap 引导类加载器 负责加…

故障演练 | 微服务架构下如何做好故障演练

前言 微服务架构场景中,应用系统复杂切分散。长期运行时,局部出现故障时不可避免的。如果发生故障时不能进行有效反应,系统的可用性将极大地降低。 什么是故障演练 故障演练是指模拟生产环境中可能出现的故障,测试系统或应用在…

软考网络工程师知识点总结(二)

目录 21、海明码--差错控制 22、CRC循环冗余校验码 23、网络时延的计算 24、根据距离选择传输介质 25、多模光纤和单模光纤的区别 26、CSMA/CD协议 27、以太网帧结构 28、以太网类型及传输介质的选择 29、交换式以太网(交换机) 30、VLAN虚拟局…

Rust编程中的线程间通信

1.消息传递 为了实现消息传递并发,Rust 标准库提供了一个 信道(channel)实现。信道是一个通用编程概念,表示数据从一个线程发送到另一个线程。 可以将编程中的信道想象为一个水流的渠道,比如河流或小溪。如果你将诸如…

【C++ 学习 ㊱】- 智能指针详解

目录 一、为什么需要智能指针? 二、智能指针的原理及使用 三、auto_ptr 3.1 - 基本使用 3.2 - 模拟实现 四、unique_ptr 4.1 - 基本使用 4.2 - 模拟实现 五、shared_ptr 5.1 - 基本使用 5.2 - 模拟实现 六、weak_ptr 6.1 - shared_ptr 的循环引用问题 …

【Python小程序】求解2 * 2矩阵的逆矩阵

一、内容简介 使用Python求解2 * 2矩阵的逆矩阵。 二、求解方法 我们使用邻接矩阵法来求解2 * 2矩阵的逆矩阵。 det(A): 矩阵A的行列式 adj(A): 矩阵A的邻接矩阵 对于2*2矩阵A 我们有 三、Python代码 基于上述求解方法,我们可以写出Python代码如下&#xff…

行情分析——加密货币市场大盘走势(11.13)

大饼上涨太快,又开始震荡,但上不去,所以目前来看差不多要做回踩动作,入场空单性价比较高。而且从MACD日线来看,也是进入空头趋势,RSI(14)也是进入了超买区间,值得入手空单…

乡镇村污水处理智慧水务智能监管平台,助力污水监管智慧化、高效化

一、背景与需求 随着城市化进程的加速,排放的污水量也日益增加,导致水污染严重。深入打好污染防治攻坚战的重要抓手,对于改善城镇人居环境,推进城市治理体系和治理能力现代化,加快生态文明建设,推动高质量…

拼多多商品详情API接口接入流程如下:

拼多多商品详情API接口可以用于获取拼多多商品的具体信息,包括商品ID、商品名称、价格、销量、评价等。以下是使用拼多多商品详情API接口的步骤: 进入拼多多开放平台,注册并登录账号。在开放平台页面中,找到“商品详情”或“商品…

基于SSM+Vue的电子商城的设计与实现

末尾获取源码 开发语言:Java Java开发工具:JDK1.8 后端框架:SSM 前端:Vue 数据库:MySQL5.7和Navicat管理工具结合 服务器:Tomcat8.5 开发软件:IDEA / Eclipse 是否Maven项目:是 目录…

基因检测技术的发展与创新:安全文件数据传输的重要作用

基因是生命的密码,它决定了我们的身体特征、健康状况、疾病风险等。随着基因检测技术的高速发展,我们可以通过对基因进行测序、分析和解读,更深入地认识自己,预防和治疗各种遗传性疾病,甚至实现个性化医疗和精准健康管…

动态调整学习率Lr

动态调整学习率Lr 0 引入1 代码例程1.1 工作方式解释 2 动态调整学习率的几种方法2.1 lr_scheduler.LambdaLR2.2 lr_scheduler.StepLR2.3 lr_scheduler.MultiStepLR2.4 lr_scheduler.ExponentialLR2.2.5 lr_scheduler.CosineAnnealingLR2.6 lr_scheduler.ReduceLROnPlateau2.7 …

ASK、PSK、FSK的调制与解调

ASK、PSK、FSK的调制与解调 本文主要涉及数字信号的调制与解调,内容包括:2ASK、2PSK、2FSK的调制与解调以及频谱分析 关于通信原理还有其他文章可参考: 1、信息量、码元、比特、码元速率、信息速率详细解析——实例分析 2、模拟系统的AM信号的…

2023最新版JavaSE教程——第6天:面向对象编程(基础)

目录 一、面向对象编程概述(了解)1.1 程序设计的思路1.2 由实际问题考虑如何设计程序1.3 如何掌握这种思想? 二、Java语言的基本元素:类和对象2.1 引入2.2 类和对象概述2.3 类的成员概述2.4 面向对象完成功能的三步骤(重要)2.4.1 步骤1:类的定…

数据分类分级方法及典型应用场景

1 2021-09-29 来源:数据学堂 [打印本稿][字号 大 中小] 《数据安全法》的第二十一条明确规定了由国家建立数据分类分级保护制度,根据数据在经济社会发展中的重要程度,以及一旦遭到篡改、破坏、泄露或者非法获取、非法利用,对国…