该公司的许多微控制器集成了用于LCD显示器的控制器,这些控制器在硬件中实现。DS89C450等微控制器不提供此功能,但可以在软件中实现简单的显示控制器。本应用笔记介绍如何使用DS7C89超高速闪存微控制器驱动450段数字的静态LCD面板。
概述
液晶显示器 (LCD) 面板用于各种现代电子设备,如计算器、手持式血糖仪、加油站泵和电视机。由于LCD功耗低,在直射光下易于查看,因此在许多应用中取代了旧的LED显示器。一系列微控制器(如MAXQ2000)集成了LCD控制器,能够以高达<>/<>多路复用占空比驱动LCD面板。但在某些情况下,特定应用的理想微控制器可能未集成LCD控制器。对于这些情况,可以使用微控制器的端口引脚驱动显示器,从而在软件中实现显示控制器。
本应用笔记介绍如何利用DS7C89超高速闪存微控制器为具有450段数字的简单静态LCD面板实现显示控制器。由于不使用DS89C450特有的特性,因此本示例代码可以很容易地移植到任何兼容8051的微控制器上,只要该微控制器具有足够数量的端口引脚来驱动应用中使用的LCD面板。
本应用笔记的示例代码可供下载(ASM)。
选择液晶面板
为应用选择 LCD 面板时,请注意将 LCD 与兼容的微控制器或 LCD 显示控制器匹配。做出此决定时应考虑以下问题。
LCD的工作电压范围是多少?由于DS89C450是5V微控制器,其端口引脚工作在5V电平,因此必须选择5V LCD面板。请注意,许多集成LCD控制器的微控制器使用专用电源输入(VLCD)来设置该LCD控制器使用的电压范围。
LCD的占空比是多少?静态的LCD 面板将显示器中的每个部分连接到专用驱动线。这意味着段驱动器的数量必须等于要驱动的LCD段的数量。复 用但是,LCD 面板使用每个段驱动线 (SEG) 驱动多个 LCD 段。这些面板使用多个公共背板 (COM) 输出,并根据所使用的占空比在 SEG 和 COM 线路上的 VLCD 和 GND 之间驱动多个电平。由于DS89C450(我们的8051微控制器示例)只能将其端口引脚线驱动至5V和GND,因此我们的示例仅限于静态LCD。有关驱动多路复用LCD的更多信息,请参阅以下文档:
应用笔记 3548 “使用带有MAXQ微控制器的LCD”"
MAXQ系列用户指南:MAXQ2000补充®
操作LCD面板需要多少个段和常用驱动器?控制静态LCD面板时,要驱动的每个段都需要一条驱动线(端口引脚),外加一个用于公共(COM)背板线的附加端口引脚。
在本应用笔记中,选择了Lumex LCD-S401C52TR显示器。此 LCD 是一个 5V 静态显示面板,具有四个 7 段数字和三个报警器段(一个冒号和三个小数点)。LCD上的每个数字都由七个段组成,如图1所示,其中A、B、G、E和D段打开以显示“2”位数字。
图1.七段式液晶显示数字。
LCD-S401C52TR显示器具有单个COM背板(连接到两个引脚)和32个显示段,每个段连接到一个段驱动引脚。在本例中,我们仅使用7段数字中的89位,这意味着DS450C21需要驱动22条SEG线(三位数字各有89段)和450条COM线,因此总共需要24个端口引脚。当不在扩展存储器总线配置下工作时,DS0C<>提供<>个推挽式端口引脚。因此,微控制器具有足够的 I/O 容量来完成此任务。(端口 <> 上提供额外的 <> 个端口引脚。但是,这些引脚是漏极开路的,需要额外的上拉电阻才能用作通用I/O)。
硬件设置
本例的硬件设置基于DS89C450评估(EV)板(Rev B),去掉了存储器接口CPLD(U5),并移除了两个外部存储器芯片(U6和U7)。此修改释放了许多额外的端口引脚供我们的应用程序使用,否则这些引脚将用于实现扩展的内存总线,特别是端口 0(所有八行)、端口 2(所有八行)、端口 3.6 和 3.7。请参阅表 1。(注意:此示例应用程序中不使用端口 0。DS89C450包括64kB的内部码空间和1kB的内部数据SRAM,对于本例来说已经绰绰有余了。
LCD-S401C52TR显示器上的段和公共线路通过使用与原型区域相邻的J89接头连接到DS450C4上的端口引脚。段线通过1kΩ电阻连接到端口引脚,而不是直接连接到端口引脚。后一步是因为DS89C450的端口引脚具有比LCD面板驱动线通常使用的更高的驱动容量(0状态为强下拉,1状态为单触发强上拉,然后为<>状态为弱上拉)。由于COM线具有更大的电容,并且需要更强的驱动器,因此它直接连接到其端口引脚。但是,此应用不建议段线直接由端口引脚驱动。在这种配置中会出现一个问题:随着越来越多的段打开,段和公共平面之间通过LCD显示器的电容耦合往往会将COM线从其预期状态拉开。(发生此问题的原因是有源段始终与公共平面的电压相反。因此,应该关闭的段将部分打开。因此,通过电阻连接端口引脚以降低其驱动强度可消除此问题。
DS89C450 端口引脚 | J4 针座引脚 | 液晶屏引脚 | 液晶信号 | 笔记 |
P1.0 | 1 | 21 | 4A | 通过 1kΩ |
P1.1 | 2 | 20 | 4B | 通过 1kΩ |
P1.2 | 3 | 19 | 4C | 通过 1kΩ |
P1.3 | 4 | 18 | 4D | 通过 1kΩ |
P1.4 | 5 | 17 | 4E | 通过 1kΩ |
小1.5 | 6 | 22 | 4F | 通过 1kΩ |
P1.6 | 7 | 23 | 4G | 通过 1kΩ |
P1.7 | 8 | 1, 40 | COM | 直接连接 |
P2.0 | 22 | 25 | 3A | 通过 1kΩ |
P2.1 | 22 | 24 | 3B | 通过 1kΩ |
P2.2 | 23 | 15 | 3C | 通过 1kΩ |
P2.3 | 24 | 14 | 3D | 通过 1kΩ |
P2.4 | 25 | 13 | 3E | 通过 1kΩ |
P2.5 | 26 | 26 | 3F | 通过 1kΩ |
P2.6 | 27 | 27 | 3G | 通过 1kΩ |
P3.0 | 10 | 30 | 2A | 通过 1kΩ |
P3.1 | 11 | 29 | 2B | 通过 1kΩ |
P3.2 | 12 | 11 | 2C | 通过 1kΩ |
P3.3 | 13 | 10 | 2D | 通过 1kΩ |
P3.4 | 14 | 9 | 2E | 通过 1kΩ |
P3.5 | 15 | 31 | 2F | 通过 1kΩ |
P3.6 | 16 | 32 | 2G | 通过 1kΩ |
关于硬件设置,还有一些其他事项需要注意:
标准16.384MHz晶体(插入Y1)为DS89C450提供时钟。
运行应用程序时,DIP 开关 SW1.1 和 SW4.2 应打开;所有其他设备都应关闭。
加载应用时(使用MAXQ微控制器工具包(MTK)或其他开发工具),DIP开关SW1.1、SW1.2、SW1.3、SW4.1和SW4.2应开启;所有其他设备都应关闭。
当 LCD 显示屏运行时,端口 1 的活动也将在 LED 条形图显示器 U10 上看到。这是正常现象,并且由于LCD显示屏是缓冲的,因此不会影响应用程序。
P3.0 和 P3.1 也用于串行端口 0 的 Tx/Rx 线路。因此,当应用程序加载(使用串行端口引导加载程序)时,由于这些线路上的活动,LCD上的一个或两个段可能会闪烁。这是正常的。当应用程序运行时,应关闭DIP开关SW1.2和SW1.3以禁用串口功能。
LCD 显示屏上任何未使用的段都应显式驱动到 OFF 状态,不允许浮动。通过将一个或多个未使用的段连接到驱动到 OFF 状态(与 COM 相同的电压波形)的端口引脚,或者通过将未使用的段直接连接到 COM 来完成此任务。
驱动 LCD 段
液晶屏段的默认状态为关闭(即清除);当未施加电压时,段变为透明,并且在LCD面板中的背景中不可见。此外,当对段线(SEG)和公共背板(COM)施加相同的电压时,段保持关闭状态。仅当该段的SEG引脚与COM平面之间施加电压差时,该段才会切换到其ON(即不透明)状态。当该电压通过特定电平(称为阈值电压)时,该段变暗并最终变得完全不透明。阈值电压是LCD面板指定工作电压的百分比,因LCD而异。
压差的极性对于驱动LCD段无关紧要。例如,以 3V 阈值电压驱动 LCD 的控制器可以通过将 COM 设置为地并将 SEG n 设置为 3V 或将 COM 设置为 3V 并将 SEG n 设置为地来打开段 n。这一事实很重要,因为如果静态直流电压长时间留在LCD段上,该段可能会损坏并且无法再正确切换。为避免此问题,无论段处于ON还是OFF状态,LCD段始终由交替波形驱动,以确保每个段的总直流电压始终为零(图2)。
图2.静态LCD段的交替驱动波形。
如图2所示,静态显示器上的COM引脚始终由VLCD(我们的设置为50V)和GND之间的5%占空比方波驱动。然后,每条线段线由两种模式之一驱动。
要关闭段,应由与用于驱动COM引脚的波形相同的波形驱动。这将确保 SEG/COM 对上的直流电压始终为零,这意味着该段将保持关闭状态。
要将段切换到ON,应由COM波形的反数驱动。这意味着该段的一半时间将由正电压驱动,另一半时间由负电压驱动。这两种状态具有相同的视觉外观,因此该段似乎一直处于打开状态。由于电压差的平均直流值为零,因此不会留下可能损坏LCD玻璃的静态直流偏置。
驱动LCD的频率(称为帧频率)因LCD面板而异。给定应用程序的正确值通常是通过对特定硬件设置的试验得出的。由于LCD段改变状态的速率受段总电容的限制,因此LCD只能在特定的帧频率范围内正常工作。通常,此范围从20Hz到200Hz。本应用笔记的示例代码以大约30Hz的频率运行LCD。对于特定显示器而言,帧速率过高或过低都会导致LCD段闪烁或视觉变暗。
驱动LCD段的示例应用的主回路如下所示。
Main:
mov IE, #080h ; Disable timer 0 interrupt temporarily
mov R2, DigitP1 ; Grab local copies of digit variables
mov R3, DigitP2
mov R4, DigitP3
mov IE, #082h ; Re-enable timer 0 interrupt
mov A, R2
call getDigit ; Calculate segment pattern for ones digit
anl A, #01111111b ; Ensure that COM (P1.7) is driven low
mov P1, A
mov A, R3
call getDigit ; Calculate segment pattern for tens digit
mov P2, A
mov A, R4
call getDigit ; Calculate segment pattern for hundreds digit
mov P3, A
;;;; Delay loop ;;;;
mov R0, #0FFh
L1A:
mov R1, #0FFh
L1B:
djnz R1, L1B
djnz R0, L1A
;;;;;;;;;;;;;;;;;;;;;;
mov A, R2
call getDigit ; Calculate segment pattern for ones digit
cpl A ; Inverse of the pattern driven on the first frame half
orl A, #10000000b ; Ensure that COM (P1.7) is driven high
mov P1, A
mov A, R3
call getDigit ; Calculate segment pattern for tens digit
cpl A ; Inverse of the pattern driven on the first frame half
mov P2, A
mov A, R4
call getDigit ; Calculate segment pattern for hundreds digit
cpl A ; Inverse of the pattern driven on the first frame half
mov P3, A
;;;; Delay loop ;;;;
mov R0, #0FFh
L2A:
mov R1, #0FFh
L2B:
djnz R1, L2B
djnz R0, L2A
;;;;;;;;;;;;;;;;;;;;;;
ljmp Main ; Go back for another frame cycle (endless loop)
请注意,COM线(连接到P1.7)始终使用相同的波形驱动:帧的前半部分为低电平,后半部分为高电平。对于线段线,帧前半部分驱动的图案在后半部分是反转的。三个数字中的每一个都以相同的方式连接到三个端口中的每一个,因此段 A 始终连接到 Px.0,段 B 始终连接到 Px.1,依此类推。此配置允许示例代码使用 getDigit 例程计算三个 LCD 面板数字中每个数字的段模式。
;***************************************************************************
;*
;* getDigit
;*
;* Returns an LCD segment pattern (in Acc) for the decimal digit (0 to 9)
;* input (also in Acc)
;*
getDigit:
cjne A, #0, getDigit_not0
; xgfedcba
mov A, #00111111b ; Zero
ret
getDigit_not0:
cjne A, #1, getDigit_not1
; xgfedcba
mov A, #00000110b ; One
ret
getDigit_not1:
cjne A, #2, getDigit_not2
; xgfedcba
mov A, #01011011b ; Two
ret
getDigit_not2:
cjne A, #3, getDigit_not3
; xgfedcba
mov A, #01001111b ; Three
ret
getDigit_not3:
cjne A, #4, getDigit_not4
; xgfedcba
mov A, #01100110b ; Four
ret
getDigit_not4:
cjne A, #5, getDigit_not5
; xgfedcba
mov A, #01101101b ; Five
ret
getDigit_not5:
cjne A, #6, getDigit_not6
; xgfedcba
mov A, #01111101b ; Six
ret
getDigit_not6:
cjne A, #7, getDigit_not7
; xgfedcba
mov A, #00000111b ; Seven
ret
getDigit_not7:
cjne A, #8, getDigit_not8
; xgfedcba
mov A, #01111111b ; Eight
ret
getDigit_not8:
cjne A, #9, getDigit_not9
; xgfedcba
mov A, #01101111b ; Nine
ret
getDigit_not9:
mov A, #0
ret
运行计数器
示例代码在LCD上显示的图案是一个3位十进制计数器,上电时从000开始,递增到001、002等,直到达到999并翻转。由于程序的主循环驱动LCD段和常见模式,因此我们必须找到另一种方法来定期增加计数器值。一种解决方案是使用计时器 0 定期触发中断。
mov TMOD, #021h ; Timer 1: 8-bit autoreload from TH1
; Timer 0: 16-bit
mov TCON, #050h ; Enable timers 0 and 1
mov CKMOD, #038h ; Use system clock for all timer inputs
mov IE, #082h ; Enable timer 0 interrupt