1、12864应用实际6. 自制单片机之六LCD12864的驱动LCD12864的驱动LCD12864在市面上主要分为两种,一种是采用st7920控制器的,它一般带有中文字库字模,价格略高一点。另一种是采用KS0108控制器,它只是点阵模式,不带字库。很可惜,我的这块就是KS0108控制器不带汉字库的,不过不打算用它专门显示文本,也就无所谓了。LCD12864模块的20个引脚定义如下:1。Vss 逻辑电源地2。VDD逻辑电源正5v3。V0LCD驱动电压4。RS数据/指令选择:高电平为数据,低电平为指令5。R/W读/写选择:高电平为读数据,低电平为写数据6。E读写使能,高电平有效,下降沿锁定数据7。
2、DB0数据输入输出引脚8。DB1数据输入输出引脚9。DB2数据输入输出引脚10。DB3数据输入输出引脚11。DB4数据输入输出引脚12。DB5数据输入输出引脚13。DB6数据输入输出引脚14。DB7数据输入输出引脚15。CS1片选择号,低电平时选择前64列16。CS2片选择号,低电平时选择后64列17。RET复位信号,低电平有效。18。VEE输出15v电源给V0提供驱动电源19。A背光电源LED正极20。K背光电源LED负极具体电路图如下:制做如下:接口说明:装上12864具体的电路还是两个电阻。一个背光限流电阻。一个液晶驱动电压调节电阻。背光电阻还是任何时候在19、20脚与电源之间串上个10
3、0欧电位器接上电源。调节电位器到合适亮度。具体值最好是到调试完程序能够正常显示后再将阻值确定换成固定电阻。液晶驱动电压的调整在数据线、电源线接好的前提下是在Vee(-15v)和地之间接一个电位器。中间接V0,通过调节电位器来调节V0上的电压。当V0上为-15V时为全暗(液晶显示为全黑)。当V0为0V时为全亮。调节电位器使屏幕从全暗刚好变到亮时,便可进行程序的调试。待屏幕显示正常后,进行对比度的细调,然后测量这两边的阻值在地和V0之间、V0和Vee之间换成两个固定电阻焊上就好了。注意在V0的电压是在一个很小的范围有效。我的就是在-2.2-2.5这个范围。仔细调节V0和地之间的电阻使V0上的电压在
4、2.3V。更换为固定电阻后的装配图:下面说说具体的驱动:先来了解一下LCD12864的内部控制结构:见图可以看出12864屏是分为左、右两块控制的。所有对屏幕的操作要受片选CS1、CS2来控制。我们再来看一看对屏幕操作数据与屏幕点阵的排布关系:见下图。从上图可以看出数据按字节在屏幕上是竖向排列的。上方为低位,下方为高位。因此在横向上(也就是Y)就一共是128列数据。分为CS1和CS2两个64列来写入。在竖方向上(也就是X)一字节数据显示8个点,竖向64个点分为8个字节,称做8页(X=0-7)。了解这些后我们就知道要满屏显示一张图就要从y=0127、X=07一共写1288=1024个字节的数据。
5、同样在AT89S51中存一张图就要1024个字节的空间。好!下面我们来了解对LCD12864进行操作的一些指令。下面对上图的指作解释:1.显示开关控制(DISPLAY ON/OFF) D=1:开显示(DISPLAY ON) 意即显示器可以进行各种显示操作 D=0:关显示(DISPLAY OFF) 意即不能对显示器进行各种显示操作 2.设置显示起始行(DISPLAY START LINE) 前面在Z地址计数器一节已经描述了显示起始行是由Z地址计数器控制的。A5A0 6位地址自动送入Z地址计数器,起始行的地址可以是063的任意一行。 例如: 选择A5A0是62,则起始行与DDRAM行的对应关系如下
6、: DDRAM 行:62 63 0 1 2 3 28 29 屏幕显示行: 1 2 3 4 5 6 31 32 3.设置页地址(SET PAGE “X ADDRESS”) 所谓页地址就是DDRAM的行地址,8行为一页,模块共64行即8页,A2A0表示07页。读写数据对地址没有影响,页地址由本指令或RST信号改变复位后页地址为0。页地址与DDRAM的对应关系见DDRAM地址表。 4.设置Y地址(SET Y ADDRESS) 此指令的作用是将A5A0送入Y地址计数器,作为DDRAM的Y地址指针。在对DDRA M进行读写操作后,Y地址指针自动加1,指向下一个DDRAM单元。 5.读状态(STATUS
7、READ) 当R/W=1 D/I=0时,在E信号为“H”的作用下,状态分别输出到数据总线(DB7DB0)的相应位。 BF: 前面已叙述过(见BF标志位一节)。 ON/OFF: 表示DFF触发器的状态(见DFF触发器一节)。 RST: RST=1表示内部正在初始化,此时组件不接受任何指令和数据。6.写显示数据(WRITE DISPLAY DATE) D7D0为显示数据,此指令把D7D0写入相应的DDRAM单元,Y地址指针自动加1。7.读显示数据(READ DISPLAY DATE) 此指令把DDRAM的内容D7D0读到数据总线DB7DB0,Y地址指针自动加1。 再帖一下接口时序图1.写操作时序2
8、.读操作时序 时序参数表: 又帖了这么多指令呀时序图什么的,看了就头晕。我也和你一样不爱看这些枯燥的东西。下面实际写些程序让屏幕亮起来。运行:不要走开哦!我会不断补全的。7.自制单片机之七LCD12864的驱动之源代码今天将LCD12864的源代码发上来。/LCD12864/*/连线表: CPU=89C51 SysClock=12MHz */RS=P1.0 R/W=P1.1 E=P1.2 CS1=P1.3 CS2=P1.4 */DB0-DB7=P0.0-P0.7 /Reset=InBoard */* #include #include #include #include #include #d
9、efine uchar unsigned char#define uint unsigned int/*引脚定义*/ #define DataPort P3 /LCD128*64 I/O 信号管脚sbit RS =P20; /数据指令sbit RW =P21; /读写sbit E =P22; /使能sbit CSL =P23; /左片选sbit CSR =P24; /右片选 uchar Page; /页 地址uchar Col; /列 地址 uchar code BMP1; /一幅图uchar code HZK_12; /1212阵点字模uchar code ASC_5x7; /57阵点字模u
10、char str4;/*函数定义*/void BusyL(void); /左屏检测忙void BusyR(void); /右屏检测忙void CheckBusy(void); /读取忙信号void Delay(uint MS); /延时void Locatexy(void); /将屏幕横向0-12纵向07转换成左、右屏的的X、Yvoid WriteCommandL( uchar CommandByte ); /向左屏写入指令void WriteCommandR( uchar CommandByte ); /向右屏写入指令uchar ReadData( void ); /读数据void Writ
11、eData( uchar DataByte ); /写数据void LcmClear( void ); /清屏void LcmInit( void ); /初始化void LcmPutBMP( uchar *puts ); /显示一幅图void LcmReverseBMP( void ); /将整屏反显void LcmPutHZ_12( uchar x,uchar y,uchar HZcode ); /在屏幕上任意点显示一个1212汉字uchar * uchartostr(unsigned char unm); /将值转成字符串void LcmPutAsc( uchar asc ); /显示一
12、个57的ASC字符void LcmPutstr( uchar row,uchar y,uchar * str ); /在设定位置显示字符串void LcmPutpoint( uchar ro,uchar lie,uchar colour ); /在设定位置显示一个点/*/*检查Busy */*/void BusyL(void) CSL= 1; CSR= 0; CheckBusy(); void BusyR(void) CSL= 0; CSR= 1; CheckBusy(); void CheckBusy(void) RS = 0; /指令 RW = 1;DataPort= 0xFF; /输出0
13、xff以便读取正确 E = 1; _nop_(); while(0);/DataPort & 0x80); /Status Read Bit7 = BUSY这地方有点问题,用了while(/DataPort & 0x80)后就一直读不到0了,陷入死循环。当用while(0)时反而能正常工作,不知道有没有人能解释 E = 0; _nop_(); /*/*根据设定的坐标数据,定位LCM上的下一个操作单元位置 */*/void Locatexy(void) uchar x,y; switch (Col&0xc0) /* col.and.0xC0 */ /*条件分支执行 */ case 0: Busy
14、L();break;/*左区 */ case 0x40: BusyR();break;/*右区 */ x = Col&0x3F|0x40; /* col.and.0x3f.or.Set Y Address*/ y = Page&0x07|0xB8; /* row.and.0x07.or.set Page */ CheckBusy(); /* waitting for enable */ RS = 0; /指令 RW = 0; /写 DataPort = y; /设置页面地址 E = 1; _nop_(); E = 0; _nop_(); CheckBusy(); /* waitting for
15、 enable */ RS = 0; RW = 0; DataPort = x; /设置列地址 E = 1; _nop_(); E = 0; _nop_(); /*/*写指令 */*/void WriteCommandL( uchar CommandByte ) BusyL(); DataPort = CommandByte; RS = 0; /指令 RW = 0; E = 1; _nop_(); E = 0; _nop_(); void WriteCommandR( uchar CommandByte ) BusyR(); DataPort = CommandByte; RS = 0; /指
16、令 RW = 0; E = 1; _nop_(); E = 0; _nop_(); /*/*读数据 */*/uchar ReadData( void ) uchar DataByte; Locatexy(); /*坐标定位,返回时保留分区状态不变 */ RS = 1; /*数据输出*/ RW = 1; /*读入 */ DataPort = 0xFF; /输出0xff以便读取正确 E = 1; /*读入到LCM*/ _nop_(); DataByte = DataPort; /*数据读出到数据口P1 */ E = 0; _nop_(); return DataByte; /*/*写数据 */*/
17、void WriteData( uchar DataByte ) Locatexy(); /*坐标定位,返回时保留分区状态不变 */ RS = 1; /*数据输出*/ RW = 0; /*写输出 */ DataPort = DataByte; /*数据输出到数据口 */ E = 1; /*写入到LCM*/ _nop_(); E = 0; _nop_(); void LcmClear( void ) Page = 0; Col = 0; for(Page=0;Page8;Page+) for(Col=0;Col128;Col+) WriteData(0); void LcmInit( void
18、) Delay(200); /等待复位 WriteCommandL(0x3f); /开显示 WriteCommandR(0x3f); WriteCommandL(0xc0); /设置起始地址=0 WriteCommandR(0xc0); WriteCommandL(0x3f); /开显示 WriteCommandR(0x3f); LcmClear(); Col = 0; Page= 0; Locatexy();void LcmPutBMP( uchar *puts ) uint X=0; Page = 0; Col = 0; for(Page=0;Page8;Page+) for(Col=0;
19、Col128;Col+) WriteData( putsX ); X+; void LcmReverseBMP( void ) uchar temp; Page = 0; Col = 0; for(Page=0;Page8;Page+) for(Col=0;Col128;Col+) temp = ReadData(); /空读一次 temp = ReadData(); temp = temp; WriteData(temp); void LcmPutHZ_12( uchar x,uchar y,uchar HZcode ) uchar offset,Rd,Wt,m,tmp,i; uint n;
20、 if(x117&y3; Col=x; n = 0x18*HZcode; offset=y&0x07; if(offset0;i-) Rd=ReadData(); Rd=ReadData(); m=HZK_12n; Wt=Rd&(0xff(8-offset)|(m(8-offset)|(moffset)|(Rd&(0xff0;i-) Rd=ReadData(); Rd=ReadData(); m=HZK_12n; Wt=Rd&(0xff(8-offset)|(m(8-offset)|(m(8-offset)|(Rd&(0xff(offset-4); WriteData(Wt); Page=Page-2;/恢复位置
copyright@ 2008-2022 冰豆网网站版权所有
经营许可证编号:鄂ICP备2022015515号-1