基于STM32单片机的万年历设计毕业设计论文
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
本科生毕业论文(或设计)
(申请学士学位)
论文题目基于STM32单片机的万年历设计
毕业设计(论文)原创性声明和使用授权说明
原创性声明
本人郑重承诺:所呈交的毕业设计(论文),是我个人在指导教师的指导下进行的研究工作及取得的成果。
尽我所知,除文中特别加以标注和致谢的地方外,不包含其他人或组织已经发表或公布过的研究成果,也不包含我为获得及其它教育机构的学位或学历而使用过的材料。
对本研究提供过帮助和做出过贡献的个人或集体,均已在文中作了明确的说明并表示了谢意。
作者签名:日期:
指导教师签名:日期:
使用授权说明
本人完全了解大学关于收集、保存、使用毕业设计(论文)的规定,即:按照学校要求提交毕业设计(论文)的印刷本和电子版本;学校有权保存毕业设计(论文)的印刷本和电子版,并提供目录检索与阅览服务;学校可以采用影印、缩印、数字化或其它复制手段保存论文;在不以赢利为目的前提下,学校可以公布论文的部分或全部内容。
作者签名:日期:
学位论文原创性声明
本人郑重声明:所呈交的论文是本人在导师的指导下独立进行研究所取得的研究成果。
除了文中特别加以标注引用的内容外,本论文不包含任何其他个人或集体已经发表或撰写的成果作品。
对本文的研究做出重要贡献的个人和集体,均已在文中以明确方式标明。
本人完全意识到本声明的法律后果由本人承担。
作者签名:日期:年月日
学位论文版权使用授权书
本学位论文作者完全了解学校有关保留、使用学位论文的规定,同意学校保留并向国家有关部门或机构送交论文的复印件和电子版,允许论文被查阅和借阅。
本人授权大学可以将本学位论文的全部或部分内容编入有关数据库进行检索,可以采用影印、缩印或扫描等复制手段保存和汇编本学位论文。
涉密论文按学校规定处理。
作者签名:日期:年月日
导师签名:日期:年月日
注意事项
1.设计(论文)的内容包括:
1)封面(按教务处制定的标准封面格式制作)
2)原创性声明
3)中文摘要(300字左右)、关键词
4)外文摘要、关键词
5)目次页(附件不统一编入)
6)论文主体部分:引言(或绪论)、正文、结论
7)参考文献
8)致谢
9)附录(对论文支持必要时)
2.论文字数要求:理工类设计(论文)正文字数不少于1万字(不包括图纸、程序清单等),文科类论文正文字数不少于1.2万字。
3.附件包括:任务书、开题报告、外文译文、译文原文(复印件)。
4.文字、图表要求:
1)文字通顺,语言流畅,书写字迹工整,打印字体及大小符合要求,无错别字,不准请他人代写
2)工程设计类题目的图纸,要求部分用尺规绘制,部分用计算机绘制,所有图纸应符合国家技术标准规范。
图表整洁,布局合理,文字注释必须使用工程字书写,不准用徒手画
3)毕业论文须用A4单面打印,论文50页以上的双面打印
4)图表应绘制于无格子的页面上
5)软件工程类课题应有程序清单,并提供电子文档
5.装订顺序
1)设计(论文)
2)附件:按照任务书、开题报告、外文译文、译文原文(复印件)次序装订
3)其它
目录
摘要 (1)
Abstract (1)
1绪论 (2)
1.1 研究背景及意义 (2)
1.2 国内外研究现状 (2)
1.3 论文主要内容 (2)
2系统硬件电路设计 (3)
2.1单片机开发板的介绍 (3)
2.2硬件电路总体结构设计 (4)
2.3 硬件电路各单元电路设计 (4)
2.3.1 按键电路的设计 (4)
2.3.2 显示电路的设计 (5)
3系统软件设计 (6)
3.1 RealView MDK3.80简介 (6)
3.2 软件总体设计 (6)
3.3 TFT-LCD显示程序设计 (7)
3.4 时钟程序设计 (8)
3.5 汉字显示程序 (10)
3.6 图片显示程序 (11)
3.7 按键功能程序 (11)
4系统调试 (12)
结论 (14)
参考文献 (14)
附录一 (15)
程序列表 (15)
主程序 (15)
TFT-LCD显示程序 (21)
时钟程序 (24)
汉字显示程序 (29)
图片显示程序 (31)
按键程序 (36)
致谢 (39)
基于STM32单片机的万年历设计
摘要:随着现代社会生活和工作节奏的加快,及时准确的掌握时间变得越来越重要。
STM32包含Cortex-M3内核,具有低功耗、低成本、丰富的片内外设以及处理速度快等特点。
本文采用STM32F103RBT6作为主控制器,利用其内部的实时时钟(RTC)在相应软件的配置下,设计了具有时间显示功能的电子万年历,可提供24小时制的实时时钟和区分平、闰年的日历。
测试表明该设计计时准确、界面美观、操作简便。
关键词:万年历;STM32F103RBT6;TFTLCD;Cortex-M3;RTC
Calendar Design Based On STM32 Microcontroller
Abstract:With the development of modern society, the accelerated pace of life and work,to grasp time timely and accurately becomes more and more important. STM32 contains the Cortex-M3 kernel, with low power consumption, low cost, rich on-chip and high processing speed. This paper uses STM32F103RBT6 as the main controller, using real time clock the internal (RTC) with the corresponding software configuration, designs electronic calendar with the function of time display, and it can provide 24 hour real-time clock and the calendar which can distinguish the flat year or the leap year. The test shows that the design of accurate timing, beautiful interface, and easy operation.
Key words: Calendar; STM32F103RBT6; TFTLCD; Cortex-M3; RTC
1 绪论
1.1 研究背景及意义
对于时间这个概念一开始在长达几千年的时间里,根本就没有任何测定时间的精确方法。
人类得知时间是通过太阳在天空的位置,或者是通过日晷或沙漏这样的仪器来大致的判断一下时间。
在中国历史上就出现日晷、沙漏、机械钟、石英钟,这几种计时装置。
二十一世纪的今天科技与经济迅速发展,人们的生活节奏变得越来越快,生活水平越来越高,对于生活的品味和质量的要求也更高。
人们不再满足于只能提供简单计时功能的时钟,希望在能保证计时精确的基础上能多添加一些其它功能,诸如日历、星期的显示,使其界面能够更加的美丽。
目前电子万年历成了现代社会中的主要计时工具之一,广泛应用于社会生活需要的各个方面。
它集时钟、日期、星期等功能于一体,具有显示直观、读取方便、界面简洁、功能多样等优点,符合目前电子计时仪器的发展趋势。
电子万年历不仅在市场上占据重要的位置,在学习中尝试制作一款功能新颖的万年历也是一个热门的课题。
此课题具有很好的开放性和发挥性,在制作过程中既巩固了单片机方面的知识,也开放了思维,将自身的想法实现于多彩功能的万年历中,这是对制作者本身能力的一种培养和锻炼。
1.2 国内外研究现状
由于大规模的电子集成电路的应用,电子万年历在当今社会钟表界中独占鳌头。
我国生产的电子万年历有很多种,总体上来说以研究多功能电子万年历为主,所以在生产的电子万年历上除了具有基本的显示时间、日期功能外,增添其它的一些附属功能如闹铃、报警等功能后,生产商在其质量、价格、外观、实用上做功课。
不断的改进万年历产品,使其更具有市场需求。
就目前市场上出现的各种万年历,第一种是纯硬件电路系统,采用分离式硬件电路分别实现各种功能,时钟的功能通过时序逻辑电路来实现,这将导致电路复杂化、整体可靠性变差、不灵活。
很难实现对系统的扩展。
第二种是通过可编程逻辑器件来实现的,与前者相比在可靠性和实现时钟的功能方面要有所提升,但这显示功能只能通过数码管来实现,使其显示的效果不明显。
同时在灵活性方面还是不行,很难对其进行扩展功能的实现。
第三种相比前两种而言在各个方面都有所提高,这也是现在商家们致力发展的方法,使用单片机作为核心控制系统,这样整个系统就可编程了,大大增加了灵活性,智能化的液晶显示使其显示界更加清楚、简洁。
同时,可以实现其它的一些额外功能如遥控调试、语音报时等功能。
1.3 论文主要内容
本文主要介绍以STM32F103RBT6单片机为核心部件来设计一款电子万年历,以其内部的RTC 模块作为时钟,用TFTLCD液晶显示器作为显示模块,时钟电路能够准确提供24小时制时间、平年闰年的判断、星期的判断。
采用RealView MDK3.80进行编写调试程序,以STM32单片机开发板为硬件平台进行设计,最终实现在TFTLCD上显示开机画面、时间、日期、星期、机械时钟以及汉字。
2 系统硬件电路设计
2.1 单片机开发板的介绍
本设计采用的是ALIENTEK MiniSTM32的开发板,如图2-1所示。
图2-1 STM32开发板
它包含一个USB转串口(用于程序的下载)、一个USB串口1(用于与PC端进行通信)、两个LED灯、一个标准的JTAG调试口、一个复位(RESET)按键、一个WK_UP按键、两个普通按键、一个开关按钮、一个W25X16 16M FLASH存储芯片、一个2.4寸/2.8寸通用LCD接口、一个开发板的核心部件STM32F103RBT6。
其中核心部件STM32微控制器是由ST(意法半导体)公司推出的第一个基于ARM Cortex-M3内核的控制器,STM32凭借其产品线的多样化、极高的性价比、低功耗,迅速成为当前微控制器产品中的一颗最闪亮的新星。
Cortex-M3内部的数据路径是32 位的,寄存器是32 位的,存储器接口也是32 位的。
CM3 采用了哈佛结构,拥有独立的指令总线和数据总线,可以让取指与数据访问互不干扰。
这样一来数据访问不再占用指令总线,从而提升了性能。
另外基于ARM Cortex-M3 STM32可以采用固件库的开发方式,不需要再熟悉底层寄存器,大大宿短了开发周期而且Thumb‐2 指令集为编程带来了更多的灵活性。
STM32已经广泛应用于工业控制、低功耗、家用电器、建筑与安防及计算机通信网络等领域。
MCU的部分原理图如图2-2所示。
图2-2 MCU部分原理图
上图中中上部的BOOT1用于设置STM32的启动方式,其对应启动模式如下表2-1所示。
表2-1 BOOT0与BOOT1的启动模式
BOOT0 BOOT1 启动模式说明
0 X 用户闪存存储器用户闪存存储器,也是FLSAH启动
1 0 系统存储器系统存储器启动,用于串口下载
1 1 SRAM启动器SRAM启动,用于在SRAM中调试代码
2.2 硬件电路总体结构设计
本设计采用STM32F103RBT6作为MCU,由内部实时时钟(RTC)实现日历功能,利用独立按键进行调整时间,通过TFT-LCD液晶显示器来显示开机画面、日历、汉字。
硬件电路的总体设计方案如图2-3。
独立按键
STM32F103R
BT6主控制器
TFT-LCD
显示
图2-3 总体结构设计框图
2.3 硬件电路各单元电路设计
2.3.1 按键电路的设计
本设计使用到开发板上两个按键,其原理图如图2-4所示。
图2-4 按键输入原理图
KEY0和KEY1用作普通按键输入,分别接在PA13和PA15上,由于他们都与JTAG共用同一个引脚,所以在使用KEY0和KEY1两个按键时要特别注意不能使用JTAG来调试,另外KEY0和KEY1还和PS/2的DA T和CLK共用,他们都是通过JTAG的上拉电阻来提供上拉的。
2.3.2 显示电路的设计
该设计的显示部分采用的是TFTLCD液晶显示模块,它可以显示16位的真彩图片,TFT-LCD 即薄膜晶体管液晶显示器,是英文名Thin Film Transistor-Liquid Crystal Display的字头缩写。
TFT-LCD技术是将微电子技术与液晶显示器技术进行巧妙的融合。
人们通过在Si上进行微电子精细加工这一项技术,实现了在大面积的玻璃上进行TFT阵列的加工,再通过已经成熟的LCD技术将该阵列基板与另一片带彩色滤色膜的基板进行相结合从而形成一个液晶盒,其次经过多到工序如偏光片贴覆等过程,最后形成液晶显示器(屏)。
TFT-LCD中的TFT相当于一个开关管,它可以有效地克服在非选通时出现的串扰,使得液晶显示屏的静态特性与扫描线数无关,从而大大提高的显示的质量。
本次采用的是2.8寸的ALIENTEK TFT-LCD模块,分辨率为320*240,该液晶显示器的控制器为ILI9320。
其模块接口如图2-5。
图2-5 TFTLCD模块接口图
该模块采用的是80并口方式与外部链接的,80并口有如下一些连接线:
CS:TFTLCD片选信号。
WR:向TFTLCD写入数据。
RD:从TFTLCD中读取数据。
D[15:0]:16位双向数据线。
RST:硬复位TFTLCD。
RS:命令/数据标志(0:读写命令1:读写数据)。
硬件部分对应的IO口连接为:
LCD_LED对应PC10;
LCD_CS对应PC9;
LCD_RS对应PC8;
LCD_WR对应PC7;
LCD_RD对应PC6;
LCD_D[17:1]对应PB[15:0];
3 系统软件设计
系统软件设计主要包括主程序、TFTLCD显示子程序、按键子程序、时钟配置子程序等。
整个系统的功能的实现是由硬件电路与软件相互配合来完成的,由于各功能的硬件部分电路连接已经完成了,在进行软件编程时只需要根据硬件电路的连接方式进行操作即可。
整套程序采用的是固件库的开发方式,所以不需要再去了解各个寄存器的配置,其中占据主导地位的主函数主要负责合理的调用各个子程序,使其完成所需的功能。
各个子程序主要负责完成相应部分的实际所要的功能,如汉字显示的程序、图片显示的程序、时钟显示的程序等等。
3.1 RealView MDK3.80简介
RealView MDK开发套件来自德国的Keil公司,是ARM公司目前为了针对各种嵌入式处理器而新推出的一款软件开发工具。
RealView MDK拥有业内最领先的技术,包含μVision3集成开发环境和RealView编译器。
能够支持ARM7、ARM9并拥有最新的Cortex-M3内核处理器,具有自动配置启动代码、集成Flash烧写模块、强大的Simulation设备模拟、性能分析等功能,相比ARM之前的工具包ADS等,RealView编译器的新版本可将性能提升20%。
RealView MDK具有的几大突出特性:
(1)启动代码生成向导,自动引导。
(2)软件模拟器,完全脱离硬件的软件开发过程。
(3)性能分析器,看的更远、看的更细、看的更清。
(4)Cortex-M3支持。
3.2 软件总体设计
主程序是通过调用LCD子程序、RTC时钟子程序、汉字显示子程序、按键功能子程序以及图片显示子程序等来实现显示开机动画、汉字、机械钟表、时间、日期、星期于一体的功能。
主程序流程图如图3-1。
图3-1主程序流程图
3.3 TFT-LCD显示程序设计
显示部分程序的设计步骤为,先确定TFT-LCD于STM32的IO口连接方式;然后初始化TFT-LCD即向内写入一系列的设置程序,来启动TFT-LCD的显示;之后对显示部位进行相关的配置;最后进行显示并可以配置相关的背景。
程序流程图如图3-2。
图3-2 TFT-LCD显示程序流程图
3.4 时钟程序设计
基于ARM Cortex-M3内核的STM32其本身包含一个独立的定时器——实时时钟(RTC),由于其拥有一组连续的计数器这一特性,我们就可以通过在相应软件的配置下,来实现时钟日历的功能。
若想重新设置系统当前的时间和日期,则可通过修改计数器值的方法来实现。
该款单片机的RTC模块和时钟配置系统(RCC_BDCR寄存器)处于后备区域(BKP),这将导致系统复位或从待机模式中唤醒后,对后备寄存器和RTC的访问被禁止,之前对RTC模块的设置和时间会不会出现变化。
其优点在于防止对于后备区域意外的写操作。
RTC的组成包含两个部分,第一部分是APB1接口,除了用于和APB1总线相连,还包含一组16位的寄存器,是通过APB1总线来对其进行读写操作。
这一部分是由APB1总线时钟驱动来与APB1总线接口的。
第二部分是RTC核心,由一组可编程计数器组成,主要分为两个模块:RTC预分频模块和一个32位的可编程计数器。
其中RTC预分频模块包含一个20位的可编程分频器被称作为RTC预分频器,如果在RTC_CR寄存器中将相应的位设置为允许位,就会在每个TR_CLK周期RTC产生一个秒中断。
模块二可以被初始化为当前的系统时间,将系统的时间按TR_CLK周期累加并与存储在RTC_ALR寄存器中的可编程时间进行比较,如果RTC_CR控制寄存器相应位设置成允许位,在比较匹配时就会产生一个闹钟中断。
总体来说RTC包含以下几个特性:
(1)可编程的预分频系数最高可达2^20。
(2)2个分离的时钟:PCLK1和RTC时钟(RTC时钟的频率必须要小于PCLK1时钟频率的1/4以上)。
(3)可用于较长时间段进行测量的32位可编程计数器。
(4)包含三种RTC的时钟源:HSE时钟除以128;LSE低速外部时钟;LSI低速内部时钟。
(5)由系统复位的APB1接口而RTC核心(预分频器、闹钟、计数器和分频器)只能由后备域复位,这两者之间是相互独立。
(6)专门的可屏蔽中断包含3个:闹钟中断—用来产生一个软件可编程的闹钟中断;秒中断—用来产生一个可编程的周期性中断信号(最长可达1秒);溢出中断—指示内部可编程计数器溢出并回转为0的状态。
RTC的简化框图如图3-3。
图3-3 RTC框图
在进行编写RTC时钟程序时是以1970年1月1日为基准,来把输入的时间转换为秒钟,程序编写的合法年份是1970-2099年。
星期的判断是利用蔡勒(Zeller)公式:w=y+[y/4]+[c/4]-2c+[26(m+1)/10]+d-1,式中的符号含义如下w:星期;c:世纪-1;y:年(后两位数);m:月(m大于等于3,小于等于14,即在蔡勒公式中,某年的1、2月要看作上一年的13、14月来计算,比如2003年1月1日要看作2002年的13月1日来计算);d:日;[ ]代表取整,即只要整数部分。
将算出来的w除以7(若算出的w是负数则将w加7直至w大于零后再除以7),余数是几就是星期几。
如果余数是0,则为星期日。
时钟的程序流程图如图3-4。
图3-4 时钟程序流程图
3.5 汉字显示程序
在液晶屏上显示汉字的原理显示字符大致是一样的。
在液晶屏上显示的汉字其实就是由点亮的点组成的。
这就类似于我们在纸上书写汉字一样,所写字都是由沾在纸上的墨汁组成的。
所以当我们知道所要显示汉字的点阵数据后就可以知道该汉字的生成方法,再通过相应的程序即可在屏幕上显示出该汉字了。
本次设计中显示汉字的点阵数据是通过一款名为PCtoLCD2002的软件生成的,再通过相关显示程序显示的。
所要显示的汉字为点阵16×16的
“李杨自动化2班”和点阵24×24的“滁州学院2010届”。
汉字显示程序流程图如图3-5。
图3-5 汉字显示程序流程图
3.6 图片显示程序
JPEG是目前网上最流行的一种图片存储格式,它可以把文件压缩到最小格式,但在压缩过程图像中重复或不重要的资料会丢失,很容易造成图片损伤,被称为有损压缩格式。
它是“联合照片专家组(Joint Photographic Expert Group)”的英文缩写,文件后缀名通常为“.jpg”或“.jpeg”。
本设计中的几幅图片的数据是通过一款名为Image2lcd的图片解码工具实现的。
图片显示程序的流程图如图3-6。
图3-6 图片显示程序
3.7 按键功能程序
根据STM32开发板中所要用到的两个按键的硬件电路连接方式,进行编写程序。
在编写程序时应注意按键的消抖。
在进行扫描某个按键时,该按键按下后进行按下的时间长短判断,然后根据按键按下的时间长短来实现同一个按键的不同功能,此种方法的优点是可以节省所需按键的数量和IO口。
此次使用的两个按键(KEY0、KEY1)功能分别是,当按键按下时长未超过3秒,两个按键分别执行的功能是进行时和分加一,超过3秒则执行时和分减一,因秒的修改无多大实际用途程序中就没有进行判断了。
按键功能程序流程图如图3-7。
图3-7 按键功能程序
4 系统调试
程序调试主要以软件调试和在开发板上进行实际运行两种方式相结合。
软件调试是先在RealView MDK3.80上进行程序的编写、调试,找出程序中命令的错误并修改。
当软件调试无错误后生成“万年历.HEX”文件,再将此文件通过串口线利用串口下载软件(mcuisp)烧录到开发板的STM32F103RBT6芯片上,观察运行结果是否和自己期望的结果相同,如若不同可找到程序中该不同的部分进行修改,直至达到自己的要求。
实际运行效果如图4-1、图4-2。
图4-1 开机画面
开机过后显示此画面,它是由四幅不同的图片组成,5秒过后会显示时钟等,如图4-2。
图4-2 时钟等显示画面
在屏幕顶端中间显示汉字点阵为24×24的“滁州学院2010届”,格式为红色、加粗、宋体;字体下方显示一个机械时钟表,三个指针根据时间而变化;接下来显示的是日期、星期、电子时钟;最后在屏幕右下角显示汉字点阵为16×16的制作者信息。
结论
本次设计的万年历系统采用了模块化设计方式,以单片机STM32F103RBT6作为主控制模块、TFT-LCD作为液晶显示模块、内部的RTC时钟作为实时时钟模块。
整体程序的开发方式是基于固件库的,每一个模块的程序逻辑清晰、目的明确、结构简单、易于编写、调试和修改。
程序可读性强,可以很方便对程序在保持主体不动的前提下进行局部修改以达到更好的显示效果。
通过本次设计可知采用STM32F103RBT6作为主控器件、TFT-LCD作为液晶显示、内部的RTC 时钟作为实时时钟的方式是可行。
而且该万年历具有计时准确、功耗低、反应快、等特点。
同时用TFT-LCD作为液晶显示模块使时间与图片等可以的直观清晰显示。
但由于毕业设计时间有限,本设计还存在很多不足之处。
比如:整点报时、音乐闹铃等。
参考文献
[1] 吴明晖,徐睿.基于ARM的嵌入式系统开发与应用[M].北京:人民邮电出版社社,2004
[2] 赖于树.ARM微处理器与应用开发[M].电子工业出版社,2007
[3] 周立功等.ARM嵌入式系统基础教程[M].北京:北京航空航天大学出版社,2005.1
[4] 刘鹏程.基于ARM 的温度测量系统[ J].科技信息, 2008( 18): 77-78
[5] 李宁.基于MDK的STM32处理器开发应用[M].北京航空航天大学出版社,2008
[6] 彭刚,秦志强.基于ARM Cortex-M3的STM32系列嵌入式微控制器应用实践[M].北京:电子工
业出版社.2011
[7] 查荣. 基于单片机的多功能万年历设计[J].世界电子元器件,2012.41(3):137-139
[8] 刘火良,杨森.STM32库开发实战指南.第1版[M].机械工业出版社,2013:317-364
[9] 廖义奎.Cortex-M3之STM32嵌入式系统设计.第1版[M].北京:中国电力出版社.2012
[10] 滕振芳,张昆.基于单片机的电子万年历的设计[J].价值工程.2010:63-63
[11] STM icroe lectron ics Corporat ion, STM32F103XX Datashee t[ J] , 2007, 11
[12] Zhao Y u-mei; CHEN Fu-rong. Research on Key Technique of Lower Concentration S2- Sensor In Situ
Measurement [J]. OceanTechnology, 2008,27 (4) :33-35
附录一
程序列表
主程序
#include "delay.h"
#include "sys.h"
#include "usart.h"
#include "lcd.h"
#include "rtc.h"
#include "math.h"
#include "chinese.h"
#include "key.h"
#include "picture.h"
#define pi 3.141592654
const u8* Week[7]={"Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"}; int main(void)
{
extern const u8 picture1[];//图片数据(包含信息头),存储在picture1.c里面.
extern const u8 picture2[];
extern const u8 picture3[];
extern const u8 picture4[];
u8 l,i,t;
timer.w_year=2014;
timer.w_month=4;
timer.w_date=6;
timer.hour=18;
timer.min=44;
timer.sec=30;
delay_init(72); //延时初始化
NVIC_Configuration();
uart_init(9600);
LCD_Init();
RTC_Init();
KEY_Init();
picture_display(20,5,(u8*)picture1);//在指定地址显示图片picture_display(0,75,(u8*)picture2);
picture_display(110,95,(u8*)picture3);
picture_display(60,220,(u8*)picture4);
delay_ms(1000);
delay_ms(1000);
delay_ms(1000);
delay_ms(1000);
delay_ms(1000);
LCD_Clear(WHITE);
POINT_COLOR=RED;//设置字体为红色
Draw_Circle(120,110,55);
Draw_Circle(120,110,50);
LCD_ShowNum(115,40,12,2,12);
LCD_ShowNum(178,105,3,2,12);
LCD_ShowNum(113,170,6,2,12);
LCD_ShowNum(50,105,9,2,12);
for(i=0;i<60;i++)
{
u8 x1,y1,x2,y2;
if(i%5==0)
l=10;
else
l=5;
x1=50*sin(i*6*pi/180)+120;
y1=50*cos(i*6*pi/180)+110;
x2=(50-l)*sin(i*6*pi/180)+120;
y2=(50-l)*cos(i*6*pi/180)+110;
LCD_DrawLine(x1,y1,x2,y2);
}
//显示时间
POINT_COLOR=BLUE;//设置字体为蓝色
LCD_ShowString(80,190," - - ");
LCD_ShowString(80,226," : : ");
TEST_FONTT();
TEST_FONT();
while(1)
{
u8 x3,y3,x4,y4,x5,y5,x6,y6,x7,y7,x8,y8,x9,y9,s,m1,n1,m2,n2, hour;
POINT_COLOR=BLUE;//设置字体为蓝色
s=KEY_Scan();
if(s)
{
switch(s)
{
case 0: RCC_RTCCLKCmd(DISABLE);break;
case 1:
RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR|RCC_APB1Periph_BKP,ENABLE);
PWR_BackupAccessCmd(ENABLE);
BKP_WriteBackupRegister(BKP_DR1, 0X5A5A);
timer.hour=timer.hour+1;
if(timer.hour==24)
timer.w_date=timer.w_date+1;
x9=20*sin(((timer.hour-1)*60+timer.min)*(float)1/2*pi/180)+120; //时针(绿色)
y9=110-20*cos(((timer.hour-1)*60+timer.min)*(float)1/2*pi/180);
POINT_COLOR=WHITE;
LCD_Draw_wide(117,110,124,110,x9,y9);
if(timer.hour>=24)
timer.hour=0;
RTC_Init();
break;
case 2:
RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR|RCC_APB1Periph_BKP,ENABLE);
PWR_BackupAccessCmd(ENABLE);
BKP_WriteBackupRegister(BKP_DR1, 0X5A5A);
timer.min=timer.min+1;
POINT_COLOR=WHITE;
LCD_Draw_wide(118,110,123,110,x5,y5);
if(timer.min>=60)
timer.min=0;
RTC_Init();
break;
case 3:
RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR|RCC_APB1Periph_BKP,ENABLE);
PWR_BackupAccessCmd(ENABLE);
BKP_WriteBackupRegister(BKP_DR1, 0X5A5A);
if(timer.hour==0)
{
hour=24;
timer.hour=hour-1;
}
else
timer.hour=timer.hour-1;
if(timer.hour==23)
timer.w_date=timer.w_date-1;
m2=20*sin(((timer.hour+1)*60+timer.min)*(float)1/2*pi/180)+120; //时针(绿色)
n2=110-20*cos(((timer.hour+1)*60+timer.min)*(float)1/2*pi/180);
POINT_COLOR=WHITE;
LCD_Draw_wide(117,110,124,110,m2,n2);
RTC_Init();
break;
case 4:
RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR|RCC_APB1Periph_BKP,ENABLE);
PWR_BackupAccessCmd(ENABLE);
BKP_WriteBackupRegister(BKP_DR1, 0X5A5A);
if(timer.min==0)
{
min=60;
timer.min=min-1;
}
else
timer.min=timer.min-1;
m1=30*sin((timer.min+1)*6*pi/180)+120; //分针(蓝色)
n1=110-30*cos((timer.min+1)*6*pi/180);
POINT_COLOR=WHITE;
LCD_Draw_wide(118,110,123,110,m1,n1);
RTC_Init();
break;
}
}
if(t!=timer.sec)
{
t=timer.sec;
LCD_ShowNum(80,190,timer.w_year,4,16);
LCD_ShowNum(120,190,timer.w_month,2,16);
LCD_ShowNum(144,190,timer.w_date,2,16);
switch(timer.week)
{
case 0:
LCD_ShowString(80,208,"Sunday ");
break;
case 1:
LCD_ShowString(80,208,"Monday ");
break;
case 2:
LCD_ShowString(80,208,"Tuesday ");
break;
case 3:
LCD_ShowString(80,208,"Wednesday");
break;
case 4:
LCD_ShowString(80,208,"Thursday ");
break;
case 5:
LCD_ShowString(80,208,"Friday ");
break;
case 6:
LCD_ShowString(80,208,"Saturday ");
break;
}
LCD_ShowNum(80,226,timer.hour,2,16);
LCD_ShowNum(104,226,timer.min,2,16);
LCD_ShowNum(128,226,timer.sec,2,16);
x3=35*sin((timer.sec-1)*6*pi/180)+120; //秒针(深红)
y3=110-35*cos((timer.sec-1)*6*pi/180);
x4=35*sin(timer.sec*6*pi/180)+120;
y4=110-35*cos(timer.sec*6*pi/180);
POINT_COLOR=WHITE;
LCD_Draw_wide(119,110,122,80,x3,y3);
POINT_COLOR=BRED;
LCD_Draw_wide(119,110,122,80,x4,y4);
x5=30*sin((timer.min-1)*6*pi/180)+120; //分针(蓝色)
y5=110-30*cos((timer.min-1)*6*pi/180);
x6=30*sin(timer.min*6*pi/180)+120;
y6=110-30*cos(timer.min*6*pi/180);
POINT_COLOR=WHITE;
LCD_Draw_wide(118,110,123,110,x5,y5);
POINT_COLOR=BLUE;
LCD_Draw_wide(118,110,123,110,x6,y6);
x7=20*sin((timer.hour*60+timer.min-1)*(float)1/2*pi/180)+120; //时针(绿色)y7=110-20*cos((timer.hour*60+timer.min-1)*(float)1/2*pi/180);
x8=20*sin((timer.hour*60+timer.min)*(float)1/2*pi/180)+120;
y8=110-20*cos((timer.hour*60+timer.min)*(float)1/2*pi/180);
POINT_COLOR=WHITE;
LCD_Draw_wide(117,110,124,110,x7,y7);
POINT_COLOR=GREEN;
LCD_Draw_wide(117,110,124,110,x8,y8);
}
delay_ms(10);
};
}
TFT-LCD显示程序
由于TFT-LCD显示程序过多,下面仅列出其初始化的部分函数:
//初始化lcd
void LCD_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC|RCC_APB2Periph_GPIOB|RCC_APB2Pe riph_AFIO, ENABLE);
GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable , ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10|GPIO_Pin_9|GPIO_Pin_8|GPIO_Pin_7|GPIO_Pin_6;
//GPIO_Pin_10
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //推挽输出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOC, &GPIO_InitStructure);
GPIO_SetBits(GPIOC,GPIO_Pin_10|GPIO_Pin_9|GPIO_Pin_8|GPIO_Pin_7|GPIO_Pin_6);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_All;
GPIO_Init(GPIOB, &GPIO_InitStructure);
GPIO_SetBits(GPIOB,GPIO_Pin_All);
delay_ms(50); // delay 50 ms
LCD_WriteReg(0x0000,0x0001);
delay_ms(50); // delay 50 ms
DeviceCode = LCD_ReadReg(0x0000);
if(DeviceCode==0||DeviceCode==0XFFFF)//读到ID不正确
{
//可能是9341,尝试9341的ID读取
LCD_WR_REG(0XD3);
LCD_RD_DATA(); //dummy read
LCD_RD_DATA(); //读回0X00
DeviceCode=LCD_RD_DATA()&0XBF;//这里读回0XD3,实际是0X93才对.强制去掉第6位DeviceCode<<=8;
DeviceCode|=LCD_RD_DATA();
}
printf(" LCD ID:%x\r\n",DeviceCode); //打印LCD ID
if(DeviceCode==0X9341) //9341初始化
{
LCD_WR_REG(0xCF);
LCD_WR_DATA(0x00);
LCD_WR_DATA(0xC1);
LCD_WR_DATA(0X30);
LCD_WR_DATA(0x64);
LCD_WR_DATA(0x03);
LCD_WR_DATA(0X12);
LCD_WR_DATA(0X81);
LCD_WR_REG(0xE8);
LCD_WR_DATA(0x85);
LCD_WR_DATA(0x10);
LCD_WR_DATA(0x7A);
LCD_WR_REG(0xCB);
LCD_WR_DATA(0x39);
LCD_WR_DATA(0x2C);
LCD_WR_DATA(0x00);
LCD_WR_DATA(0x34);
LCD_WR_DATA(0x02);
LCD_WR_REG(0xF7);
LCD_WR_DATA(0x20);
LCD_WR_REG(0xEA);
LCD_WR_DATA(0x00);
LCD_WR_DATA(0x00);
LCD_WR_REG(0xC0); //Power control
LCD_WR_DATA(0x1B); //VRH[5:0]
LCD_WR_REG(0xC1); //Power control
LCD_WR_DATA(0x01); //SAP[2:0];BT[3:0]
LCD_WR_REG(0xC5); //VCM control
LCD_WR_DATA(0x30); //3F
LCD_WR_DATA(0x30); //3C
LCD_WR_REG(0xC7); //VCM control2
LCD_WR_DATA(0XB7);
LCD_WR_REG(0x36); // Memory Access Control LCD_WR_DATA(0x48);
LCD_WR_REG(0x3A);
LCD_WR_DATA(0x55);
LCD_WR_REG(0xB1);
LCD_WR_DATA(0x00);
LCD_WR_DATA(0x1A);
LCD_WR_REG(0xB6); // Display Function Control LCD_WR_DATA(0x0A);
LCD_WR_DATA(0xA2);
LCD_WR_REG(0xF2); // 3Gamma Function Disable LCD_WR_DATA(0x00);
LCD_WR_REG(0x26); //Gamma curve selected LCD_WR_DATA(0x01);
LCD_WR_REG(0xE0); //Set Gamma。