第1章 编址
1.1 如何编址
如何在MCU系统中,对其地址空间内的各种存储器、外设、IO准确唯一地编址,在李广弟的《单片机基础》(2000年8月,北航出版社)中已经阐述得很清楚,但是例子过于简单,也没总结出什么原则性的东西。对于一些memory map比较复杂的系统,这个问题是很重要的,应该把握一些原则来进行分析和设计。确定系统中的memory map是硬件平台设计的第一步。
首先需要分两种情况考虑:你所用的CPU是程序、存储、寄存器、IO统一编址呢,还是程序、存储和IO分别编址。但无论怎样,我们在确定每片空间时的原则是一样的,就是要按应用需要分配,而且要唯一,即一个地址对应一个存储单元(字节或者字)。
对于特定的CPU,其寄存器和IO所位处的地址空间,我们一般都不能动。因此确定memory map的关键是处理好程序(一般是ROM)和数据存储(一般是RAM或flash)的地址编址。(复杂的系统还可能有一大堆的外设地址)
多数嵌入式CPU在上电复位或受控复位后,都是从0000H地址开始取指令,8086是个例外,是从FFFF0H处开始取指令,原因是8086的代码段寄存器CS复位后值为FFFFH,偏移4位后就是FFFF0H了。
因此在编址时,系统的程序ROM(启动代码)必须编制在CPU上电后取指的地址,例如0000H。至于执行完这段启动代码后,系统是跳转到程序ROM的别的地方,还是跳转到数据存储空间去继续取指,那是以后的事。
在目前大容量存储技术发达的21世纪来说,系统中的程序ROM一般一块搞定,或者是片内FLASH搞定,不必要设计成多块,但是在我研究的小日本80年代的某个产品中,一块CPU对应的ROM都有10块8块,这是题外话。
相对于程序ROM,数据存储则很可能会很多片,因为一个复杂的系统中可能需要有nand flash,同时需要SRAM,SDRAM,DDR……等,以及还有各种特殊外设映射给CPU的地址,因此在设计时主要的编址工作在这里。
编址的工作实际上就是两件事情:一是确定数据总线的字长(8位,16位, 32位……),二是确定如何准确给出存储芯片(或外设芯片,以下省略)的片选信号。
确定数据总线的字长,影响着CPU与存储芯片的地址线的连接。因为CPU的编址数据宽度并不一定与存储器的存储单元宽度一致,举例说,8086是按照字节编址的,意思是说0000H这样的地址是对应一个字节,0001H地址则对应下一个字节,以此类推。但是对于16位宽的存储器(大部分都是),它的地址线上的一个0000H地址对应着一个16位字长的存储单元也即2个字节。这种情况下,在设计原理图时,CPU的地址线就不能跟存储器的地址线一一对连,而应该往前偏移一位,如本该A15-A00 对应存储器的A15-A00的,现在应该改为A16-A01对应连接存储器的A15-A00。这样,无论A00是0还是1,一次读写操作都涉及到2字节的内容。对于这种情况,一般在硬件电路上需要连接高字节和低字节的控制引脚,如80186CPU有UBE和LBE引脚。或者如ARM44b0,可以通过设置内部寄存器来配置数据总线宽度,这样就无需在外部连接UBE和LBE。
确定如何准确给出各存储芯片的片选信号,这就是体现设计者对地址空间如何进行分配的关键所在。当代码中要访问某个地址时,该地址的数值出现在地址总线上,每片存储芯片都能收到,而到底哪一片芯片该响应此地址,决定于片选信号(一般称为CS或CE),在那一刻没有被CS或CE的芯片,都得当哑巴,不能把自己的数据放到总线上。编址问题,核心就是如何构造准确的片选信号问题,而构造片选信号问题,核心就是如何摆弄各存储芯片的高位地址线的问题。
举个例子,譬如说要在地址空间总计64kB的51单片机中分配3片4kB的SRAM地址空间,简单起见,假设是从最低地址处开始分配。
4kB意味着有12根地址线A00-A11,而51的64kB地址空间是对应着16根地址线A00-A15的,那么对于每片SRAM来说,51多出来的4根地址线:A15-A12就是其高位地址线,产生它们自身片选信号就从这几根高位地址线里作文章。
如何作文章?仔细看李广弟的书就能清楚了。李广弟提到了两种方法,一种是线选法,一种是译码法。除了极其简单的系统外,要唯一、准确地编址都必须使用译码法。
理解了上面的描述后,更进一步,假如这3片4K 的SRAM 需要分配在0x8000开始的空间呢,或者更难一点,需分配在任意一个地址开始的空间,那又该如何设计呢?我所研究的系统中,8086的1M的地址空间中划分了非常多的地址,包括存储器地址和外设地址,译码电路非常复杂,需要大量的与、非门器件参与,当然今天一般是采用CPLD来统筹管理复杂外部地址的译码逻辑。
------------------------------------------------------
本章题外废话:玩过很多款CPU,体现的是知识;能在很短时间内玩转一款新CPU,体现的是能力。
(二) 常用存储器
前言:以下的内容似乎有点俗,有点像讲解如何设计开发板。不过很多时候,目标板就是开发板的子集。
2.1 SRAM
最简单的外存储器,地址线和数据线(如不是分配在特殊地址)依次跟CPU连接即可,片选信号根据第一章讨论的译码法给出,片子的输出使能信号OE一般跟CPU的RD脚连接,片子的写使能信号WE则跟CPU的WR脚连接。
对于好些没有像51或8086这样的并行总线、但却有很多IO脚的CPU,如MSP430F149、449,可以使用IO脚来跟SRAM器件连接,CE、 RD、WR等信号的时序用3根IO口线编程实现,何时拉高何时拉低,参考SRAM datasheet的时序图即可,非常简单。
题外话提一下,由于历史原因曾经存在支持所谓intel时序和motorola时序的芯片,譬如用于老式PC主板上的实时时钟芯片DS12887,就是同时支持 intel时序和motorola时序。一般这类芯片的datasheet会着重说明的,目前应该基本看不到motorola时序的芯片了。
对于一些地址和数据总线复用(Multiplexed)的CPU,如51或8086,需要使用传统的74系列IC进行地址锁存(74LS373)和数据总线缓冲(74HC245)。有时候假如同时挂在地址和数据总线上的芯片太多,则需要考虑在总线上先加一级缓冲以获得较大的扇出系数,以前常用244,现在则常用245因为布线方便(3.3V电压的系统就使用LV4245)。当然如果对成本不敏感,推荐使用GAL或者CPLD来代替373、245、138这些东西。
SRAM优点是总线扩展简单直观,存取速度快,缺点是造价成本高,而且SRAM的容量都很小,通常只有几十k,不会超过1MB。
提到SRAM,不得不提到PSRAM,即伪静态RAM。站在CPU程序员的角度,可以认为它跟SRAM是一样的。其实PSRAM的存储单元结构类似于 DRAM(如下所说),因此它具有了DRAM的高密度、价格低的特点,并且速度也不算太慢。适合于对成本敏感而又需要较大容量RAM的系统。
时至今日,虽然串行方式的接口总线成为微机接口的趋势,看USB、以太网、SATA硬盘等等皆是串行,但是几乎所有的CPU都仍然保留如SRAM这种并行总线式的接口。因为实在太多外设器件仍旧是采用这种接口的。关于这个接口,第三章继续拓展讨论。请关注。
2.2 双端口RAM
顾名思义,提供两套端口的RAM,基本上是为了实现多CPU通信而存在的。总线用法跟SRAM一样,不过是有两套总线端口,连到每套总线上的CPU都可能取得共享RAM区的访问权。为了避免多个CPU同时从两侧读写RAM阵列的同一个单元,双端口RAM芯片自身会提供多种冲突检测机制,以Cypress的 CY7C026为例,提供了BUSY引脚、邮箱(mailbox)以及信号量(semaphore)等多种手段。
2.3 动态SDRAM
SDRAM 是目前中等复杂度以上的嵌入式系统普遍采用的RAM。DRAM与SRAM的最大区别是DRAM只采用1个晶体管加一个电容的结构来保存1位数据,而 SRAM则需要4-6个晶体管才能保存一位数据。但是DRAM由于靠电容的充放电来实现0和1的状态变化,因此经常需要对电容状态进行刷新,不仅要周期性地刷新(约几十毫秒一次),在每次读取操作后也一样要刷新。
SDRAM的存储单元按行、列来组织,寻址时也就根据行地址和列地址综合来找到存储单元的。行地址和列地址的具体范围需依赖datasheet具体分析。
SDRAM芯片的引脚主要有:行地址锁存控制脚RAS,列地址锁存控制脚CAS,时钟输入脚CLK,其他的地址总线、数据总线、CE、WE等与SRAM是一致的。
CLK 是SDRAM芯片的主时钟输入,所有控制信号都必须与该脚的上升沿同步(Synchronous),这也是SDRAM名字中S的意思。对于SDRAM片子,CLK的频率有个极限,要看datasheet的说明,100MHz,133MHz,或者是166MHz。我们PC电脑用的SDRAM内存条不也有 PC100,PC133的说法吗,正是此意。
SDRAM读取的过程一般如下:
1. CPU把行地址传送到DRAM的地址引脚上。
2. 激活RAS引脚,地址引脚上的行地址就打入DRAM芯片的锁存器了
3. WE脚不使能,确定目前是处于读操作
4. 同第1、2步把列地址打入到列地址锁存器
5. 使能OE脚(一般就是CAS脚),此时数据就从数据总线上出现
6. 人为置RAS和CAS同时失效,表示当前读取周期结束。
写过程类似,具体的时序,很多资料会有,一般如果CPU有SDRAM控制器,那就无须管上述过程。但如果用FPGA来实现该时序,就还是需要了解。
以三星256Mbit SDRAM K4S561632为例,其引脚如附图1所示:
DQM脚还分为LDQM脚和UDQM脚,也即前面第一章提到的,方便那些字节寻址的CPU(如2410,2440)控制读写存储器的高字节和低字节(MASK),关于这个内容,第三章有个详细的例子。
CLK、CS、CKE(Clock Enable)、A0-A12、RAS/CAS、WE、D0-Dn等引脚无需再解释。BA0 和 BA1 是bank选择地址,这两根地址线可以译码出4种情况,也即这片SDRAM 芯片内部的存储单元划分为4个BANK。
对于带有SDRAM控制器的CPU如2440,它的数据手册会详细介绍如何跟不同BANK组织方式的SDRAM连线的了,以2440为例,截下其datasheet对应的说明如附图2:
可见把2440的24和25号地址线连接到BA1和BA0即可。
2.4 DDR
即将要用,到时用完后有经验了再补充吧。
2.5 NAND FLASH
一般应用在中等复杂度以上的系统,CPU一般会有NAND的接口以及从NAND启动的机制,参照datasheet的指引连线即可,如三星ARM 2410,2440等。低级MCU一般不会用到NAND FLASH,如果需要大容量存储器,个人认为还不如扩个USB口外接U盘好过。
------------------------------------------
本章题外废话:
我反复提到:datasheet里就有详细说明。是的,datasheet能教会我们一切,用一个器件前,请认真地看它的datasheet,没有任何一本中文书比datasheet更权威。高中英语水平加上一个金山词霸,足够看懂任何datasheet。
(三) CPU的其他功能单元
一个典型的MCU包含的功能单元方块图是如下所示:
1.1 BUS Control Interface单元
其实从第一章到这里,还是在谈论memory controller单元。CPU要访问挂在地址和数据总线上的外设就需要总线控制信号的参与,前面也提到了,目前为止大多数嵌入式CPU仍然保留着这种并行的BUS Interface控制单元。最常见的控制信号莫过于RD、WR、ALE。
RD常常连接外设的OE,WR常连接外设的WE。OE就是output enable,CPU使能外设在数据总线上输出数据;WE就是write enable,使能外设允许CPU对其写入数据。ALE只出现在数据总线与地址总线低8位地址引脚复用的CPU中(如8051、8086),ALE意为Address Latch Enable,使能地址锁存,用于配合外部锁存器件的如74LS373(573),当ALE信号有效时373芯片把当前总线上的低八位地址锁存住,送给外设,因为下一个时钟周期,总线上的就是数据的低八位了。
8086的BUS 控制信号需要使用一片8288来进行译码,因为8086通过3个引脚S0-S2的8种不同译码状态来给出ALE、DEN、MEM_WR、MEM_RD等控制信号。
有时你还会看到有些CPU还有类似ARDY,SRDY,HOLD,HLDA等的总线控制信号,8086就有(8086真是一款经典的CPU)。ARDY顾名思义,异步(传输)已准备好信号,SRDY则是同步传输已准备好。这俩信号都是外设(譬如一台打印机)输入给CPU的,意思是外设告诉CPU:我READY了,你可以读写我的某个地址数据。
HOLD也是外设给CPU的请求信号,意思是目前外设需要使用总线,CPU这边先别往总线上送数据。这种情况多发生在多CPU共享同一块存储器时,CPU 甲告诉CPU 乙,它要暂时取得总线的控制权。
HLDA顾名思义,就是CPU 乙对甲所提出的HOLD请求做一肯定的回应(Ack)。
在2440上我们还可以看到更多一些的引脚。
譬如你能看到GCS0~GCS7,它们都是来自2440CPU的存储器片选控制单元(Chip Select Unit)。2440支持最大1GB的寻址空间,于是它设计了这样一个逻辑,把1GB的连续空间分为了8个区,每个区128M。(http://www.pw0.cn/ 版权所有)当程序中寻址到该范围内的地址,这些片选信号自动有效,激活该地址上的存储器。CPU里有了这种片选控制单元,某种程度上简化了外部译码逻辑。
你还可以看到BWE0:DQM0 ~BWE3:DQM3这四个引脚。这就是第一章提到的,当CPU数据总线宽度跟存储芯片的数据宽度不一致的时候,需要增加高低字节(高低字)控制信号。因为2440的寻址方式是字节寻址,而2440数据总线宽度32位(32除8等于4,所以要提供四个控制引脚以便能寻址到字节),SDRAM宽度则是16位,因此需要把上述的四个控制引脚作为SDRAM的低两位地址线,并且要两片级联(这里以第二章提到的16位数宽的SDRAM为例子,它们的连线方式例子如下图)。
1.2 时钟、上电复位
80年代的8086系统常用8284A来完成这两个工作。8284A可以输出5M和8M的时钟,可以根据输入端经过内部的斯密特触发器产生可靠的RESET信号。
MCU一般用无源晶体来产生时钟,MPU和DSP常用更准确的有源晶振。请注意一点字眼上的区别,无源VS有源,晶体VS 晶振。
它们的区别:无源晶体没有电压的问题,信号电平是可变的,同样的晶体可以适用于多种电压的CPU,而且价格通常也较低,缺点是信号质量较差。
而有源晶振就是晶体再配上若干电路,并留了电源引脚,加电源即可输出稳定的振荡信号。对于时序要求敏感的应用,还是有源的晶振好,因为可以选用比较精密的晶振,甚至是高档的温度补偿晶振。有些CPU内部没有起振电路,这时只能选择有源晶振了。其缺陷是其信号电平是固定的,譬如3.3V,或者5V,需要根据CPU的电压电平来选择匹配,灵活性较差,价格也相对晶体高很多。
对于ARM等同时存在多时钟的系统,外部晶振也会不限于一个,如对于带实时时钟RTC功能的片子,一般外部配置一个手表晶振32.768k,同时再配个电池。
小小的出个题,貌似前两年比较多应届生面试时被问到:上图中1M电阻和两个电容的作用是什么?它们是否必须?只用万用表能否量出晶振起振了没?
对于复位电路,有廉价的实现方式,也有奢侈的实现方式。低档MCU一般使用最简单的阻容充电式电路,通过电容的充电时间来获得足够的复位时间。有些CPU是高电平复位,有些则是低电平复位,没关系,都可以用该阻容复位电路,低电平方式的CPU就把复位脚用电阻上拉然后电容接地,高电平复位的则相反对待。待电容充电完成,电位处于逻辑高(低),复位脚就失效,MCU开始处于正常工作状态。若想加入按键复位功能也很简单,把按键跟电容并联即可。
除此外,还可以使用电源监控和复位芯片如IMP707、MAX691等,这属于较奢侈的实现方式。有些场合需要用外部的单片机或者CPLD、FPGA来控制CPU进行热复位,这种情况下就是外部的IO口直接接到CPU的reset脚了。
1.3 外部中断输入引脚
应该没有哪款CPU没有外部中断输入引脚吧?不用的话,设计原理图时应可靠地处置,譬如低电平触发的,就上拉;下降沿触发的,就接地,总之保证其状态不会被触发。
1.4 JTAG
JTAG貌似简单,但是暗藏杀机,一旦不注意,查都很难查得出来。不打算作详细分析了,网上好像也有相应文章。两个原则:芯片datasheet有说明的,按说明接;有官方应用电路的,按官方电路接;都没有的,按如下的图来接。
顺便提一下,对于同个电路上的多片同类器件,一般都可以设计成JTAG菊花链的形式把各片器件串起来,共用一个JTAG头,这样就省了很多电路板空间。譬如常用于电信语音音频处理单板上的DSP阵列,FPGA阵列,等等。菊花链电路一般通用如下,具体当然还是那句话:看datasheet:
不过设计成菊花链的时候,很容易忽略一点就是电源的能力。不要小看多片片子级联后的电流消耗,我试过一片1117带不起三片ACTEL的FPGA A3P060,发现编程的时候软件老是提示编不了程。我开始时是带五片片子,别说编程,连JTAG链子都找不到。这是新人的错误,后人不该再犯。
1.5 MMU
两年前偶尔看到某网友说了一句:面试一个嵌入式系统工程师,不需要问太多东西,就让ta解释一下对MMU的理解就基本够了,足见理解MMU是需要不少基础知识的。MMU虽然没有外引电路引脚,但是往往设计嵌入式硬件平台的工程师是需要同时负责电路调试的,绕不开对MMU的配置(如果所用的CPU有MMU的话),因此还是必须理解MMU。
要理解MMU,必须首先了解这些方面知识:
A 扁平式(Flat)的内存访问机制,即之前提到的寻址方式和编址机制(再次体现了熟悉编址的重要性,因为寻址对于计算机来说是最基础的东西)
B 嵌入式系统内存管理的概念和意义。
C 虚拟地址、内存分页、存储器页帧的概念。
D多任务多线程操作系统的任务调度(任务内存分配,任务堆栈,越界)
E CPU cache的概念及其替换和写操作策略(计算机组成原理课程)然后就可以顺利地阅读关于MMU的介绍文章了。我不在此画蛇添足。
(四)外设接口
前言: 这次的牵涉到的内容比较多,有些我用过已经很久了,记得不是太清楚,估计有错,大家边看边挑。
外设接口精彩纷呈。经典串口UART,同步串口SPI,基于ADC输入的触摸屏接口,用于短距离互连的总线I2C,USB,用于SD和MMC卡的媒介接口,ATA硬盘接口,DOC 电子盘接口,微型打印机口,以太网接口,CAN总线,lin总线,或者红外IrDA、蓝牙、wifi模块、GSM/GPRS模块接口,等等。上面提到的大部分接口都很独立,参考各自的数据手册和应用手册就能轻松上手。下面简单写一下我对它们的印象。
4.1 经典串口UART
没有哪款CPU会没有这个接口,可见其经典。实际应用中常见的是3线串口(只用收、发和GND三根线)和9线串口(用于modem通讯)。然后根据传输过程的电气规范,又可分为RS232、RS485、RS422等。
使用UART需要收发双方设置好相同的波特率、起始停止位数、奇偶校验位。MCU TO MCU的通讯不存在电平转换问题,MCU TO PC则要使用电平转换芯片,MAX232(5V)、MAX3232(3.3V) 最常用。UART口到目前为止还是最常用的调试程序的打印信息输出口,STC系列的51单片机更是一律需要通过UART口编程。
在MCU侧设置波特率时是根据UART口的时钟源来算分频系数的。如果发现MCU的串口有输出数据但接收端收到的数据值不对,十有八九是波特率寄存器值没设对,剩下的百分之一可能是没处理好数据位数(7位还是8位)和奇偶校验位。
另外,UART串口完全可以用IO口模拟。
4.2 同步串口SPI
四根信号引脚:SCLK、MISO、MOSI、CE(片选)。之所以称为同步是因为收发双方是严格按照SCLK的节奏来动作的。因此数据速度可以到达10Mbps,但传输距离就不能远了,几米范围内。
数据收发是主从式的,主发,从收。在时序上需要注意的是主在发送一字节数据后,需要接着发送一字节的哑数据(dummy data)以维持SCLK线上的同步时钟脉冲,因为从机要接受该字节数据就依赖于这个哑字节所带来的SCLK脉冲的持续。通常哑字节是0x0或者 0xff。具体看器件的数据手册。
4.3 I2C总线
这个乏善可陈,仔细研究一下周立功网站上针对它的显示芯片7290 的用C51写的例子即可,唯一值得注意的是,这种总线中,同一类器件的地址是预指定的(由飞利浦公司为该类器件的生产商预制定,例如周立功的LED与键盘控制芯片7290)。很多EEPROM、ADC、DAC都是I2C接口的。
4.4 USB
参考我写的USB host 实现一文。Host都熟悉了,device就手到擒来。在我的21ic 笔记上有得下载。地址是:user1/1025/index.html
4.5 SD和MMC卡接口
2410和2440有此接口。没仔细看过程序,保持缄默。
4.6 ATA硬盘、DOC电子盘接口
没搞过。
4.7 微型打印机接口
跟 PC的打印机口是一样的。关键控制引脚就是Busy、Error、STROBE。时序也非常简单。有兴趣的朋友编个DOS下的C程序,调用 outportb()函数往PC打印机口的0x378地址写数据、往0x37a写控制信号,调用inportb()函数从0x379读打印机状态,就可以驱动打印机了。当然还需要了解一下简单的打印机控制命令。使用热敏式微型打印机的时候需要注意设计好电源,要有足够的能力,因为热敏打印时要求的持续电流比较大,我用过伟煌的热敏打印机,需要用一片LM2576来对之供电,打印效果才好。
4.8 CAN总线接口
类似于以太网的CSMA/CD的总线冲突检测机制,但是与以太网不同,CAN网络使用标识符(其实即CAN节点的地址)来进行按位仲裁以解决访问冲突,数值高的标识符自动获得总线控制的优先权。CAN是一个广播类型的总线,所有节点都接收总线上的数据,硬件上的过滤机制决定消息是否提供给该接点用。
在嵌入式应用中使用CAN总线,可以直接使用带CAN总线控制器(controller)的CPU,如DSP 2407,然后外加一片CAN收发器(Tranceiver)如82C250或者MCP2551。假如CPU没有CAN控制器,也没问题,可以用SPI口外挂一片MCP2515,然后再加一片收发器。CAN 控制器芯片再加上收发器可以完成CAN通讯网络的物理层和MAC层功能,能反馈报文发送或接收过程的错误与状态,用起来不会比用UART更复杂。所以说硬件电路是很简单的。关键在于通讯网络中应用层的协议。这是软件的工作了。
4.9 以太网接口
早年刚流行时常用8019芯片来实现基于IEEE802.3标准的MAC层和PHY层收发,现在流行CS8900等。用于单片机控制网络中的以太网从硬件上乏善可陈,主要工作量在软件上,stack的实现,需要了解802.3的协议,以及更高层的协议,如TCP/IP协议族,这些都是软件方面的工作了,不表。
4.10 功能模块
红外、蓝牙、wifi、GSM/GPRS、CDMA等无线通信功能通常是以一个模块的方式提供,提供跟MCU的接口不外乎是UART、SPI、并行总线、USB这些,只要掌握了前面的各种接口,就没有半点问题。
4.11 显示器件
嵌入式系统的显示器件很多,从数码管到各种形状可定制的液晶模组到点阵式液晶模组到伪彩STN屏到真彩TFT LCD都有。数码管和LED的应用可以很简单也可以很复杂,不在本文讨论范围之内。主要讲讲常用的点阵式液晶模组以及STN屏的嵌入式系统接口。
4.11.1 点阵式液晶模组LCM
如果用过98年开始流行的IC卡电话,应该记得电话机上那个泛着黄绿色底光的显示屏,那种就是点阵式液晶模组,称为LCM。那时候好像用的是1602或者 12232。1602的字库只支持ASCII码,1602的意思是只有两行,每行最多只能显示16个英文字符。12232支持二级汉字库,也是只能显示两行,每行最多显示8个汉字或16个ASCII字符。12864也渐渐用的多起来,支持显示四行,每行最多8个汉字。
1602我只见过接口是8位并行总线的,即跟SRAM一样,像访问SRAM一样访问1602即可。
12232和12864的接口有选择,有些是如1602是8位的并行总线接口,有些是跟UART一样,是一收一发的串行接口。IO口紧张的情况下,当然用串行接口的模组要省脚了,只需要两个IO。
在硬件接口上,需要注意的有两点。LCM一般有一个引脚叫“液晶显示偏压”信号,LCM采集该引脚上的电压值(0~5V),根据电压值的大小调节LCM的显示亮度。调试程序时如果发现屏上一片白或一片黑,看不到字,也许就是该脚的电压给的不对,我记得大概在4V左右会比较合适,记不清了,多年前做过。一般用两只电阻分压,如果想可调,上个电位器,但是成本高了。
另一点,背光工作电流在5mA左右,需要串联限流电阻以调节背光强度,太强的背光会缩短背光LED的寿命。如果要做到背光的亮灭可控,只要在背光电路中串联一只三极管,如8050,用MCU或者逻辑电路来控制三极管基极通断。
LCM模组内部,其实确有一块RAM的(所以难怪接口类似SRAM),编程的时候,直接写RAM的相应地址,屏上相应的位置就会出现字符了。如果需要做动画等效果,就需要程序直接控制到某个像素点。
4.11.2 STN屏
早期使用的STN彩色屏很多是sharp公司的屏,具有代表性,典型分辨率是320×240。其接口信号线定义如下:
序号 引脚符号 描述
1 YD 帧同步信号
2 LP 行数据锁存信号
3 XCK 行数据时钟信号
4 DISP 控制屏是否显示的信号
5 VDD 电源
6 VSS 地
7 VEE 背光电源
8 D0~D7 8位显示数据
写满一屏的数据称为1帧,YD是帧同步数据,也即是由YD脉冲启动新一帧数据的写入。两个YD脉冲之间的时间长度显然就是帧周期,也即LCD刷屏的周期,其倒数是我们熟悉的刷新率,对于这款Sharp LCD屏,频率一般70~80Hz。
LP是行(共240行)数据输入锁存信号,也就是行同步脉冲信号。该信号启动新一行数据的写入,所以显然每帧中包含240个LP脉冲。
XCK是行数据输入信号,是每行中每一像素点数据传输的时钟信号,每8个字节的数据在XCK的下降沿出被锁存。
DISP控制屏是否显示,如果L电平 ,那屏幕就不显示,类似于显示器被关了。
在硬件上STN和TFT屏的驱动偏置电压产生电路与背光电路比LCM复杂很多。
STN/TFT LCD的驱动需要正电压或者负电压偏置,而大多数嵌入式子系统都是5V电源,因此需要DC-DC变换电路。我使用过ANDORIN专为LCD负电压偏置而设计的adp05c24,是产生-24V的可调DC变换器。或者采用如MAX680、摩托的34063等DC-DC芯片也可做到正负电压电源。
LCD 背光,中大点阵的STN型与TFT型LCD,多为白色(红绿蓝色调)CCFL背光,一般为25kHz~100kHz、300V以上交流驱动。该交流驱动目前多使用外加一块拇指大小的驱动板,特征是其上有个小变压器,实现5V输入,300V以上交流驱动的输出。或者用成品的背光模块,如森宝的VET- N1210-01 CCEL模块,用IC器件搭建背光电路,可以紧凑设计结构并降低成本。
以上是LCD屏的电路接口,幸运的话CPU这边有对应的LCD控制器接口,譬如44b0,就有STN屏的接口,外部接口信号一般跟屏是对应的,如44b0,V跟YD对应,VLINE跟LP对应,VCLK跟XCK对应,VM跟DISP对应,等等。
LCD控制器的工作概括起来就是把显示缓冲区的LCD图像数据送到外部LCD屏去。一般的特征为:支持色彩深度xx位,支持xx 扫描方式的屏,支持虚拟屏(可硬件方式地水平和垂直滚动),支持多种像素的屏,等等。