您好,欢迎来到汇智旅游网。
搜索
您的当前位置:首页基于STM32单片机LCD多级菜单的设计

基于STM32单片机LCD多级菜单的设计

来源:汇智旅游网


基于STM32单片机LCD多级菜单的设计

摘 要

本设计介绍了以ARM内核嵌入式处理器STM32为控制核心,辅以低功耗的液晶模块MFG240160-3-A,以及相应的按键控制电路,实现了LCD多级菜单的设计。在本系统中,侧重点在于LCD的显示上,因此此系统的硬件结构很简单,侧重点在于软件架构及程序的编写上,该系统程序量大,函数封装多,关于实时时钟信息、波形存储信息都留有相应的软件接口,以便与其它模块正确的相连接。本系统硬件电路简单,但显示信息丰富,可以移植到各种便携式的电子产品上去,为电子产品的显示界面的设计提供了一个新的思路。

关键词 STM32单片机;LCD多级菜单;低功耗;

Base on STM32 Microprocessor LCD modules in the multi-level menu display system Abstract

This design describes to STM32 embedded processor based on ARM core for control, coupled with low power consumption of LCD module MFG240160-3-A as well as the corresponding keys control circuitry, enabling multi-level menu design of LCD. In this system, the focus is on the LCD display, so this system hardware structure is very simple, the emphasis lies in software architectures and applications, the system capacity, function encapsulates the information about the real-time clock, waveform stored information will have the appropriate software interface so that correct with other modules that you are connecting to. This system is simple, but the display information-rich, portable to a

variety of portable electronic products, for electronic product display interface design provides a new train of thought.

Keywords: STM32; LCD multi-level menu; low-power; 目 录 摘 要

(((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((I

Abstract((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((II 前

言 ............................................................... 4 1 方案设计 ........................................................... 5

1.1 设计方案概述 ................................................. 5 1.2 电路介绍 ..................................................... 5 2 器件介绍 ........................................................... 9

2.1 STM32简介 .................................................... 9 2.2 MFG240160-3-A LCD介绍 ....................................... 13 3 软件设计 .......................................................... 16

3.1 STM32单片机的初始化 ......................................... 16 3.2 液晶屏的初始化 .............................................. 20 3.3 数据的传输 .................................................. 20 3.4 字模的提取 .................................................. 21 3.5 菜单框架的设计 .............................................. 23 3.6 字模库的建立 ................................................ 25 3.7 函数库的封装 ................................................ 25 3.8 菜单标记 .................................................... 26

3.9 时钟信息的显示 .............................................. 27 3.10 波形的显示 ................................................. 28 4 结论 .............................................................. 30 参考文献 ............................................................ 31 致 谢 ............................................ 错误~未定义书签。27

前 言

随着人们生活水平的提高,人们对生活质量的要求也越来越高。对电子产品的要求也越来越苛刻。特别是对便携式电子产品,不仅要求功能全,性能好,还必须具有超低的功耗。“又要让马儿跑,又不让马儿吃草”,这条理念在电子产品中体现得淋漓尽致。处理器必须在不怎么增加主频和功耗的条件下干更多的活儿,这就要求我们在设计电子产品中必须抛弃那些传统的、功耗大的单片机及其它设备,选择当前先进的、超低功耗的单片机及IC,以满足人们的需要。这也符合我国正在提出的低碳生活要求。

对于各种便携式的电子产品,最重要的莫过于界面的显示。一个信息量丰富的显示界面绝对是吸引人们注意力的一大因素。但在现实的生活当中,特别是在一些中低档的便携式电子产品中,信息的显示都是一些显示信息量非常小的液晶模块或单调的LED数码管显示。这完全不能满足人们的信息需求。特别是对中高端的电子产品,三、四级的菜单随处可以。菜单的界面可以给予人们丰富的信息,便于人们进行各种操作。低功耗加上信息丰富的液晶显示是未来电子产品发展的主流。本文主要介绍基于STM32低功耗单片机和液晶模块组成的多级菜单显示系统。符合现代电子产品发展的主流,通过简单的修改就可以在各种平台上进行移植,具有很强的实用性。

本文主要是针对便携式的电子产品的显示界面做一个探讨。主要是针对某医疗电子公司的手掌式心电图机的界面进行设计。

1 方案设计 1.1 设计方案概述

方案以STM32单片机系统为核心,通过按键控制LCD液晶显示模块进行各种信息的显示,包括实时的时钟显示、实时的波形显示、存储的波形显示以及各种菜单的显示。如图1.1所示,该方案通过按键对各种菜单进行操作以执行相应的功能。本系统结构简单,但程序却并不简单,需要大量的编程操作才能完成。

按键控制 液晶显示模块 单 片 机 电 源

图1.1 系统整体方案 1.2 电路介绍 1(电源电路 5VVCC U113INOUT ADJ 2LM117LH

C21C23C24C22CapCap2Cap2Cap0.1uF10uF10uF0.1uF 图1.2 电源电路

该模块主要由USB下载线提供5V的电源供电。然后通过LM117降压到3.3V供单片机工作。

2(电源滤波电路

滤波电路设计如图1.3所示。由于采用STM32单片机内部的AD进行数据的采 集,因此良好的滤波电路是必要的。同时也为单片机的稳定工作奠定了基础。

VCC

C33C34C35C36C37C38C39C40C41C42C43 CapCapCapCapCapCapCapCapCapCapCap

100nF100nF100nF100nF100nF100nF100nF100nF100nF100nF100nF 图1.3 滤波电路 3(STM32最小系统 VCC

R3Res110KM1MENU3456DB0RESTPA0PG0057DB1PG01DOWN10087DB2PA8PG0288DB3PG03S1OK117DB4PD3PG04SW-PB90DB5PG05C3UP791DB6PC13PG06Cap292DB7PG07100nF77WRPD087178RSTVSS_1PD09107VSS_214381CSVSS_3PD123885RSVSS_4PD1416STM32F103ZEBT86RDVSS_5PD15C151VSS_6Cap61232VSS_7OSC_INR1Y120pF83C?VSS_8Res1XTAL9424VSS_9OSC_OUT10MC21201VSS_10Cap2Cap1306VCC8MVSS_11VBAT100pF20pF7225RESTVDD_1REST108VDD_2C51448VDD_3PC14/OSC32_INCap392VDD_4Y220pF179VDD_5PC15/OSC32_OUTXTAL52VDD_6C6621VDD_7Cap8432.768KVDD_820pF95VDD_9121VDD_10131VCCVDD_11

138BOOT048PB02/BOOT1 STM32F103ZEBT

图1.4 单片机最小系统

该模块主要由以下几个部分组成:

系统的启动配置,在STM32F10XXX里,可以通过BOOT,1:0,引脚选择三种不同的启动模式。如表1-1所示。

根据选定的启动模式,主闪存存储器、系统存储器或SRAM可以按照以下方式访问:从主闪存存储器启动:主闪存存储器被映射到启动空间(0x0000 0000),但仍

然能够在它原有的地址(0x0800 0000)访问它,即闪存存储器的内容可以在两个地址区域访问,0x0000 0000或0x0800 0000。

表1-1 启动方式配置

启动模式选择管脚 启动模式 说明 BOOT1 BOOT0 用户闪存存储器被选为启动X 0 用户闪存存储器 区域 0 1 系统存储器 系统存储器被选为启动区域 1 1 内嵌SRAM 内嵌SRAM被选为启动区域

从系统存储器启动:系统存储器被映射到启动空间(0x0000 0000),但仍然能够在它原有的地址(0x1FFF F000)访问它。

从内置SRAM启动:只能在0x2000 0000开始的地址区访问SRAM。 注意: 当从内置SRAM启动,在应用程序的初始化代码中,必须使用NVIC的异常表和偏移寄存器,从新映射向量表之SRAM中。

在这里,我们选择从用户闪存存储器里启动的方式。即从FLASH中启动。 时钟源电路:OSC_IN,OSC_OUT引脚连接的是外部的高速时钟。通过内部的倍频器倍频到72MHZ高速时钟。OSC32_IN,OSC32_OUT引脚连接的是LSE时钟。LSE晶体是一个32.768kHz的低速外部晶体或陶瓷谐振器。它为实时时钟或者其他定时功能提供一个低功耗且精确的时钟源。

STM32单片机的每个GPI/O端口有两个32位配置寄存器(GPIOx_CRL,GPIOx_CRH),两个32位数据寄存器(GPIOx_IDR,GPIOx_ODR),一个32位置位/复位寄存(GPIOx_BSRR),一个16位复位寄存器(GPIOx_BRR)和一个32位锁定寄存器(GPIOx_LCKR)。 根据数据手册中列出的每个I/O端口的特定硬件特征, GPIO端口的每个位可以由软件分别配置成多种模式。 输入浮空、 输入上拉、 输

入下拉、 模拟输入 、开漏输出、 推挽式输出 、推挽式复用功能 、开漏复用功能, 每个I/O端口位可以自由编程,然而I/0端口寄存器必须按32位字被访

问(不允许半字或字节访问)。GPIOx_BSRR和GPIOx_BRR寄存器允许对任何GPIO寄存器的读/更改的访问;这样,在读和更改访问之间产生IRQ时不会发生危险。 这样大大方便了我们对IO口的编程,可以根据我们的需要来配置不同的IO功能,节省了引脚资源。我们也可以通过设置IO口的输出频率,如表1-2所示,可以根据不同的需要设置不同的IO口速率。

表1-2 IO输出配置 MODE[1:0] 意义 00 保留

01 最大输出速度为10MHZ 10 最大输出速度为2MHZ 11 最大输出速度为50MHZ 4(液晶模块的硬件连接 L1

LCDMFG240*160

DDC01234567DVLCDVS+VS-VB0-VB1-VB1+VB0+VVSSNBM0CS0CWR1WR0RSTDDDDDDDD 12345670123456701234111111111122222 VCCRSSDCRRWRSTDB0DB1DB2DB3DB4DB5DB6DB7

C53Cap4.7uFR50C52C51Res1CapCapC3.3M330nF0.22uFCap4.7uF 图1.5 液晶硬件电路

该模块主要采用内部升压的模式给LCD供电。据此电路图我们可知:如果内部升压成功,则根据如表1-3所示的寄存器配置,测得C51两端电压应该是6.1V-17.986V。根据寄存器的配置不同,VLCD脚对应不同的电压。这可以作为我们初始化液晶是否成功的一个判据。

表1-3 LCD温度补偿配置

BR Cv0(V) Cpm(mV) PM_reg Vlcd(V) 0 6(1 5 6(1 11(22 255 9(015 0 12(157 10 12(157 22(26 255 17(833 0 13(369 11 13(369 24(45 255 17(991 0 14(580 12 14(580 26(61 255 17(986 2 器件介绍 2.1 STM32简介

Cortex-M3是一个32位处理器内核。内部的数据路径是32位的,寄存器是32位的,存储器接口也是32位的。CM3采用了哈佛结构,拥有的指令总线和数据总线,可以让取指与数据访问并行不悖。这样一来数据访问不再占用指令总线,从而提升了性能。为实现这个特性, CM3内部含有好几条总线接口,每条都为自己的应用场合优化过,并且它们可以并行工作。比较复杂的应用可能需要更多的存储系统功能,为此CM3提供一个可选的MPU,而且在需要的情况下也可以使用外部的cache。另外在CM3中,Both小端模式和大端模式都是支持的。

CM3内部还附赠了好多调试组件,用于在硬件水平上支持调试操作,如指令断点,数据观察点等。另外,为支持更高级的调试,还有其它可选组件,包括指令跟踪和多种类型的调试接口。它的内部结构图如图2.1所示:

Cortex-M3

处理器内核系统 外中断

寄存器组 跟踪 指信号组 取跟中令指踪断解信号 单接控跟码元口控踪 算术逻辑单元 器 制系器统

存储器接口

指令总线存储器保护单元 数据总线 总线互连网络 调试接口 调试 线

信号

指令存储器 存储器系统和外设 私有外设 图2.1 STM32内核结构 STM32特征如下: 1(内核

(1) ARM 32位的Cortex?-M3 CPU;

(2) 72MHz,1.25DMips/MHz,零等待周期的存储器; (3) 单周期乘法和硬件除法。 2(存储器

(1) 从32K字节至128K字节的闪存程序存储器; (2) 从6K字节至K字节的SRAM。 3(时钟、复位和电源管理

(1) 2.0至3.6伏供电和I/O管脚;

(2) 上电/断电复位(POR/PDR)、可编程电压监测器(PVD); (3) 内嵌4至16MHz高速晶体振荡器; (4) 内嵌经出厂调校的8MHz的RC振荡器; (5) 内嵌40kHz的RC振荡器; (6) PLL供应CPU时钟;

(7) 带校准功能的32kHz RTC振荡器。 4(低功耗

为了使功耗更低,以及能源利用效率更高,Cortex-M3在设计时加入了很多 针对性的功能。

首先,在节能模式上,它提供了睡眠模式和深度睡眠模式。芯片以及整个系统在设计时通过与内核的节能模式相呼应,就可以根据应用的要求,在空闲时降低功

耗。第二,它精练的设计使得门数很低,并且在工作状态下电路的活动更少,所以CM3自己也是“身先士卒”地以身作则了。而且,由于CM3的程序代码密度高,程序容量也可以变得更少;同时,再加上它强大的性能减少了程序执行时间,使得系统能以最快的速度回到睡眠中,以削低对能源的用量。

它可以工作在这三种模式:睡眠、停机和待机模式,并且可以在这三种模式下动态切换。

睡眠模式: 在睡眠模式,只有CPU停止,所有外设处于工作状态并可在发生中断事件时唤醒CPU。

停机模式: 在保持SRAM和寄存器内容不丢失的情况下,停机模式可以达到最低的电能消耗。在停机模式下,停止所有内部1.8V部分的供电,PLL、HSI和HSE的RC振荡器被关闭,调压器可以被置于普通模式或低功耗模式。 可以通过任一配置成EXTI的信号把微控制器从停机模式中唤醒,EXTI信号可以是16个外部I/O口之一、PVD的输出、RTC闹钟或USB的唤醒信号。

待机模式: 在待机模式下可以达到最低的电能消耗。内部的电压调压器被关闭,因此所有内部1.8V部分的供电被切断;PLL、HSI和HSE的RC振荡器也被关闭;进入待机模式后,SRAM和寄存器的内容将消失,但后备寄存器的内容仍然保留,待机电路仍工作。 从待机模式退出的条件是:NRST上的外部复位信号、IWDG复位、WKUP管脚上的一个上升边沿或RTC的闹钟到时。

综上所述,Cortex-M3的能效要高于大多的8位或16位单片机。 5(ADC(模拟/数字转换器)

STM32F103xx增强型产品内嵌2个12位的模拟/数字转换器(ADC),每个ADC有多达16个外部通道,可以实现单次或扫描转换。在扫描模式下,转换在选定的一组模拟输入上自动进行。ADC接口上额外的逻辑功能允许:

(1) 同时采样和保持;

(2) 交叉采样和保持; (3) 单次采样。

ADC可以使用DMA操作。模拟看门狗功能允许非常精准地监视一路、多路或 所有选中的通道,当被监视的信号超出预置的阀值时,将产生中断。由标准定时器(TIMx)和高级控制定时器(TIM1)产生的事件,可以分别内部级联到ADC的开始触发、外部触发和DMA触发,以使应用程序能同步AD转换和时钟。 STM32F103xx增强型产品:ADC时钟为56MHz时为1μs(ADC时钟为72MHz为1.17μs)。

6(DMA

(1) 7通道DMA控制器;

(2) 支持的外设:定时器、ADC、SPI、I2C和USART。 7(多达80个快速I/O口

26/37/51/80个多功能双向5V兼容的I/O口所有I/O口可以映像到16个外部中断,所有端口都有外部中断能力。为了使用外部中断线,端口必须配置成输入模式。

8(定时器

(1) 多达3个16位定时器,每个定时器有多达4个用于输入捕获/输出比较/PWM或脉冲计数的通道;

(2) 16位6通道高级控制定时器; (3) 多达6路PWM输出;

(4) 死区控制、边缘/中间对齐波形和紧急制动; (5) 2个看门狗定时器(的和窗口型的); (6) 系统时间定时器:24位自减型。 9(通信接口

(1) 多达2个I2C接口(SMBus/PMBus);

(2) 多达3个USART接口,支持ISO7816,LIN,IrDA接口和调制解调; (3) 控制多达2个SPI同步串行接口(18兆位/秒); (4) CAN接口(2.0B 主动); (5) USB 2.0全速接口。 10(中断处理功能

(1) 内建的嵌套向量中断控制器支持多达240条外部中断输入。向量化的中断功能剧烈地缩短了中断延迟,因为不再需要软件去判断中断源。中断的嵌套也是在硬件水平上实现的,不需要软件代码来实现。

(2) Cortex-M3在进入异常服务例程时,自动压栈了R0-R3, R12, LR, PSR 和PC,并且在返回时自动弹出它们,既加速了中断的响应,也再不需要汇编语言代码了。

(3) NVIC支持对每一路中断设置不同的优先级,使得中断管理极富弹性。最粗线条的实现也至少要支持8级优先级,而且还能动态地被修改。

(4) 优化中断响应还有两招,它们分别是“咬尾中断机制”和“晚到中断机制”。

(5) 有些需要较多周期才能执行完的指令,是可以被中断,继续的——就好比它们是一串指令一样。这些指令包括加载多个寄存器(LDM),存储多个寄存器(STM),多个寄存器参与的PUSH,以及多个寄存器参与的POP。

(6) 除非系统被彻底地锁定,NMI(不可屏蔽中断)会在收到请求的第一时间予以响应。对于很多安全-关键(safety-critical)的应用,NMI都是必不可少的(如化学反应即将失控时的紧急停机)。

11(调试支持

(1) 在支持传统的JTAG基础上,还支持更新更好的串行线调试接口;

(2) 基于CoreSight调试解决方案,使得处理器哪怕是在运行时,也能访问处理器状态和存储器内容;

(3) 内建了对多达6个断点和4个数据观察点的支持;

(4) 可以选配一个ETM,用于指令跟踪。数据的跟踪可以使用DWT; (5) 在调试方面还加入了以下的新特性,包括fault状态寄存器,新的fault异常,以及闪存修补 (patch)操作,使得调试大幅简化;

(6) 可选ITM模块,测试代码可以通过它输出调试信息,而且“拎包即可入住”般地方便使用。

2.2 MFG240160-3-A LCD介绍 1(升压模式

MFG240160-3-A是信利公司生产的一款240x160内部带升压的液晶模块,通过设置内部的寄存器,可以设置内部升压方式或外部升压方式,这样可以方便进行外部电路的连接,不需要外接高电压。因此,对于低电压、低功耗的电子产品来说,无疑是最好的选择。如表2-1所示,当PC[1]=1时,选择外部电压驱动;当

PC[1]=0时,选择内部升压方式。 表2-1 LCD升压模式配置

Action C/D W/R D7 D6 D5 D4 D3 D2 D1 D0 PC[1:0] 0 0 0 0 1 0 1 0 PC1 PC0

它的内部升压模块为低功耗,低电压设计奠定了基础。 2(扫描方式

本液晶模块通过配置内部的寄存器可以设置多种扫描方式,例如:横向扫描、纵向扫描、反向横向扫描、反向纵向扫描,多种扫描方式让该液晶模块可以更灵活的被利用,可以方便的应用到各种场合。

另外,通过设置其它内部的寄存器还可以设置该液晶模块的局部扫描,即不通过刷整屏的方式去显示信息。这样,大大降低了功耗,节省了单片机的资源,简化了编程的难度,让该液晶模块在图形处理方面更有优势,通过灵活的运用局部扫描方式,可以进行各种画点画线的功能,不用建立大量的字模库,大大降低了单片机内部的RAM资源,因此可以方便的在各种内部RAM资源少的单片机上开发信息丰富的显示界面。

3(温度补偿

该液晶模块还具有温度补偿的功能,也可以通过设置内部寄存器去配置,如表2-2所示,让该液晶模块在恶劣的条件更能出色的发挥它的性能,大大提高了该液晶模块的抗干扰能力。

表2-2 温度补偿配置

Action C/D W/R D7 D6 D5 D4 D3 D2 D1 D0 TC[1:0] 0 0 0 0 1 0 0 1 TC1 TC0

可以通过设置TC[1:0]的值来设置液晶模块的温度系数,通过TC[1:0]的值可以设置不同的温度系数。一般来说,我们通常取默认的值即可。如表2-3所示。

表2-3 温度补偿对比 TC1 TC0 温度系数 0 0 -0.00%/? 0 1 -0.05%/? 1 0 -0.15%/? 1 1 -0.25%/? 4(颜色模式

该液晶模块的内部控制器UC1698是一个彩色屏的控制芯片。在这里用来去控制点阵屏,因此需要在颜色模式上进行一下转变。它主要有两种模式:4K模式和

K模块。在这里,我们主要介绍4K模式。由于该液晶模块内部RAM是16位的,但最高4位未用。余下的12位需要一个半字节的数据写入才能填满其内部RAM,如表2-4所示。所以在4K模式8位数据模式下,每次向LCD内部RAM进行数据写入时,需要最少进行三个字节的读写,否则会出现个别点无法显示的情况。

表2-4 LCD内部RAM结构

X X X X R3 R2 R1 R0 G3 G2 G1 G0 B3 B2 B1 B0 数据读写的顺序如表2-5所示: 表2-5 数据读写顺序 数据读写顺序D[7:0] (8位)

第1次数据写 R3 R2 R1 R0 G3 G2 G1 G0 第2次数据写 B3 B2 B1 B0 R3 R2 R1 R0 第3次数据写 G3 G2 G1 G0 B3 B2 B1 B0

如上图我们可知,如果要显示一个点,需要把其对应的四位置1,也就是说,每个字节中的四位对应一个点的显示。例如:我们如果要显示第一个点,只需要写入0XF0即可;如果要显示第二个点,则需要写入0X0F;如果要显示第三个点,则我们需要第一次送入0X00,第二次送入0XF0;在这里我们必须注意:只有把LCD内部的RAM填满之后点才能显示,也就是说,我们要显示第一个点,也必须把第二个点第三个点也同时显示出来,这样才把内部的第一个RAM填满,但由于数据的传输是八位的数据,每次要传输一个半字节才能显示出来三个点,所以我们的最小传输单位是三个字节,也就是六个点。这样可能为以后的波形的显示带

来也麻烦,这个问题我们将在软件部分给予解决。 3 软件设计

3.1 STM32单片机的初始化 1(STM32单片机的时钟配置

在STM32的时钟配置方面,ST公司已经为我们提供了例程,我们只需要在例程中修改相应的数据达到我们想要的时钟速率即可,不必要我们自己再去编写程序配置时钟,这样大大减少了我们的开发周期,提高了我们的开发效率。例如:

void RCC_Configuration(void) {

/* RCC system reset(for debug purpose) */ RCC_DeInit(); /* Enable HSE */

RCC_HSEConfig(RCC_HSE_ON); /* Wait till HSE is ready */

HSEStartUpStatus = RCC_WaitForHSEStartUp(); if(HSEStartUpStatus == SUCCESS) {

/* Enable Prefetch Buffer */

FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable); /* Flash 2 wait state */

FLASH_SetLatency(FLASH_Latency_2); /* HCLK = SYSCLK */

RCC_HCLKConfig(RCC_SYSCLK_Div1); /* PCLK2 = HCLK */

RCC_PCLK2Config(RCC_HCLK_Div1); /* PCLK1 = HCLK/2 */

RCC_PCLK1Config(RCC_HCLK_Div2); /* PLLCLK = 8MHz * 9 = 72 MHz */

RCC_PLLConfig(RCC_PLLSource_HSE_Div1, RCC_PLLMul_9); /* Enable PLL */ RCC_PLLCmd(ENABLE);

/* Wait till PLL is ready */

while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET) { }

/* Select PLL as system clock source */ RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK); /* Wait till PLL is used as system clock source */ while(RCC_GetSYSCLKSource() != 0x08) { } } }

我们可以通过更改RCC_PLLMul_9这个参数就可以设置我们想要的时钟频率。 为了减少功耗,STM32为每个外设都配备了一个时钟源,当我们需要打开外设时,我们需要首先打开外设的时钟,然后再使能外设。通过这种方式,可以大大的减少单片机的功耗。在这个系统中,因为我们需要软件模拟INTEL的8080时序,所以我们需要将用到的IO的时钟源打开,这样我们才可以使用IO。

2(STM32的启动方式

前面介绍过,STM32单片机有三种不同的启动模式,根据不同的启动模式我们需要编写不同的代码以及在编译环境上进行不同的设置。ST公司提供了这样的一个例程:

void NVIC_Configuration(void) {

#ifdef VECT_TAB_RAM

/* Set the Vector Table base location at 0x20000000 */ NVIC_SetVectorTable(NVIC_VectTab_RAM, 0x0); #else /* VECT_TAB_FLASH */

/* Set the Vector Table base location at 0x08000000 */ NVIC_SetVectorTable(NVIC_VectTab_FLASH, 0x0); #endif }

这个例程就是针对不同的启动模式而进行编写的。如果我们要在内部RAM中进行程序的调试,首先我们需要根据下表3-1所示的表进行STM32单片机外部引脚的配置,然后我们需要在Keil3的IDE中进行设置。

表3-1 系统启动方式配置

启动模式选择管脚 启动模式 说明 BOOT1 BOOT0 用户闪存存储器被选为启动X 0 用户闪存存储器 区域 0 1 系统存储器 系统存储器被选为启动区域 1 1 内嵌SRAM 内嵌SRAM被选为启动区域

在Keil中必须进行如下的设置,这样才可以正确的编译程序,让程序在STM32单片机内部的RAM中运行。如图3.1所示。

这样编译器会把中断向量表定位到内部RAM的起始地址,也就是0x20000000的地址空间。如果我们程序比较大,在内部RAM中调试已经不能满足我们的需要,则我们需要在FLASH中调试程序,配置方法同在内部RAM中调试的方法一样。

图3.1 配置Keil在RAM中调试 3(STM32的中断

STM32的中断功能十分强大,它的中断可以分为五组,如表3-2所示: 表3-2 优先级配置 NVIC优先级组 描述

先占优先级0位 NVIC_PriorityGroup_0 从优先级4位 先占优先级1位 NVIC_PriorityGroup_1 从优先级3位 先占优先级2位 NVIC_PriorityGroup_2 从优先级2位 先占优先级3位 NVIC_PriorityGroup_3 从优先级1位 先占优先级4位 NVIC_PriorityGroup_4 从优先级0位

先占优先级的级别最高,从优先级次之。通过把中断分进一个组,然后设置每个中断在每个组中的优先级次序就可以达到中断优先级响应的目的。通过不同的排列可以选择不同的优先级次序。

STM32所有端口都有外部中断能力。为了使用外部中断线,端口必须配置成 输入模式。外部中断/事件控制器由19个产生事件/中断要求的边沿检测器组成。每个输入线可以地配置输入类型(脉冲或挂起)和对应的触发事件(上升沿

或下降沿或者双边沿都触发)。每个输入线都可以被的屏蔽。挂起寄存器保持着状态线的中断要求。在此系统,我们必须把PA0,PA8,PD3,PC13配置成输入模式,因为每个按键外部都接有上拉电阻,所以对应的触发事件我们配置成下降沿儿触发,IO配置为输入浮空或输入上拉模式。这样单片机中断可以有效的检测到外部电平的变化情况,及时的产生中断请求。

4(IO口的配置

前面已经介绍过,STM32的IO口有八种输入输出模式,我们可以根据不同的需要配置成不同的端口状态。在此系统中,四个按键需要单片机的中断处理,所以这四个按键配置成输入浮空或输入上拉模式。对于PG,PD端口,主要是液晶的数据线和控制线。所以我们只用把它们配置成输出推挽方式,增大IO口的驱动能力。

3.2 液晶屏的初始化

该屏仅支持INTEL的8080时序,如图3.2所示。STM32的最高主频是72MHZ。所以,我们在编写程序的时候一定要注意时序的问题。注意操作中的延时问题。否则,程序写进去了液晶屏可能不会有任何反应~在液晶屏初始化时,必须严格按照液晶屏内部的控制芯片的时序来写。这样才不会盲头绪,找不到是硬件出问题还是软件出问题,良好的编程思想可以大大节约我们的编程周期。

图3.2 Intel 8080时序 3.3 数据的传输

由于该液晶的驱动芯片是一个RGB彩色屏的驱动芯片来驱动一个点阵屏,导致向其写数据稍微复杂一些。它内部RAM为16位,但是它的高四位并没有用。

所以我们在采用8位的数据传输方式时,必须考虑到内部RAM的特殊性。即我们必须每次写3个字节6个点。这样,内部RAM才会显示,否则,将出现部分点显示不全的现象~也就是说,在写列数时,必须以6倍数去写。如果用16位数据传输,则每次只用写一次数据,每次数据为一个半字节,显示3个点,这样我们可以不必每次写6个点,每次可以写3个点。

3.4 字模的提取

由于该屏在列方向上一次要写六点,即三个字节。所以我们在用字模软件取字模时,一定要注意这样的问题,以保证程序编写的方便。比如说,如果我们用横向取模的方式,每次得判断一个字节,即八个点,但是列方向上我们只能六个点六个点的去写。所以,横向取模的方式是不可取的。在纵向取模的方式中,我们应该取字模列方向是六的倍数。比如12、18、24等。在行方向上,我们尽量取八的倍数。这样在编写程序时,极大的降低了程序编写的难度。比如我们取“中国”这两个汉字的字模,我们取24*24的。在字模软件中,我们设置这样的取模方式:纵向取模、字节正序。可以编写这样的程序来达到在液晶上显示的目的。

for(k = 0;k < 3;k++) {

for(j = 0;j < 8;j++) {

for(i = m;i < m + 24;i++ )//先取前24个字节 24*24 {

if(reverse == 1) {

temp = ~(p[i]);//取第一个字节 } else {

temp = p[i];//取第一个字节 }

if((temp&value) == value)//如果最高位是1 {

buffer_msb = 0xf0; //buffer 高四位为1,显示黑点 } else {

buffer_msb = 0x00;//buffer 高四位为0,显示白点 } i = i++;

if(reverse == 1) {

temp = ~(p[i]);//取第二个字节 } else {

temp = p[i];//取第二个字节 }

if((temp&value) == value)//如果最高位是1

{

buffer_lsb = 0x0f; //buffer 高四位为1,显示黑点 } else {

buffer_lsb = 0x00;//buffer 高四位为0,显示白点 }

buffer = buffer_msb | buffer_lsb; WriteDat(buffer); }

value = value >> 1; }

m = m + 24; value = 0x80; }

首先定义一个缓冲区,该缓冲区有两部分组成:buffer_msb,buffer_lsb。该程序有三个循环:最内的循环是先取这24个字节的最高位,然后判断这24个字节的第一个字节的最高位是0或者是1。如果是0,则buffer_msb = 0xf0,否则buffer_msb = 0x00;然后再判断这24个字节的第二个字节的最高位是0还是1。如果是0,则buffer_lsb = 0x0f,否则buffer_lsb = 0x00;然后buffer = buffer_msb | buffer_lsb;这样就组成了一个新的值buffer。然后就把这个新值送给液晶。相当于一次送了两个点。次循环是把这24个字节从高位依次显示到最低位。外边的大循环是显示几行,对于这个函数来说,就是24行。这样就可以把这个字模完整的显示到液晶中去了。

3.5 菜单框架的设计

由于该系统涉及到的菜单级数比较多,多达四级的菜单。所以我们在设计菜单的整体框架时要考虑到这些因素。不能一个屏一个框架,这样我们的单片机可能没有那么多的空间让我们去建立那么多的框架字模库。当然这个屏提供的各种扫描方式也为我们在设计框架时提供了方便。例如我们在画一条线时,我们只需要设置行的起始地址和结束地址是一个值,然后改变列的地址我们就可以得到一条想要的直线。例如:在0x1c行画一条直线,该屏的起始列地址是0x18,列地址从0x18到0x67共80大列,因为每次写是以三个点为单位的,所以这一条直线是从第一列到最到一列。

//配置窗口

WriteCmd(0xf5); //set row start address WriteCmd(0x1c); //start address=0x00 WriteCmd(0xf7); //set row end address WriteCmd(0x1c); //row end address 0x1c = 28 WriteCmd(0xf4); //set oolumn start address WriteCmd(0x18); //start address=0 WriteCmd(0xf6); //set column end address WriteCmd(0x67); //窗口内部编程

WriteCmd(0xf8); //inside mode for(i = 0;i < 120;i++) {

WriteDat(0xff); }

如果要画一条竖线,则可以通过如下的配置: WriteCmd(0x75 ); //set row MSB address WriteCmd(0x ); //set row LSB address

WriteCmd(0x14); //set column MSB address 列的起始地址 WriteCmd(0x0b); //set column LSB address //配置窗口

WriteCmd(0xf5); //set row start address WriteCmd(0x); //start address=0x00 WriteCmd(0xf7); //set row end address WriteCmd(0x); //row end address

WriteCmd(0xf4); //set oolumn start address WriteCmd(0x4b); //start address=0 WriteCmd(0xf6); //set column end address WriteCmd(0x67); // //窗口内部编程

WriteCmd(0xf8); //inside mode for(i = 0;i < 42;i++) {

WriteDat(0xff); }

可以设置列的起始地址和结束地址是同一个地址,即三小列。所以这一条竖线可以说是一条横向为三个像素的直线。但因为我们前五个点都是白点,只有最后一个点是黑点,所以我们在视觉上看起来像是一条竖线。

3.6 字模库的建立

因为本系统需要进行RTC时钟的显示和FLASH存储器中数据记录的读取,所以我们需要建立一个数字的字模库,以匹配RTC时钟或FLASH存储器区域中的数据显示。另外,本系统也涉及到了大量的字体的显示,单独的为每一个字体都写一个函数是不现实的。所以我们需要在设计字符的字模库时尽量用一个相同的框架,然后用一个公用的函数去调用各个字库,这样可以减少程序的复杂性,减轻程序员的工作量。

3.7 函数库的封装

由于该系统涉及到大量的函数调用,程序量相当大,这对单片的的存储空间是一个严峻的考验。虽然STM32F系列的单片机的FLASH存储空间相当大,但是我们还是要考虑到其它的很多因素,不能只实现这一个功能就把空间占用完了,为其它的功能函数没有留有余地。所以我们在处理相同或相近的函数时,应对这几个函数进行总结,发现其共有性,然后在其共有性的基础上写一个公共函数,该公共函数有很大的收缩性,可以让这多个函数进行调用,这样极大地减少了代码量,缩减了代码的空间。

比如说,我们在写一级菜单下的各个列表的函数,因为这几个函数都是相似的,只是行的地址不同罢了。所以我们在写这几个函数时,不必要每个菜单的显示都去写一个函数,我们只需要写一个公用的函数,然后在这几个列表函数中去调用这个公用函数,这样就大大减少了程序的代码。如我们可以写这样的一个公用函数:void DrawList(u8 *p,u8 reverse,u8 row_pos);这个函数需要传递一个地址,一个行地址,一个列地址。然后在写其它的列表函数时,我们只需要调

用这个函数,用这个函数去完成其它几个列表菜单的显示功能。如在显示列表菜单一时,可以通写这样的函数调用来实现:

void DrawList1(u8 rev) {

if(rev == 1) {

DrawList(List1,1,0x1e); } else {

DrawList(List1,0,0x1e); } }

其中形参rev代表了是否反转,如果rev为1时,就反转;否则,不反转。这样通过一个函数就实现了菜单的显示和反转功能。

3.8 菜单标记

由于该系统菜单级数比较多(多达四级,并且还有100个FLASH数据记录),为每一级菜单设置一个标记已不在现实。我们可以设置一个数组来表达各级菜单。如MENU,2,,4,,在这个数据中,每一级的菜单都表示一个标记状态。如下表3-3所示:

表3-3 MENU菜单架构 0/1 0/1 0/1 0/1 MENU,2,,4, X X X X

其中,MENU,0,,X,(X = 0,1,2,3)分别代表了一、二、三、四级菜单的标记。当该标记为1时,表示进入第几级的菜单;如果为0时,则表示没有进入第几级菜单。例如:如果当前进入第一级菜单,则MENU,0,,0, = 1;MENU,1,,0,则表示第一级菜单的第几个子菜单;如果进入第二级菜单,则MENU,0,,1, = 1,MENU,1,,1,就代表了第二级菜单的第几个子菜单;这样就可以利用一个数组就可以达到多级菜单标记的功能。比单纯的一个菜单设定一个标记效

率要高的多。也使整个程序结构看起来有井有条,结构清晰明了,编写起来也更加简单易懂。

3.9 时钟信息的显示

对于该液晶模块,内部没有字库,如果要显示时钟信息,需要我们建立一个0-9的数字字模库。例如,我们把0-9的所有字模都放在一个数组中,每个数字的字模都用相同的大小,每个数字字模在数组中也占用相等字节,即每个数字字模占用的字节数相等。在这个系统中,我们取6*16的字模,每个字模占用的字节数为12个,通过一个判断语句来确定程序需要显示哪一个字符。在如下的程序中, number中程序中传递的形参,m为字模库的偏移量。

switch(number) {

case 0: m = 0;//第一次从前12个字节开始,取“0”的字模库 break;

case 1: m = 12;//第二次从第12个字节到第23个字节,共12个字节。取“1”

break; //的字模库 case 2: m = 24;//依次类推 break;

case 3: m = 36; break;

case 4: m = 48; break;

case 5: m = 60; break;

case 6: m = 72; break;

case 7: m = 84; break;

case 8: m = 96; break;

case 9: m = 108; break;

default: m = 0; break; }

这样我们就可以利用STM32内部的RTC时钟,动态地去更新这个时钟了。 3.10 波形的显示

该系统主要是为了测心电波形,但由于该液晶内部控制器的特殊性每次最少要写6个点(对于8位的数据口来说),这样对于我们处理波形是带来了很大的麻烦。所以我们可以采取这样的措施,在软件上对波形处理的算法进行优化。假设我们波形显示的区域是128个点,8位的AD进行采样。首先,因为我们要在这128个区域内分配0-255之间的数据,所以AD采样进来的数据先要除以2。然后把数据对8求商,把整个区域分成16页,再把数据对8求余,把数据点位到哪一页中的哪个点上。这样对AD采样的得来的数据在垂直方向上进行了分配。

对于水平方向上,由于每次最少3个点进行显示,但由于数据是8位的,也就决定了我们最少要6个点为单位进行显示。但每次显示6个点显然是不可以的。我们可以建立这样一个数组,WAVE,128,,3,,这个数组有128行3列,初始化为0,分别对应波形显示区域的0-127行。把液晶的扫描区域以128行6列这样的方式进

行,每次扫描128行6列,第一次扫描时定位到哪一行时,把第一个字节与0xf0进行相或,第二次再把第一个字节与0x0f相或,第三次把第二个字节与0xf0相或„以次类推。把这六个点显示完之后,列地址再加2。这样就可以把点完美的分配到各个行上了。

对于波形的连续性,由于要显示的是心电波形,点与点之间不能存在很大的空隙,所以对于不在同一行上的点或者不在相邻行上的点,必须要处理点与点之间空隙的问题。我们可以建这样一个缓冲区,BUFFER,2,,BUFFER,0,存储的是当前的行数,BUFFER,1,存储的是上一次的行数,通过,BUFFER,0,- BUFFER,1,,取得相差的行数,然后从最小行开始向上依次描点,都描在同一列上,一直描到最大行上,这样就可以在点与点之间画出一条直线,很好的处理了点与点之间的连接。

4 结论

本系统主要是为便携式产品的界面进行的设计。电子产品的界面设计的工作量相对来说是比较大的,我们在设计程序架构时应考虑到这一点。在编写液晶的各种显示函数时尽量编写成子函数的形式,而且尽可能的提高函数的可伸缩性,这样就可以大大的减少程序的代码量,也为整个程序的结构设计提供了方便。

在界面框架设计方面,尽可能的提前画好框图,在整个程序设计中,不要随意的更改这个框架,否则给人以混乱的感觉。对自己各级的菜单框架设计也会带来不便。

在器件的选取方面,低功耗是便携式产品的一个硬指标。没有超低的功耗,产品在销售市场便没有竞争力。在单片机的选取方面,尽量选择低功耗的、内部存储容量大,内部RAM空间大的单片机。因为在界面的显示过程中,需要建立大量的字库存放在单片机的FLASH或内部RAM中,涉及到的菜单级数比较多,列表选项较多,数据量比较大,一般8位或16位的单片机没有这么大的存储空间供我们使用。在这方面,STM32系列的单片机是首选。对于液晶的选取,低功耗仍然是不可

缺少的,但液晶操作的灵活性也是一大因素。在这方面,信利的这款液晶模块做的很好,它的窗口模式为我们局部进行界面的更新、画线等功能提供了极大的便利,不需要我们整屏的去刷屏显示,这样也降低了整个液晶模块的功耗。

在系统的调试方面,液晶初始化时需要我们注意,如果液晶初始化成功,那么它的内部升压将工作。VLCD端的电压将高达十几伏。如果没有初始化成功,则VLCD端是测不到高电压的。我们需要结合STM32单片机工作的频率与液晶内部控制器的操作时序来写这个初始化函数。特别是要注意STM32单片机的主频可以达到72MHZ,在编写写命令或写数据的函数时,要加入适当的延时。

参考文献

[1] 高锋 单片机应用系统设计及实用技术.北京:机械工业出版社,2004.4 [2] 郭强 液晶显示器的驱动和控制.北京:北京清华蓬远科贸公司,1999.4 [3] 李朝青 单片机原理及接口技术.北京:北京航空航天大学出版社,2003.4 [4] 徐惠民,安德宁 单片微型计算机原理、接口及应用.北京:北京邮电大学出版社,2000.8 [5] 童诗白,华成英著.模拟电子技术[M].北京:高等教育出版社 2005.1 [6] 王占广 基于C51的液晶显示模块的研究与应用.甘肃科技报,2005.1 [7] 张鹏飞 单片机技术应用的发展状况研究.浙江工商职业技术学院学报,2005.1 [8] 高志华,沈小丽 液晶驱动芯片及其硬件软件设计 中国计量学院,1997.1 [9] 严义,包键 单片机实现多路LCD直接驱动 杭州电子工业学院,1998.2 [10] 杜忠良,高旭光 液晶显示控制器SED的特性与应用 电测与仪表,1999.4 [11] 陈忠波,胡鹏程 液晶显示控制原理及应用.沈阳:铁路计算机应用,1999.6 [12] 程加力,司玉娟 用液晶驱动芯片驱动有机发光显示屏的设计 发光学报,2004.10

附录

系统整体电路图 L1

VCCVCCVCCVCCLCDMFG240*160

DDC01234567DR10R11R12R13VLCDVS+VS-VB0-VB1-VB1+VB0+VVSSNBM0CS0CWR1WR0RSTDDDDDDDDRes1Res1Res1Res110K10K10K10KMENUUPDOWNOK12345670123456701234111111111122222

VCCRSSDCRRWRSTDB0DB1DB2DB3DB4DB5DB6DB7S2S3S4S5SW-PBSW-PBSW-PBSW-PB C53Cap4.7uFR50C52C51VCCRes1CapCapC3.3M330nF0.22uFCap4.7uFR3Res110KM1MENU3456DB0RESTPA0PG0057DB1PG015VVCCDOWN10087DB2PA8PG0288DB3PG03S1U1OK117DB4PD3PG04SW-PB1390DB5INOUTPG05C3UP791DB6PC13PG06ADJCap292DB7PG07100nF77WR2PD087178RSTLM117LHVSS_1PD09107VSS_2C21C23C24C2214381CSVSS_3PD12CapCap2Cap2Cap3885RSVSS_4PD140.1uF10uF10uF0.1uF16STM32F103ZEBT86RDVSS_5PD15C151VSS_6Cap61232VSS_7OSC_INR1Y120pF83C?VSS_8Res1XTAL9424VSS_9OSC_OUT10MC21201VSS_10Cap2Cap1306VCC8MVSS_11VBAT100pF20pF7225RESTVDD_1REST108VDD_2C51448VDD_3PC14/OSC32_INCap392VDD_4Y220pF179VDD_5PC15/OSC32_OUTXTAL52VDD_6C6621VDD_7CapVCC8432.768KVDD_820pF95VDD_9121VDD_10131VCCVDD_11C33C34C35C36C37C38C39C40C41C42C43138BOOT0CapCapCapCapCapCapCapCapCapCapCap48PB02/BOOT1100nF100nF100nF100nF100nF100nF100nF100nF100nF100nF100nF

STM32F103ZEBT

因篇幅问题不能全部显示,请点此查看更多更全内容

Copyright © 2019- hzar.cn 版权所有 赣ICP备2024042791号-5

违法及侵权请联系:TEL:199 1889 7713 E-MAIL:2724546146@qq.com

本站由北京市万商天勤律师事务所王兴未律师提供法律服务