资源描述
毕 业 设 计 报 告 (论 文 ) 题目:基于 STM32 的数码相框系统 设计与实现(软件) 所 属 系 电子工程系 专 业 自 动 化 设计地点 东南大学成贤学院 东南大学成贤学院毕业设计报告(论文) 诚 信 承 诺 本人承诺所呈交的毕业设计报告(论文)及取得的成果是在导师指导 下完成,引用他人成果的部分均已列出参考文献。如论文涉及任何知识产 权纠纷,本人将承担一切责任。 学生签名: 日期: - I - 基于 STM32 的数码相框系统设计与实现(软件) 摘 要 本设计是一款基于嵌入式硬件平台的数码相框,主控芯片为基于 ARM Cortex-M3 内核的 STM32 系列嵌入式处理器,本设计包含主控制器核心板、LCD 液晶显示、SD 卡存储器等多个功能模块。实 现对 SD 卡里多幅图片以幻灯片形式在 TFT 屏上动态显示的效果,且带有实时时钟的功能。 关键词:嵌入式;数码相框;Cortex-M3 - II - The design of digital photo frames based on the STM32 Abstract The design is a digital photo frame-based embedded hardware platform ,whose main chip for the STM32 family of embedded processors based on ARM Cortex-M3 core . The design includes a host controller core board, LCD display, SD card memory and other functional modules. It can achieve the effect of multiple images of the SD card as a slide show on the TFT screen dynamic display, and with real- time clock function. Keywords:Embedded; Digital Photo Frame; Cortex-M3 - III - 目 录 摘 要 .I ABSTRACT.II 第一章 引 言 .1 1.1 课题研究意义 .1 1.2 数码相框的发展情况和趋势 .1 1.2.1 数码相框的发展现状 .1 1.2.2 数码相框的发展趋势 .2 1.3 本课题设计主要研究内容 .2 1.4 主要章节安排 .3 第二章 硬件介绍 .4 2.1 嵌入式系统概况 .4 2.1.1 嵌入式系统的定义 .4 2.1.2 嵌入式系统的组成 .4 2.1.3 嵌入式系统的特点 .5 2.2 数码相框模块 .5 2.2.1 MCU 主控模块 .5 2.2.2 LCD 模块 .6 2.2.3 SD 存储卡模块 .9 第三章 编程环境介绍 .12 3.1 RVMDK3.80A 简介 .12 3.2 新建 RVMDK 工程 .12 3.3 软件仿真 .19 3.4 在线调试 .24 3.4.1 J-link 简介 .24 3.4.2 J-link 调试步骤 .25 3.5 程序下载 .28 第四章 程序设计与调试 .34 4.1 系统描述 .34 4.2 软件设计 .34 4.2.1 文件读取 .34 4.2.2 图像解码与显示 .35 4.2.3 时钟显示 .42 4.2.4 主程序设计 .52 4.3 程序调试 .57 第五章 结束语 .59 致 谢 .60 参考文献(REFERENCES) .61 附录 数码相框原理图 .62 东南大学成贤学院毕业论文 - 1 - 第一章 引 言 1.1 课题研究意义 嵌入式系统无疑是当前最热门最有发展前途的 IT 应用领域之一。嵌入式系统用在一些专用设 备上,通常这些设备的硬件资源(如处理器、存储器等)非常有限,并且对成本很敏感,有时对实时 响应要求很高。特别是随着消费家电的智能化,嵌入式更显重要。像我们平常常见到的手机、 PDA、电子字典、可视电话、VCDDVDMP3 播放器、数码相机、数字摄像机、U-Disk、机顶盒、 高清电视、游戏机、智能玩具、交换机、路由器、数控设备、汽车电子、家电控制系统、医疗仪器、 航天航空设备等都是典型的嵌入式产品。 数字摄影的兴起不可避免地引起了数码相框的发展,因为仅有不到 35%的数码照片被打印出来。 数码相框的基本原理就是采用普通相框的造型,把原来相框中间的照片部分换成液晶显示屏,配上 电源,存储介质等,使得同一个相框内可以循环播放照片,比普通照片的单一显示功能更有优势。 从 2007 年开始,数码相框的市场关注度开始激增。在 2008 年,数码相框市场呈现高速发展的态势, 本课题的研究具有极高的潜在市场价值。 此外,本设计属于数字影音娱乐产品,需要较为强劲的处理器进行图像解码的工作,而 STM32 具有超低的价格、超多的外设、丰富的型号、优异的实时性能、杰出的功耗控制和极低的开发成本 等特点。因此,进行基于 STM32 平台的数码相框系统的设计具有重要的理论意义和实用价值。 1.2 数码相框的发展情况和趋势 1.2.1 数码相框的发展现状 数码相框产品是 2001 年开始出现的,但由于当时消费者的接受度及价格过高的因素,使这一 市场一直到 2003 年都很低迷。随着主要器件价格的下降,数码相框的价格也逐步下降,市场在 2004 年开始有了起色,尤其在 2005 年,数码相框产品开始在欧美热销,但出货量也只有 150 万台 左右,到了 2006 年的出货量同比上涨 133,为 280 万台,2007 年的出货量同比上涨 185,为 800 万台,预计到 2011 年出货量将达到 4000 万台。从屏幕尺寸来看,2006 年 5-6.9 英寸产品占主 流,2007 年 7、8、9 英寸产品成为最大市场。预计 2011 年,7、8、9 英寸产品的供货比例将持续 保持首位,而平均销售单价将以每年 16.5左右的速度降低。 2006 年以前,中国生产的数码相框绝大多数出口国外。2005 年底 Philips 率先将数码相框在 中国推广,在礼品市场上取得了一些成绩,但由于销售价格较高,约为 2050 元/台,这一年中国数 码相框的销售量仅有 1.7 万台。2006 年下半年,开始有更多的国内厂商在中国市场推出数码相框, 因而也带动了此产品价格的下降,这一年的平均售价为 1150 元/台,仍然较高,市场也以商务礼品 为主,但由于 2005 年销售量的基数较低,2006 年的销售量同比增长了 470.6,达到 9.7 万台。 直到 2007 年下半年,业界才感到这个一直处于培育期的市场,开始了真正的起飞。这得益于对数 码相框产品认知度的提高、价格的下滑和需求量的提高。 从 IT 厂商来看,仅 2007 年下半年以来,就有惠普、三星、优派、AOC、明基、柯达、长城等 众多新军加入数码相框阵营。其中,巨头惠普 2007 年 7 月底在美国宣布进入数码相框市场,2007 年数码相框出货量设定为 50 万台。除新军外,数码相框老牌劲旅的出货量表现也令业界振奋,如 飞利浦 2006 年数码相框出货量达到 50 万台,而 2007 年上半年出货量已达去年总和,2007 年全年 出货量达 150 万台。而从上游面板厂商的动作来看,也显示出乐观的发展态势。中华映管、群创等 厂商均显著调高了配套数码相框产品的中尺寸面板的出货量目标,2007 年出货量达 1000 万台,预 东南大学成贤学院毕业论文 - 2 - 计 2008 年更将倍增至 2000 万台。其中,中华映管目前已调配一座 4.5 代面板厂来支持生产中尺寸 面板,主要生产可携式 DVD 播放机面板与数码相框面板,其数码相框面板以 7 英寸、8 英寸、10.2 英寸为主要尺寸,数码相框面板占其中尺寸面板的比重提高到 40。 1.2.2 数码相框的发展趋势 从长远来看,2008 年及今后几年将为处在数码相框产品供应链的各企业带来巨大的商机。未 来几年,数码相框的市场将处在逐渐走向成熟期的阶段,其产销量和市场需求依然将保持大幅度的 增长,在未来的三年内,市场尚无萎缩的可能。但数码相框拓展中国市场需克服两大难点:一是价 格;二是拓展应用空间。价格下降是必然趋势,中国消费者接受只是时间的问题,而根据中国消费 者的需求和特点,开发出相应的应用产品,则是需要数码相框厂商亟待解决的问题。 从技术上来说,未来数码相框的发展将向两极分化。一部分产品着重强调基本功能和低成本, 整合家庭中的闹钟、日历和装饰功能,这些产品走的是低成本路线,以展示照片为主,追求图像的 品质及幻灯片播放特效,已成为 DC/DV 的附属物;另一部分产品将会添加一些新的功能,如 WiFi,还可即时报告天气、股票等信息,从而有望成为“桌面信息中心”。此外,触摸面板会成为 一个应用的新亮点。 从产品形态上来说,数码相框的市场将会有非常明确的细分。 1 数码相框: 这将是以数字照片的重显为主要功能的产品,其功能更接近于传统意义上的相框。 由于人机界面的限制,为了更方便的重显和浏览以及确定重显的规则,这类产品并不强调有大 容量的内存以及丰富的存储卡接口,这类产品的主要特征是: 1) 支持 USB Device Stm32_Clock_Init(9); /72M delay_init(72); /延时初始化 东南大学成贤学院毕业论文 - 18 - uart_init(72,9600); /设置串口 1 波特率 while(1) printf(t:%dn,t); delay_ms(500); t+; 点击 (部分编译按钮)编译一下,会在 Output Windows 信息栏中发现如下报错信息: test.c(1): error: #5:can not open source input file sys.h: No such file or directory。如下图所示(图中红圈内信息): 图 3-10 编译报错 意思是无法打开源输入文件 sys.h,没这个文件或目录。双击红圈内的内容,你会发现在 test.c 的 01 行出现了一个浅绿色的小箭头,说明错误是这个地方产生的。双击后浅绿色箭头出现位置如 下: 图 3-11 编译报错 其实通过下面错误的说明,就是 include 的路径没有加进去的缘故,而导致了这个错误。现 在我们点击 (Options for Target 按钮),弹出 Options for TargetTarget 1对话框,选 择 C/C+选项卡,如下图所示: 东南大学成贤学院毕业论文 - 19 - 图 3-12 加入头文件包含路径 在 Include Paths 处,点击 2 处的按钮。在弹出的对话框中加入 SYSTEM 文件夹下的 3 个文件 夹名字,把这几个路径都加进去(此操作即设定编译器的头文件包含路径,下面会经常用到)。 图 3-13 头文件包含路径设置 点击 OK 确认,回到 IDE,此时再点击 按钮,再编译一次,发现没错误了,得到如下界面: 东南大学成贤学院毕业论文 - 20 - 图 3-14 再次编译结果 至此,一个完整的 STM32 开发工程在 MDK 下建立了,接下来我们就是进行软件仿真了。 3.3 软件仿真 MDK 的一个强大的功能就是提供软件仿真,通过软件仿真,我们可以发现很多将要出现的问题, 避免了下载到 STM32 里面来查这些错误,这样最大的好处是能很方便的检查程序存在的问题,因为 在 MDK 的仿真下面,你可以查看很多硬件相关的寄存器,通过观察这些寄存器,你可以知道代码是 不是真正有效。另外一个优点是不必频繁的刷机,从而延长了 STM32 的 FLASH 寿命。当然,软件仿 真不是万能的,很多问题还是要到在线调试才能发现。接下来我们开始进行软件仿真。 在软件仿真之前,先检查一下配置是不是正确,点击 ,确定 Target 选项卡内容如下所示 (主要检查芯片型号和晶振频率,其他的一般默认就可以): 图 3-15 Target 选项卡 确认了芯片以及外部晶振频率(8.0 M)之后,基本上就确定了硬件环境了,接下来,我们再 东南大学成贤学院毕业论文 - 21 - 看 Debug 选项卡,设置为如下图所示的设置: 图 3-16 Debug 选项卡 主要确认是 Use Simulator 是否选择(因为如果选择右边的 Use,那就是用 ULINK 进行硬件 Debug 了,这个将在下面介绍),其他的采用默认的就可以。确认了这项之后,我们便可以选择 OK,退出 Options for Target 对话框了。接下来,我们点击 (开始/停止仿真按钮),开始仿 真,出现如下界面: 图 3-17 开始仿真 可以发现,多出了一个工具条,这个工具条对于我们仿真是非常有用的,下面简单介绍一下工 具条相关按钮的功能,工具条部分按钮的功能如下图所示 东南大学成贤学院毕业论文 - 22 - 图 3-18 仿真工具条 复位:其功能等同于硬件上按复位按钮。相当于实现了一次硬复位。代码重新执行。 执行到断点处:该按钮用来快速执行到断点处,有时候你并不需要观看每步是怎么执行的,而 是想快速的执行到程序的某个地方看结果,这个按钮就可以实现这样的功能。 挂起:此按钮在程序一直执行的时候会变为有效,通过按该按钮,就可以使程序停止下来,进 入到单步调试状态。 执行进去:该按钮用来实现执行到某个函数里面去的功能,在没有函数的情况下,是等同于执 行过去按钮的。 执行过去:在碰到有函数的地方,通过该按钮就可以单步执行过这个函数,而不进入这个函数 单步执行。 执行出去:该按钮是在进入了函数单步调试的时候,有时候你可能不必再执行该函数的剩余部 分了,通过该按钮就直接一步执行完函数余下的部分,并跳出函数,回到函数被调用的位置。 执行到光标处:该按钮可以迅速的使程序运行到光标处,其实是挺像执行到断点处按钮功能, 但是两者是有区别的,断点可以有多个,但是光标所在处只有一个。 汇编窗口:通过该按钮,就可以查看汇编代码,这对分析程序很有用。 观看变量/堆栈窗口:该按钮按下,会弹出一个显示变量的窗口,在里面可以查看各种你想要 看的变量值,也是很常用的一个调试窗口。 串口打印窗口:该按钮按下,会弹出一个串口调试助手界面的窗口,用来显示从串口打印出来 的内容。 内存查看窗口:该按钮按下,会弹出一个内存查看窗口,可以在里面输入你要查看的内存地址, 然后观察这一片内存的变化情况,是很常用的一个调试窗口 性能分析窗口:按下该按钮,会弹出一个观看各个函数执行时间和所占百分比的窗口,用来分 析函数的性能是比较有用的。 逻辑分析窗口:按下该按钮会弹出一个逻辑分析窗口,通过 SETUP 按钮新建一些 I/O 口,就 可以观察这些 I/O 口的电平变化情况,以多种形式显示出来,比较直观。 其他几个按钮用的比较少,以上是比较常用的,当然也不是每次都用得着这么多,具体看你程 序调试的时候有没有必要观看这些东西来决定要不要看。 这样,我们在上面的仿真界面里面选内存查看窗口、串口打印窗口。然后调节一下这两个窗口 的位置,如下图所示: 东南大学成贤学院毕业论文 - 23 - 图 3-19 调出仿真串口打印窗口 我们把光标放到 test.c 的 09 行,然后双击鼠标左键,可以看到在 09 行的右边出现了一个红 框,即表示设置了一个断点(也可以通过鼠标右键弹出菜单来加入,再次双击则取消)。然后我们 点击,执行到断点处,如下图所示: 图 3-20 执行到断点处 我们不忙着往下执行,现在来点击菜单栏的 Peripherals-USARTs-USART1。可以看到,有很 多外设可以查看,这里我们查看的是串口 1 的情况。如下图所示 东南大学成贤学院毕业论文 - 24 - 图 3-21 查看串口 1 相关寄存器 单击 USART1 后会在 IDE 之外出现一个如下界面: 图 3-22 串口 1 各寄存器初始化前后对比 左边这个就是 STM32 默认时候,串口 1 的状态,从中可以看到所有与串口相关的寄存器全部在 这上面表示出来了,而且有当前串口的波特率等信息的显示。我们接着单击一下 ,执行完串口 初始化函数,得到了如上面右边图片所示的串口信息。你可以对比一下这两个的区别,就知道在 uart_init(72,9600);这个函数里面大概执行了哪些操作。这样可以很清楚的告诉你,当前的串口 是否可用,你的设置是否正确,同样这样的方法也可以适用于很多其他外设。 然后我们继续单击 按钮,一步步执行,最后就会看到在 USART #1 中打印出相关的信息,如 下图所示: 东南大学成贤学院毕业论文 - 25 - 图 3-23 串口 1 输出信息 这样证明我们的仿真是通过的,代码运行会在串口 1 不停的输出 t 的值,每 0.5s 执行一次 (时间可以通过 IDE 的最下面观看到),并且 t 自增。与我们预期的目地是一致的。再次按下 结束仿真。至此,我们软件仿真算是结束了,接下来我们下载代码到硬件上来真正验证一下我 们的代码是否可行。 3.4 在线调试 利用串口,我们只能下载程序,并不能实时跟踪,而利用调试工具,比如 JLINK、ULINK 等就 可以实时跟踪程序,使你的开发事半功倍。这里我们以 JLINK V8 为例,说说如何在线调试。 3.4.1 J-link 简介 J-Link 是 SEGGER 公司为支持仿真 ARM 内核芯片推出的 JTAG 仿真器。配合 IAR EWAR,ADS,KEIL,WINARM,Real View 等集成开发环境支持所有 ARM7/ARM9/ARM11 内核芯片的仿 真,通过 RDI 接口和各集成开发环境无缝连接,操作方便、连接方便、简单易学,是学习开发 ARM 最好最实用的开发工具。 J-LINK 仿真器 V8 版,其仿真速度和功能远非简易的并口 WIGGLER 调试器可比。J-LINK 支持 ARM7、ARM9、ARM11、Cortex-M3 核心,支持 ADS、IAR、KEIL 开发环境。V8.0 版本除拥有上一版本 V7.0 的全部功能外,软硬件上都有改进:(1)V8.0 版的 SWD 硬件接口支持 1.2-5.0V 的目标板, V7.0 只能支持 3.3V 的目标板。(2)V8.0 使用双色 LED 可以指示更多的工作状态,V7.0 只有 1 个 LED 指示灯。(3)V8.0 增强了 JTAG 驱动能力,提高了目标板的兼容性。(4)优化了固件结构, 使应用程序区扩大。J-Link ARM 主要特点: IAR EWARM 集成开发环境无缝连接的 JTAG 仿真器。 支持所有 ARM7/ARM9 内核的芯片,以及 Cortex-M3,包括 Thumb 模式。 支持 ADS,IAR,KEIL,WINARM,REALVIEW 等几乎所有的开发环境。 下载速度高达 ARM7:600kB/s,ARM9:550kB/s,通过 DCC 最高可达 800 KB/s。 最高 JTAG 速度 12MHz。 目标板电压范围 1.2V3.3V,5V 兼容。 自动速度识别功能。 监测所有 JTAG 信号和目标板电压。 东南大学成贤学院毕业论文 - 26 - 完全即插即用。 使用 USB 电源(但不对目标板供电) 带 USB 连接线和 20 芯扁平电缆。 支持多 JTAG 器件串行连接。 标准 20 芯 JTAG 仿真插头。 选配 14 芯 JTAG 仿真插头。 选配用于 5V 目标板的适配器。 带 J-Link TCP/IP server,允许通过 TCP/ IP 网络使用 J-Link。 3.4.2 J-link 调试步骤 JLINK-V8 支持 JTAG 和 SWD,而 STM32 也支持 JTAG 和 SWD。所以,我们有 2 种方式可以用来调 试,JTAG 调试的时候,占用的 I/O 线比较多,而 SWD 调试的时候占用的 I/O 线很少,只需要 2 跟 即可。 在安装了 JLINK V8 之后,我们接上 JLINK-V8,并把 JTAG 口插到硬件板上,打开之前新建的 工程,点击 ,打开 Options for Target 选项卡,在 Debug 栏选择仿真工具为 Cortex-M3 J- LINK,如下图所示 图 3-24 Debug 选项卡设置 然后我们点击 Settings,设置 J-LINK 的一些参数,如下图所示: 东南大学成贤学院毕业论文 - 27 - 图 3-25 J-LINK 模式设置 上图中,我们使用 J-LINK V8 的 SW 模式调试,因为我们 JTAG 需要占用比 SW 模式多很多的 I/O 口,而在硬件板上这些 I/O 口都是非常有用的,并造成部分外设无法使用。所以建议大家在调 试的时候,一定要选择 SW 模式。Max Clock,可以点击 Auto Clk 来自动设置,这里设置 JLINK 的 调试速度为 10MHZ,如果 USB 数据线比较差,那么可能会出问题,此时,可以通过降低这里的速率 来试试。 单击 OK,完成此部分设置,接下来我们还需要在 Utilities 选项卡里面设置下载时的目标编 程器,如下图所示: 图 3-26 FLASH 编程器选择 上图中,我们选择 J-LINK 来调试 Cortex-M3,然后点击 Settings,设置如下图所示: 东南大学成贤学院毕业论文 - 28 - 图 3-27 编程设置 这里要根据不同的 MCU 选择 FLASH 的大小,因为我们开发板使用的是 STM32F103RBT6,其 FLASH 大小为 128K,所以我们在 Programming Algorithm 里面选择 128K 型号的 STM32。然后选中 Reset and Run,以实现在编程后自动启动。其他默认设置即可。 在设置完之后,点击 OK,然后再点击 OK,回到 IDE 界面,编译一下工程。再点击 ,开始仿 真(如果开发板的代码没被更新过,则会先更新代码,再仿真,你也可以通过按 ,只下载代码, 而不进入仿真,特别注意:开发板上的 B0 要设置到 GND,否则代码下载后不会自动运行的!), 如下图所示: 图 3-28 开始仿真 可以看到都是一些汇编码的查看,如果我们要快速运行到 main 函数,可以在 main 函数的第一 句语句处放入断点,然后点击 ,来快速执行到该处。如下图所示: 东南大学成贤学院毕业论文 - 29 - 图 3-29 程序运行到断点处 接下来,我们就可以和软件仿真一样的开始仿真了,不过这是真正的在硬件上的仿真,其结果 更可信。 3.5 程序下载 STM32 的程序下载有多种方法:USB、串口、JTAG、SWD 等,这几种方式都可以用来给 STM32 下 载代码。不过,我们最常用的,最经济的,就是通过串口给 STM32 下载代码。 STM32 的串口下载一般是通过串口 1 下载的,本设计的硬件板,不是通过 RS232 串口下载的, 而是通过自带的 USB 串口来下载。看起来像是 USB 下载(只有一根 USB 线,并没有串口线)的,实 际上,是通过 USB 转成串口,然后再下载的。 下面,我们就一步步实现如何在实验平台上利用 USB 串口来下载代码。 首先要在板子上设置一下,在板子上把 RXD 和 PA9(STM32 的 TXD),TXD 和 PA10(STM32 的 RXD)通过跳线帽连接起来,这样我们就把 PL2303 和 MCU 的串口 1 连接上了。这里由于硬件板自带 了一键下载电路,所以并不需要去关心 BOOT0 和 BOOT1 的状态,但是为了让下载完后可以按复位执 行程序,要把 BOOT1 和 BOOT0 都设置为 0。设置完成如下图所示: 东南大学成贤学院毕业论文 - 30 - 图 3-30 开发板串口下载跳线设置 接着我们在 USB_232 处插入 USB 线,并接上电脑,如果之前没有安装 PL2303 的驱动(如果已 经安装过了驱动,则应该能在设备管理器里面看到 USB 串口,如果不能则要先卸载之前的驱动, 卸载完后重启电脑(必要步骤),再重新安装我们提供的驱动),则电脑会提示找到新硬件,如下 图所示: 图 3-31 找到新硬件 我们不理会这个提示,直接找到光盘-软件文件夹下的 PL-2303 驱动,安装该驱动。在驱动安 装完成之后,拔掉 USB 线,然后重新插入电脑,此时电脑就会自动给其安装驱动了。在安装完成之 后,可以在电脑的设备管理器里面找到 USB 串口(如果找不到,则重启下电脑),如下图所示: 图 3-32 USB 串口驱动安装成功 东南大学成贤学院毕业论文 - 31 - 上图中我们显示的 USB 串口为 COM5,不同电脑可能不一样,可能是 COM4、COM6 等,但是 Prolific USB-to-Serial Comm Port,这个一定是一样的,如果没找到,则有可能是安装有误或者 系统不兼容。 在安装了 USB 串口驱动之后,我们就可以开始串口下载程序了,这里我们的串口下载软件选择 的是 mcuisp,该软件属于第三方软件,由单片机在线编程网提供,大家可以去 免 费下载,目前最新版本为 V0.993。该软件启动界面如下: 图 3-33 mcuisp 启动界面 然后我们选择要下载的 HEX 文件,以前面我们新建的工程为例,因为我们前面的工程没有在 KEIL 里面设置生成.hex 文件,所以在 USER 文件夹下是找不到.hex 文件的。下面我们看看如何设 置:先在工程里面点击,打开 Output 选项卡,勾选 Create HEX File 选项,如下图所示: 图 3-34 MDK 设置生成 HEX 文件 图中选中第二个红圈内的选项,可以使编译器产生浏览信息,方便快速查看函数和变量等,这 点在后面会介绍。选中之后点击 OK,重新编译,编译结果如下图所示: 东南大学成贤学院毕业论文 - 32 - 图 3-35 重新编译结果 从上图中可以看到,编译器已经产生了 hex 文件了,然后我们打开 USER 文件夹,看看里面发 生了什么变化?如下图所示: 图 3-36 新编译生成文件 从上图可以看到,重新编译产生了很多文件,其中就有我们所需要的 hex 文件(图中红圈圈中) ,至此,我们就可以开始下载了。用 mcuisp 软件打开 USER 文件夹,找到 TEST.hex,打开并进行 相应设置后,如下图所示: 图 3-37 mcuisp 设置 东南大学成贤学院毕业论文 - 33 - 图 3-37 中红圈圈中的设置,是我们建议的设置。编程后执行,这个选项在无一键下载功能的 条件下是很有用的,当选中该选项之后,可以在下载完程序之后自动运行代码。否则,下载代码之 后,必须先将 B0 连接 GND,再按复位键,才能开始运行刚刚下载的代码。硬件板虽然自带了一键 下载功能,但是还是建议选上这个设置。 编程前重装文件,该选项也比较有用,当选中该选项之后,mcuisp 会在每次编程之前,将 hex 文件重新装载一遍,这对于代码调试的时候是比较有用的。 最后,我们选择的 DTR 的低电平复位,RTS 高电平进 BootLoader,这个选择项选中,mcuisp 就会通过 DTR 和 RTS 信号来控制板载的一键下载功能电路,以实现一键下载功能。如果不选择,则 无法实现一键下载功能。这个是必要的选项(在 BOOT0 接 GND 的条件下)。 在装载了 hex 文件之后,我们要下载代码还需要选择串口,这里 mcuisp 有智能串口搜索功能。 每次打开 mcuisp 软件,软件会自动去搜索当前电脑上可用的串口,然后选中一个作为默认的串口 (一般是您最后一次关闭时所选则的串口)。也可以通过点击菜单栏的搜索串口,来实现自动搜索 当前可用串口。串口波特率则可以通过 bps 那里设置,对于 STM32,该波特率最大为 230400bps, 这里我们一般选择最高的波特率:460800,让 mcuisp 自动去同步。搜索完串口之后界面如下图所 示: 图 3-38 搜索串口 从之前 USB 串口的安装可知,开发板的串口被识别为 COM5 了,所以我选择 COM5。选择了相应 串口之后就可以通过按”开始编程(P)”这个按钮,一键下载代码到 STM32 上,下载成功后如下 图所示: 东南大学成贤学院毕业论文 - 34 - 图 3-39 下载完成 上图中,我用圈圈圈出了 mcuisp 对一键下载电路的控制过程,其实就是控制 DTR 和 RTS 电平 的变化,控制 BOOT0 和 RESET,从而实现自动下载。另外界面提示已经下载完成(如果老提示:开 始连接,需要检查一下,开发板的设置是否正确,是否有其他因素干扰等),并且从 0X80000000 处开始运行了,我打开串口调试助手选择 COM5,会发现从硬件板发回来的信息,如下 图所示: 图 3-40 程序开始运行了 接收到的数据和我仿真的是一样的,证明程序没有问题。至此,说明下载代码成功了,并且也 从硬件上验证了代码的正确性。 东南大学成贤学院毕业论文 - 35 - 第四章 程序设计与调试 4.1 系统描述 本系统采用基于 ARM Cortex-M3 内核的 STM32 作为主控制器,外扩 SD 卡以及 TFT 彩屏。系统 通过文件系统读取 SD 卡内存储的 BMP、JPEG、JPG 格式图片,把多幅图片以幻灯片的形式从 TFT 屏 上显示出来。同时,通过 STM32 内部的 RTC 模块使系统具有掉电不遗失日期及时钟的功能。系统框 图如图 4-1 所示。 图 4-1 系统框图 4.2 软件设计 4.2.1 文件读取 本设计需要用到 FAT(FAT16/32)文件系统来读取 SD 卡上的字库和 UNICODE 到 GBK 的转换码表 到 W25X16 部分,因此要重点介绍 FAT 文件系统。FAT 文件系统本身比较复杂,所以这里只简单介 绍一下。 常用的文件系统有 FAT12/16/32 等,FAT12 是最古老的文件系统,只能管理 8M 左右的空间, 现在基本淘汰了。FAT16 则可以管理 2G 的空间(通过特殊处理也能管理 2G 以上的空间),而 FAT32 则能管理到 2TB(2048GB)的空间。FAT32 较 FAT16 的优势还在于 FAT32 采用了更小的簇,可以更 有效的保存信息,而不会造成较多的浪费。 XP 在 SD 卡里面建立的文件系统最常用的也就是 FAT16 和 FAT32。这是由 XP 在格式化 SD 卡的 时候建立的,通常 SD 卡上的数据信息由 MBR、DBR、FAT、FDT 和数据区 5 个部分组成(有的也没有 MBR)。我们以 FAT32 为例做介绍。 MBR 称为主引导记录区,该区存储了分区表等信息,位于 SD 卡的扇区 0(物理扇区),在其分 区信息里面记录了 DBR 所在的位置,SD 卡一般只会有一个分区,所以也就只要找到分区 1 的 DBR 所在位置就可以了。 DBR 称为操作系统引导记录区,如果没有 MBR,那么 DBR 就位于 0 扇区,如果有则必须通过 MBR 区得到 DBR 所在的地址,然后读出 DBR 信息。在 DBR 区,我们可以知道每个扇区所占用的字节 数、每个簇的扇区数、FAT 表的份数、每个 FAT 表的扇区数、跟目录簇号、FAT 表 1 所在的扇区等 一系列非常重要的信息。 FAT 称为文件分配表(FAT 表),一般一个卡上会存在 2 个 FAT 表,一个用作备份,一个用作 使用。FAT 表一般紧随 DBR,另一个 FAT 表则紧随第一个 FAT 表,这样只要知道了第一个 FAT 表的 位置及大小,那么第二个 FAT 表的位置也就确定了。FAT 表记录了每个文件的位置和区域,是一种 链式结构,FAT 以“F8 FF FF 0F FF FF FF FF”这样的 8 个字节为表头,用以表示 FAT 表的开始, 后面的数据每四个字节为一个簇项(从第 2 簇开始),用来标记下一个簇所在的位置,这样每个位 置都存储了下一个簇,只要按着这个表走,就可以找到文件的所有内容。如果找到下一个簇位置, 里面记录的是“FF FF FF 0F”,代表这个文件到此就结束了,没有后续簇了,这样一个文件的读 东南大学成贤学院毕业论文 - 36 - 取就结束了。 FDT 称为文件根目录表,这个区域固定为 32 个扇区,假设每个扇区为 512 个字节,那么更目 录下最多存放 512 个文件(假设都用短文件名存储,每个短文件名占 32 个字节)。 文件目录表是另一个重要的部分,FAT 文件系统中(仅以短文件名介绍),文件目录项在目录 表下以 32 个字节的方式记录,各字段定义如下: 表 4.1 文件目录项各字节定义 从上表可知,我们在文件的目录项就可以找到该文件的其实簇,然后在 FAT 表里面找到该簇开 始的下一个簇,依次读取这些簇就可以把整个文件读出来了。 4.2.2 图像解码与显示 4.2.2.1 BMP 文件格式 BMP 是一种与硬件设备无关的图像文件格式,使用非常广。它采用位映射存储格式,除了图像 深度可选以外,不采用其他任何压缩,因此,BMP 文件所占用的空间很大。BMP 文件的图像深度可 选 lbit、4bit、8bit 及 24bit。BMP 文件存储数据时,图像的扫描方式是按从左到右、从下到上的 顺序。典型的 BMP 图像文件由三部分组成:位图文件头数据结构,它包含 BMP 图像文件的类型、显 示内容等信息;位图信息数据结构,它包含有 BMP 图像的宽、高、压缩方法,以及定义颜色等信息。 部分代码: /BMP 信息头 typedef _packed struct DWORD biSize ; /说明 BITMAPINFOHEADER 结构所需要的字数。 LONG biWidth ; /说明图象的宽度,以象素为单位 LONG biHeight ; /说明图象的高度,以象素为单位 WORD biPlanes ; /为目标设备说明位面数,其值将总是被设为 1 WORD biBitCount ; /说明比特数/象素,其值为 1、4、8、16、24、或 32 DWORD biCompression ; /说明图象数据压缩的类型。其值可以是下述值之一: 东南大学成贤学院毕业论文 - 37 - DWORD biSizeImage ;/说明图象的大小,以字节为单位。当用 BI_RGB 格式时,可设置为 0 LONG biXPelsPerMeter ;/说明水平分辨率,用象素/米表示 LONG biYPelsPerMeter ;/说明垂直分辨率,用象素/米表示 DWORD biClrUsed ; /说明位图实际使用的彩色表中的颜色索引数 DWORD biClrImportant ; /说明对图象显示有重要影响的颜色索引的数目,如果是 0,表示 都重要。 BITMAPINFOHEADER ; /BMP 头文件 typedef _packed struct WORD bfType ; /文件标志.只对BM,用来识别 BMP 位图类型 DWORD bfSize ; /文件大小,占四个字节 WORD bfReserved1 ;/保留 WORD bfReserved2 ;/保留 DWORD bfOffBits ; /从文件开始到位图数据(bitmap data)开始之间的的偏移量 BITMAPFILEHEADER ; /彩色表 typedef _packed struct BYTE rgbBlue ; /指定蓝色强度 BYTE rgbGreen ; /指定绿色强度 BYTE rgbRed ; /指定红色强度 BYTE rgbReserved ;/保留,设置为 0 RGBQUAD ; /位图信息头 typedef _packed struct BITMAPFILEHEADER bmfHeader; BITMAPINFOHEADER bmiHeader; BITMAPINFO; /解码这个 BMP 文件 BOOL BmpDecode(FileInfoStruct *BmpFileName) u16 count; u8 rgb ,color_byte; u16 x ,y,color,tmp_color ; u16 uiTemp; /x 轴方向像素计数器 u16 countpix=0;/记录像素 u8 realx=0; u16 realy=0; /x,y 的实际坐标 u8 yok=1; 东南大学成贤学院毕业论文 - 38 - BITMAPINFO *pbmp;/临时指针 CurFile=BmpFileName; F_Open(CurFile);/打开文件 F_Read(CurFile,jpg_buffer);/读出 512 个字节 pbmp=(BITMAPINFO*)jpg_buffer;/得到 BMP 的头部信息 count=pbmp-bmfHeader.bfOffBits; /数据偏移,得到数据段的开始地址 color_byte=pbmp-bmiHeader.biBitCount/8;/彩色位 16/24/32 PICINFO.ImgHeight=pbmp-bmiHeader.biHeight;/得到图片高度 PICINFO.ImgWidth=pbmp-bmiHeader.biWidth; /得到图片宽度 /水平像素必须是 4 的倍数! if(PICINFO.ImgWidth*color_byte)%4) uiTemp=(PICINFO.ImgWidth*color_byte)/4+1)*4; else uiTemp=PICINFO.ImgWidth*color_byte; AI_Drow_Init();/初始化智能画图 /开始解码 BMP x =0 ; y=PICINFO.ImgHeight; rgb=0; realy=y*PICINFO.Div_Fac/10000; while(1) while(count3 ; color |= tmp_color; break ; case 1: tmp_color = jpg_buffercount2 ; tmp_color 3 ; tmp_color 5; tmp_color=6; color|=tmp_color; break ; case 1 : tmp_color=jpg_buffercount; tmp_color3; break ; case 1 : tmp_color=jpg_buffercount; tmp_color=2; color|=tmp_color=3; color|=tmp_color11; break ; case 3 :break ; 东南大学成贤学院毕业论文 - 40 - /位图颜色得到 rgb+; count+ ; if(rgb=color_byte) /水平方向读取到 1 像素数数据后显示 if(x=uiTemp)/水平方向像素值到了.换行 y-; if(y=PICINFO.ImgWidth) sizej=0; sizei+=SampRate_Y_V*8; if(sizej=0) return funcret; /智能画图 /FileName:要显示的图片文件 BMP/JPG/JPEG /(sx,sy) :开始显示的坐标点 /(ex,ey) :结束显示的坐标点 /图片在开始和结束的坐标点范围内显示 BOOL AI_LoadPicFile(FileInfoStruct *FileName,u16 sx,u16 sy,u16 ex,u16 ey) int funcret;/返回值 /得到显示方框大小 if(eysy)PICINFO.S_Height=ey-sy; else PICINFO.S_Height=sy-ey; 东南大学成贤学院毕业论文 - 43 - if(exsx)PICINFO.S_Width=ex-sx; else PICINFO.S_Width=sx-ex; /显示区域无效 if(PICINFO.S_Height=0|PICINFO.S_Width=0) PICINFO.S_Height=LCD_H; PICINFO.S_Width=LCD_W; return FALSE; /显示的开始坐标点 PICINFO.S_YOFF=sy; PICINFO.S_XOFF=sx; CurFile=FileName; /文件名传递 if(CurFile-F_Type=T_BMP)/得到一个 BMP 图像 funcret=BmpDecode(CurFile); /得到一个 BMP 图像 return funcret; else if(CurFile-F_Type=T_JPG|CurFile-F_Type=T_JPEG)/得到 JPG/JPEG 图片 F_Open(CurFile); /得到 JPEG/JPG 图片的开始信息 /开始时读入 1024 个字节到缓存里面.方便后面提取 JPEG 解码的信息 F_Read(CurFile,jpg_buffer); /读第一次 F_Read(CurFile,jpg_buffer+512);/读第二次 InitTable(); /初始化各个数据表 if(funcret=InitTag()!=FUNC_OK)return FALSE;/初始化表头不成功 if(SampRate_Y_H=0)|(SampRate_Y_V=0)return FALSE ;/采样率错误 AI_Drow_Init(); /初始化 PICINFO.Div_Fac,启动智能画图 funcret=Decode();/解码 JPEG 开始 else return FALSE; /非图片格式! if(funcret=FUNC_OK)return TRUE;/解码成功 else return FALSE; /解码失败 此部分代码包含了 JPEG/JPG 以及 BMP 的解码代码,解码通过 AI_LoadPicFile( )函数来实现, 在该函数里面先判断文件的类型,然后调用不同的解码函数,解码 JPEG 由 Decode( )函数实现, 而解码 BMP 则由 BmpDecode( )函数实现。AI_LoadPicFile( )函数会将图片以合适的大小显示在液 晶上(总是不会超过你给定的区域),对比输入尺寸大的图片,会自动压缩。解码图片完成后返回 解码是否成功的信息。 4.2.3 时钟显示 实时时钟(RTC)是一个独立的定时器。RTC 模块拥有一组连续计数的计数器,在相应软件配 置下,可提供时钟日历的功能。修改计数器的值可以重新设置系统当前的时间和日期。RTC 模块和 时钟配置系统(RCC_BDCR 寄存器)是在后备区域,即在系统复位或从待机模式唤醒后 RTC 的设置和 时间维持不变。但是在系统复位后,会自动禁止访问后备寄存器和 RTC,以防止对后备区域(BKP) 的意外写操作,所以在要设置时间之前,先要取消备份区域(BKP)写保护。 东南大学成贤学院毕业论文 - 44 - RTC 由两个主要部分组成(见下图 4.2)。第一部分(APB1 接口)用来和 APB1 总线相连。此单元 还包含一组 16 位寄存器,可通过 APB1 总线对其进行读写操作。APB1 接口由 APB1 总线时钟驱动, 用来与 APB1 总线连接。 另一部分(RTC 核心)由一组可编程计数器组成,分成两个主要模块。第一个模块是 RTC 的预分 频模块,它可编程产生最长为 1 秒的 RTC 时间基准 TR_CLK。RTC 的预分频模块包含了一个 20 位的 可编程分频器(RTC 预分频器)。如果在 RTC_CR 寄存器中设置了相应的允许位,则在每个 TR_CLK 周 期中 RTC 产生一个中断(秒中断)。第二个模块是一个 32 位的可编程计数器,可被初始化为当前的 系统时间,一个 32 位的时钟计数器,按秒钟计算,可以记录 4294967296 秒,约合 136 年左右,作 为一般应用,这已经是足够了的。 RTC 还有一个闹钟寄存器 RTC_ALR,用于产生闹钟。系统时间按 TR_CLK 周期累加并与存储在 RTC_ALR 寄存器中的可编程时间相比较,如果 RTC_CR 控制寄存器中设置了相应允许位,比较匹配 时将产生一个闹钟中断。 图 4-2 RTC 简化框图 RTC 内核完全独立于 RTC APB1 接口,而软件是通过 APB1 接口访问 RTC 的预分频值、计数器值 和闹钟值的。但是相关可读寄存器只在 RTC APB1 时钟进行重新同步的 RTC 时钟的上升沿被更新, RTC 标志也是如此。这就意味着,如果 APB1 接口刚刚被开启之后,在第一次的内部寄存器更新之 前,从 APB1 上的 RTC 寄存器值可能被破坏了(通常读到 0)。因此,若在读取 RTC 寄存器曾经被 禁止的 RTC APB1 接口,软件首先必须等待 RTC_CRL 寄存器的 RSF 位(寄存器同步标志位,bit3) 被硬件置 1。 接下来,我们介绍一下 RTC 相关的几个寄存器。首先要介绍的是 RTC 的控制寄存器,RTC 总共 有 2 个控制寄存器 RTC_CRH 和 RTC_CRL,两个都是 16 位的。RTC_CRH 的各位描如下 东南大学成贤学院毕业论文 - 45 - 图 4-3 寄存器 RTC_CRH 各位描述 该寄存器用来控制中断的,我们将要用到秒钟中断,所以该寄存器必须设置最低位为 1,以允 许秒钟中断。我们再看看 RTC_CRL 寄存器。该寄存器各位描述如下图所示: 图 4-4 寄存器 RTC_CRL 各位描述 本设计我们用到的是该寄存器的 0、35 这几个位,第 0 位是秒钟标志位,我们在进入闹钟中 断的时候,通过判断这位来决定是不是发生了秒钟中断。然后必须通过软件将该位清零(写 0)。 第 3 位为寄存器同步标志位,我们在修改控制寄存器 RTC_CRH/CRL 之前,必须先判断该位,是否已 东南大学成贤学院毕业论文 - 46 - 经同步了,如果没有则等待同步,在没同步的情况下修改 RTC_CRH/CRL 的值是不行的。第 4 位为配 置标位,在软件修改 RTC_CNT/RTC_ALR/RTC_PRL 的值的时候,必须先软件置位该位,以允许进入配 置模式。第 5 位为 RTC 操作位,该位由硬件操作,软件只读。通过该位可以判断上次对 RTC 寄存器 的操作是否完成,如果没有,我们必须等待上一次操作结束才能开始下一次操作。 第二个要介绍的寄存器是 RTC 预分频装载寄存器,也有 2 个寄存器组成,RTC_PRLH 和 RTC_PRLL。这两个寄存器用来配置 RTC 时钟的分频数的,比如我们使用外部 32.768K 的晶振作为时 钟的输入频率,那么我们要设置这两个寄存器的值为 32767,以得到一秒钟的计数频率。RTC_PRLH 的各位描述如下: 图 4-5 寄存器 RTC_PRLH 各位描述 RTC_PRLL 的各位描述如下: 图 4-6 寄存器 RTC_PRLL 各位描述 在介绍完这两个寄存器之后,我们介绍 RTC 预分频器余数寄存器,该寄存器也有 2 个寄存器组 成 RTC_DIVH 和 RTC_DIVL,这两个寄存器的作用就是用来获得比秒钟更为准确的时钟,比如可以得 到 0.1 秒,或者 0.01 秒等。该寄存器的值是自减的,用于保存还需要多少时钟周期获得一个秒信 号。在一次秒钟更新后,由硬件重新装载。这两个寄存器和 RTC 预分频装载寄存器的各位是一样 的,这里我们就不列出来了。 接着要介绍的是 RTC 最重要的寄存器,RTC 计数器寄存器。该寄存器由 2 个 16 位的寄存器组 成 RTC_CNTH 和 RTC_CNTL,总共 32 位,用来记录秒钟值(一般情况下)。此两个计数器也比较简 单,我们也不多说了。注意一点,在修改这个寄存器的时候要先进入配置模式。 最后我们介绍 RTC 部分的最后一个寄存器,RTC 闹钟寄存器,该寄存器也是由 2 个 16 为的寄
展开阅读全文