首页资源分类嵌入式处理器51内核 > (T6963)驱动程序

(T6963)驱动程序

已有 444994个资源

下载专区

上传者其他资源

    文档信息举报收藏

    标    签:t6963

    分    享:

    文档简介

    dfagafdbgadfv

    文档预览

    液晶显示模块的应用 一、结构特点 内藏T6963C 的液晶显示模块上已经实现了T6963C 与行、列驱动器及显示缓冲区RAM 的接口,同时也已用硬件设置了液晶屏的结构(单双屏、数据传输方式、显示窗口长度、宽度等等。我们常用的液晶显示模块一般都是单屏结构,因此我们这里只讨论单屏结构的液晶显示模块。内藏T6963C 的单屏结构点阵图形液晶显示模块的方框图如下: 二、T6963C 的特点 (1) T6963C 是点阵式液晶图形显示控制器它能直接与8 位微处理器接口; (2) T6963C 的字符字体可由硬件或软件设置,其字体有4 种5X8 、6X8 、7X8、8X8; (3) T6963C 的占空比可从1/16 到1/128; (4) T6963C 可以图形方式、文本方式及图形和文本合成方式进行显示,以及文本方式下的特征显示,还可以实现图形拷贝操作等等; (5) T6963C 具有内部字符发生器CGROM,共有128 个字符。T6963C 可管理64K显示缓冲区及字符发生器CGRAM,并允许MPU 随时访问显示缓冲区,甚至可以进行位操作。  三、该类液晶模块的管脚定义见下表: 说明: 对于单电源模块,标志为V0/POFF。 当该管脚为高或悬空时,内部DC/DC 功能开启;为低时,内部DC/DC 功能关闭。该功能可用作屏幕保护和休眠方式。如果用其直接替代双电源模块,该管脚直接悬空即可。 四、液晶显示模块的供电说明 1. 如果您所选用的液晶模块是双电源(VDD/V0)供电的就需要提供一个负电压(液晶驱动电压V0/VEE), 用以调节对比度,接在液晶模块的V0 引脚上。因为液晶材料的物理特性,液晶的对比度会随着温度的变化而相应变化,所以,您加的负电压值应该随温度作相应的调整,大致是温度变化10°C 电压变化1伏左右。为满足这一要求您要选择较大值的负电源,然后做一个温度补偿电路,或者安排一个电位器调整负电压值。例如对于QH12864T-HT-LED04, 当室温(VDD=5V)时,V0=-10.5V, 如果要用到-20°C, 液晶驱动电压将要变到V0=-14.5V,再考虑到负载消耗所以您提供的负电源应该为-16V 左右。但如果超过此值太多或说超过了液晶驱动电源的极限值的话应该考虑保护电路。 2. 常用负电源产生办法 1) 采用79 系列三端集成稳压器可产生-18v(7918) -24v(7924)等电源 2) 采用DC-DC 模块市场上常见的5D**系列型号可选择使用 3) 采用DC-DC 集成电路制作负电源如MAX749、 MAX680、 MC34063 等。 3. 液晶模块可选用带背光的型号大部分为LED 背光方式,供电为3.8~ 4.3V 直流电源,严格限制5V 电源直接供电,否则不仅会增加您的功耗,更会增加损坏背光灯的可能性和缩短液晶模块的使用寿命。推荐电压如下: 当背光方式为LED04 即底背光时VLED<4.0V; 当背光方式为LED03 即边背光时VLED4.1V。 五、T6963C 与MPU 的接口时序: T6963C 与MPU 接口时序如图:    六、液晶显示模块指令系统 该类液晶模块的系统指令集其实就是T6963C 控制器的指令集。模块的初始化设置一般都由管脚设置完成,因此其指令系统将集中于显示功能的设置上。T6963C的指令可带一个或两个参数,或无参数。每条指令的执行都是先送入参数(如果有的话),再送入指令代码。每次操作之前,最好先进行状态字检测。 T6963C 的状态字如下所示: 由于状态位作用不一样,因此执行不同指令必须检测不同状态位。在MPU每一次读写指令和数据时,STA0 和STA1 要同时有效――处于"准备好"状态。 当MPU 读写数组时,判断STA2 或STA3 状态。 屏读、屏拷贝指令使用STA6。 STA5 和STA7 反映T6963C 内部运行状态。 T6963C指令系统的说明: 1、指针设置指令,格式如下: D1,D2为第一和第二个参数,后一个字节为指令代码,根据N0,N1,N2的取值,该指令有三种含义(N0,N1,N2不能有两个同时为1) (1) 光标指针设置:D1表示光标在实际液晶屏上离左上角的横向距离(字符数),D2表示纵向距离(字符行) (2) CGRAM偏置地填寄存器设置:设置了CGRAM在显示64KRAM内的高5位地址,CGRAM的实际地址为: (3) 地址指针设置:设置将要进行操作的显示缓冲区(RAM)的一个单元地址,D1、D2为该单元地址的低位和高位地址。 2、显示区域设置,指令格式为: 根据N1,N0的不同取值,该指令有四种指令功能形式: 文本区和图形区首地址为对应显示屏上左上角字符位或字节位,修改该地址可以产生卷动效果。D1,D2分别为该地址的低位和高位字节。 文本区宽度(字节数/行)设置和图形区宽度(字节数/行)设置用于调整一行显示所占显示RAM的字节数,从而确定显示屏与显示RAM单元的对应关系。 T6963C硬件设置的显示窗口宽度是指T6963C扫描驱动的有效列数。需说明的是当硬件设置6×8字体时,图形显示区单元的低6位有效,对应显示屏上6×1显示位。 3、显示方式设置,指令格式为: N3:字符发生器选择位。 N3=1为外部字行发生器有效,此时内部字符发生器被屏蔽,字符代码全部 提供给外部字符发生器使用,字符代码为00H-FFH。 N3=0为CGROM即内部字符发生器有效,由于CGROM字符代码为00H~7FH。因此选用80H~FFH字符代码时,将自动选择CGRAM。 N2~N0:合成显示方式控制位,其组合功能如下表: 当设置文本方式和图形方式无能打开时,上述合成显示方式设置才有效。其中的文本特征方式是指将图形区改为文本特征区。该区大小与文本区相同,每个字节作为对应文本区的每个字符显示的特征,包括字符显示与不显示、字符闪烁及字符的“负向”显示。通过这种方式,T6963C可以控制每个字符的文本特征。文本特征区内,字符的文本特征码由一个字节的低四位组成,即: d3:字符闪烁控制位,d3=1为闪烁,d3=0为不闪烁; d2~d0的组合如下: 启用文本特征方式时可在原有图形区和文本区外用图形区域设置指令另开一区作为文本特征区,以保持原图形区的数据。显示缓冲区可划分如下: 4、显示开关,指令格式如下: N0:1/0,光标闪烁启用/禁止 N1:1/0,光标显示启用/禁止 N2:1/0,文本显示启用/禁止 N3:1/0,图形显示启用/禁止 5、光标形状选择,指令格式如下: 光标形状为8点(列) N行,N的值为0-7H 6、数据自动读、写方式设置: 该指令执行后,MPU可以连续地读、写显示缓冲区RAM的数据,每读、写一次,地址指针自动增1。自动读、写结束时,必须写入自动结束命令以使T6963C退出自动读、写状态,开始接受其它指令。 N1,N0组合功能如下: 7、数据一次读、写方式,指令格式如下: D1为需要写的数据,读时无此数据。 8、屏读,指令格式为: 该指令将屏上地址指针处文本与图形合成后显示的一字节内容数据送到T6963C的数据栈内,等待MPU读出。地址指针应在图形区内设置。 9、屏拷贝,指令格式为: 该指令将屏上当前地址指针(图形区内)处开始的一行合成显示内容拷贝到相对应的图形显示区的一组单元内,该指令不能用于文本特征方式下或双屏结构液晶显示器的应用上。 10、位操作: 该指令可将显示缓冲区某单元的某一位清零或置1,该单元地址当前地址指针提供。 N3=1置1,N3=0清零。 N2~N0:操作位,对应该单元的D0~D7位。 至此,T6963C的指令系统全部讲述完毕。 七、液晶显示模块与MCU的接口方法 一、直接访问方式 MPU可利用数据总线与控制信号直接采用I/O设备访问形式控制T6963C类液晶显示模块。接口电路以精电蓬远公司提供的演示板为例,如下图所示: 8031数据口P0口直接与液晶显示模块的数据口连接,由于T6963C接口适用于8080系列和Z80系列MPU,所以可以直接用8031的/RD、/WR作为液晶显示模块的读、写控制信号,液晶显示模块/RESET,/HALT挂在+5V上。/CE信号可由地址线译码产生。C/D信号由8031地址线A8提供,A8=1为指令口地址;A8=0为数据口地址。 指令通道地址C_ADD:8100H 数据通道地址D_ADD:8000H 二、间接控制方式 间接控制方式是MPU通过并行接口间接实现对液晶显示模块控制。根据液晶模块的需要,并行接口需要一个8位的并行接口和一个3位的并行口,由上图所示。8031的P1口作为数据总线。P3口中3位作为读、写及寄存器选择信号。由于并行接口只用于液晶显示模块,所以/CE信号接地就行了。MPU通过并行接口操纵液晶显示模块,要对其时序关系有一个清楚的了解,并在程序中应明确地反映出来。 八、LCD驱动程序的设计 以直接访问方式为例,说明LCD驱动程序的编制方法。 #include #include #include #include #include #define ulong unsigned long #define uint unsigned int #define uchar unsigned char #define TRUE 1 #define FALSE 0 #define HIGH 1 #define LOW 0 // T6963C 端口定义 #define LCMDW XBYTE[0x08100H] // 数据口 #define LCMCW XBYTE[0x08000H] // 命令口 // T6963C 命令定义 #define LCM_CUR_POS 0x21 // 光标位置设置 #define LCM_CGR_POS 0x22 // CGRAM偏置地址设置 #define LCM_ADD_POS 0x24 // 地址指针位置 #define LCM_TXT_STP 0x40 // 文本区首址 #define LCM_TXT_WID 0x41 // 文本区宽度 #define LCM_GRH_STP 0x42 // 图形区首址 #define LCM_GRH_WID 0x43 // 图形区宽度 #define LCM_MOD_OR 0x80 // 显示方式:逻辑"或" #define LCM_MOD_XOR 0x81 // 显示方式:逻辑"异或" #define LCM_MOD_AND 0x83 // 显示方式:逻辑"与" #define LCM_MOD_TCH 0x84 // 显示方式:文本特征 #define LCM_DIS_SW 0x90 // 显示开关:D0=1/0:光标闪烁启用/禁用; // D1=1/0:光标显示启用/禁用; // D2=1/0:文本显示启用/禁用; // D3=1/0:图形显示启用/禁用; #define LCM_CUR_SHP 0xA0 //光标形状选择:0xA0-0xA7表示光标占的行数 #define LCM_AUT_WR 0xB0 // 自动写设置 #define LCM_AUT_RD 0xB1 // 自动读设置 #define LCM_AUT_OVR 0xB2 // 自动读/写结束 #define LCM_INC_WR 0xC0 // 数据一次写,地址加1 #define LCM_INC_RD 0xC1 // 数据一次读,地址加1 #define LCM_DEC_WR 0xC2 // 数据一次写,地址减1 #define LCM_DEC_RD 0xC3 // 数据一次读,地址减1 #define LCM_NOC_WR 0xC4 // 数据一次写,地址不变 #define LCM_NOC_RD 0xC5 // 数据一次读,地址不变 #define LCM_SCN_RD 0xE0 // 屏读 #define LCM_SCN_CP 0xE8 // 屏拷贝 #define LCM_BIT_OP 0xF0 /* 位操作:D0-D2:定义D0-D7位;D3:1置位;0:清除 */ /* ----- 定义液晶屏内部RAM  ------ */ #define LCM_T_BASE 0x00            // 文本区内存首地址 #define LCM_G_BASE 0x00            // 图形区内存首地址 #define LCM_BYTES_PER_ROW 16         // 定义屏幕文本宽度为16字节 // 绘图坐标限制 #define LCM_XMAX 128   #define LCM_XMIN 0 #define LCM_YMAX 64 #define LCM_YMIN 0 // 判准备好子程序 uchar fnST01(void) // 状态位STA1,STA0判断(读写指令和读写数据) { uchar i; for(i=10;i>0;i--) { if((LCMCW & 0x03) == 0x03) break; } return i; // 若返回零,说明错误 } uchar fnST2(void) // 状态位ST2判断(数据自动读状态) { uchar i; for(i=10;i>0;i--) { if((LCMCW & 0x04) == 0x04) break; } return i; // 若返回零,说明错误 } uchar fnST3(void) // 状态位ST3判断(数据自动写状态) { uchar i; for(i=10;i>0;i--) { if((LCMCW & 0x08) == 0x08) break; } return i; // 若返回零,说明错误 } uchar fnST6(void) // 状态位ST6判断(屏读/屏拷贝状态) { uchar i; for(i=10;i>0;i--) { if((LCMCW & 0x40) == 0x40) break; } return i; // 若返回零,说明错误 } uchar fnPR10(uchar uCmd,uchar uPar1,uchar uPar2) // 写双参数的指令 { if(fnST01() == 0) return 1; LCMDW = uPar1; if(fnST01() == 0) return 2; LCMDW = uPar2; if(fnST01() == 0) return 3; LCMCW = uCmd; return 0; // 返回0成功 } uchar fnPR11(uchar uCmd,uchar uPar1) // 写单参数的指令 { if(fnST01() == 0) return 1; LCMDW = uPar1; if(fnST01() == 0) return 2; LCMCW = uCmd; return 0; // 返回0成功 } uchar fnPR12(uchar uCmd) // 写无参数的指令 { if(fnST01() == 0) return 1; LCMCW = uCmd; return 0; // 返回0成功 } uchar fnPR13(uchar uData) // 一次写数据 { if(fnST01() == 0) return 1; LCMDW = uData; return 0; // 返回0成功 } uchar fnPR14(uchar uData) // 自动写数据 { if(fnST3() == 0) return 1; LCMDW = uData; return 0; // 返回0成功 } uchar fnPR2(void) // 一次读数据 { if(fnST01() == 0) return 1; return LCMDW; } //设置地址 void LCM_set_address(unit addr) { fnPR1(LCM_ADD_POS, addr & 0xFF, addr / 256); //0x24为设定地址命令 } //文本方式设置显示坐标 void LCM_xy(uchar x, uchar y) { uint addr; addr = LCM_T_BASE + (y * LCM_BYTES_PER_ROW) + x;  LCM_set_address(addr);   // 设置显示地址 } //文本清屏 void LCM_clear_text(void) { uint i; fnPR1(LCM_ADD_POS, LCM_T_BASE,0x00); // 置地址指针 fnPR12(LCM_AUT_WR); // 自动写 for(i=0;i<16*8*;i++) { fnST3(); fnPR14(0x00); // 写数据 } fnPR12(LCM_AUT_OVR); // 自动写结束 fnPR1(LCM_ADD_POS, LCM_T_BASE,0x00); // 重置地址指针} } // 图形清屏 void LCM_clear_graph(void)  { uint i; fnPR1(LCM_ADD_POS, LCM_G_BASE,0x00); // 置地址指针 fnPR12(LCM_AUT_WR); // 自动写 for(i=0;i<16*8*8;i++) { fnST3(); fnPR14(0x00); // 写数据 } fnPR12(LCM_AUT_OVR); // 自动写结束 fnPR1(LCM_ADD_POS, LCM_G_BASE,0x00); // 重置地址指针 } //清全部32KB内存 void LCM_clear_ram(void)   { uint i; fnPR1(LCM_ADD_POS, 0x00,0x00); // 置地址指针 fnPR12(LCM_AUT_WR); // 自动写 for(i=0;i<8000;i++) { fnST3(); fnPR14(0x00); // 写数据 } fnPR12(LCM_AUT_OVR); // 自动写结束 fnPR1(LCM_ADD_POS, 0x00,0x00); // 重置地址指针 } // 初始化显存和显示模式 void LCM_init (void) { if(fnPR1(LCM_TXT_STP, LCM_T_BASE,0x00) != 0) // 文本显示区首地址 return -1; fnPR1(LCM_TXT_WID, LCM_BYTES_PER_ROW,0x00); // 文本显示区宽度 fnPR1(LCM_GRH_STP, LCM_G_BASE,0x00); // 图形显示区首地址 fnPR1(LCM_GRH_WID, LCM_BYTES_PER_ROW,0x00); // 图形显示区宽度 fnPR12(LCM_CUR_SHP | 0x07); // 光标形状 fnPR1(LCM_ADD_POS, 0x00,0x00); // 光标位置设置 fnPR12(LCM_MOD_OR); // 显示方式设置 fnPR12(LCM_DIS_SW | 0x0C); //显示设置为:图形开、文本开  // 注意:如果设置显示光标,需要设定光标的位置 return 0; } // 显示字符串RAM void LCM_print_ram(uchar x,uchar y, uchar *string)  {  uchar i,c;  LCM_xy(x,y); fnPR12(LCM_AUT_WR); // 自动写  for (i=0;string[i]!=0;i++) {   c = string[i] - 0x20;     // 转换ASCII码为屏幕内码 fnPR14(c); // 写数据  } fnPR12(LCM_AUT_OVR); // 自动写结束 } //声明函数 uchar fnST01(void) // 状态位STA1,STA0判断(读写指令和读写数据) uchar fnST2(void) // 状态位ST2判断(数据自动读状态) uchar fnST3(void) // 状态位ST3判断(数据自动写状态) uchar fnST6(void) // 状态位ST6判断(屏读/屏拷贝状态) uchar fnPR10(uchar uCmd,uchar uPar1,uchar uPar2)   // 写双参数的指令 uchar fnPR11(uchar uCmd,uchar uPar1) // 写单参数的指令 uchar fnPR12(uchar uCmd) // 写无参数的指令 uchar fnPR13(uchar uData) // 一次写数据 uchar fnPR14(uchar uData) // 自动写数据 uchar fnPR2(void) // 一次读数据 void LCM_init(void);             // 初始化显存和显示方式 void LCM_xy(uchar x, uchar y);    // 设置显示坐标(文本模式) void LCM_clear_text(void);         // 文本清屏 void LCM_print_ram(uchar x,uchar y,char *string);   // 显示字符串RAM void LCM_set_address(unit addr);   //设置地址 void LCM_clear_graph(void);         // 图形清屏 void LCM_pixel(uchar column, uchar row, char show); //画、清点 void LCM_show(uchar * s,int start_line,int how_many_line);    //指定数据组图 void LCM_line(int x1, int y1, int x2, int y2, uchar show); //画直线 void LCM_circle(int x, int y, int radius, uchar show);  //画圆 void LCM_circle_half(int x, int y, int radius, uchar show);//画半圆 void LCM_box(int x1, int y1, int x2, int y2, uchar show); //画矩形 //画线段 void LCM_degree_line(int x, int y, int degree, int inner_radius, int outer_radius, uchar show); //画线段包围线 void LCM_degree_line_bold(int x, int y, int degree, int inner_radius, int outer_radius, uchar show); void LCM_fill(int x1, int y1, int x2, int y2, uchar persent,char first); //画进度条 void DelayMs(unit ms); //画、清点函数 //column为水平点数,row为垂直点数 //show=1画点,show=0清点 void LCM_pixel(uchar column, uchar row, char show) {  int addr;       // memory address of byte containing pixel to write  if( (column>=LCM_XMAX) || (row>=LCM_YMAX) )return;  addr =  LCM_G_BASE + (row*LCM_BYTES_PER_ROW)  + (column/8);  LCM_set_address(addr);   // set LCD addr. Pointer  if(show)  fnPR13(0xf8 | (7-column%8));  // 0xf8为画点命令  else  fnPR13(0xf0 | (7-column%8));  // 0xf0为清点命令 } //以指定的数据进行画点 void LCM_show(uchar * s,int start_line,int how_many_line){  int addr,i;  addr =  LCM_G_BASE +start_line*16;  LCM_set_address(addr);  fnPR12(LCM_AUT_WR);   //自动写模式  for(i=0;i dy)  {   fraction = dy - (dx >> 1);   while (x1 != x2)   {    if (fraction >= 0)    {     y1 += stepy;     fraction -= dx;    }    x1 += stepx;    fraction += dy;     LCM_pixel(x1,y1,show);   }  }  else  {   fraction = dx - (dy >> 1);   while (y1 != y2)   {    if (fraction >= 0)    { x1 += stepx;     fraction -= dy;    }    y1 += stepy;    fraction += dx;    LCM_pixel(x1,y1,show);   }  } } /*********************************************************************** 以x,y为圆心,以radius为半径画贺 (show=1画点,show=0清点) ***********************************************************************/ void LCM_circle(int x, int y, int radius, uchar show) {  int xc = 0;  int yc ;  int p ;  yc=radius;  p = 3 - (radius<<1);  while (xc <= yc)   {   LCM_pixel(x + xc, y + yc, show);   LCM_pixel(x + xc, y - yc, show);   LCM_pixel(x - xc, y + yc, show);   LCM_pixel(x - xc, y - yc, show);   LCM_pixel(x + yc, y + xc, show);   LCM_pixel(x + yc, y - xc, show);   LCM_pixel(x - yc, y + xc, show);   LCM_pixel(x - yc, y - xc, show);   if (p < 0)   p += (xc++ << 2) + 6;   else   p += ((xc++ - yc--)<<2) + 10;  } } //画半圆 void LCM_circle_half(int x, int y, int radius, uchar show) {  int xc = 0;  int yc ;  int p ;  yc=radius;  p = 3 - (radius<<1);  while (xc <= yc)   {   //    LCM_pixel(x + xc, y + yc, show);   LCM_pixel(x + xc, y - yc, show);   //    LCM_pixel(x - xc, y + yc, show);   LCM_pixel(x - xc, y - yc, show);   //    LCM_pixel(x + yc, y + xc, show);   LCM_pixel(x + yc, y - xc, show);   //    LCM_pixel(x - yc, y + xc, show);   LCM_pixel(x - yc, y - xc, show);   if (p < 0)   p += (xc++ << 2) + 6;   else   p += ((xc++ - yc--)<<2) + 10;  } } //画矩形 void LCM_box(int x1, int y1, int x2, int y2, uchar show) {  LCM_line(x1,y1,x2,y1,show);  // up  LCM_line(x1,y2,x2,y2,show);  // down  LCM_line(x2,y1,x2,y2,show);  // right  LCM_line(x1,y1,x1,y2,show);  // left } //*********************************************************************** //以x,y点为原点,以degree为角度,画一条从内径到外径之间的线段 //(show=1画点,show=0清点) //*********************************************************************** /* void LCM_degree_line(int x, int y, int degree, int inner_radius, int outer_radius, uchar show) {   int fx,fy,tx,ty;   fx = x + (inner_radius * sin(degree * 3.14 / 180));   fy = y - (inner_radius * cos(degree * 3.14 / 180));   tx = x + (outer_radius * sin(degree * 3.14 / 180));   ty = y - (outer_radius * cos(degree * 3.14 / 180));   LCM_line(fx,fy,tx,ty,show); } //画上函数线段的包括线 void LCM_degree_line_bold(int x, int y, int degree, int inner_radius, int outer_radius, uchar show) {   int fx,fy,tx,ty;   fx = x + (inner_radius * sin(degree * 3.14 / 180));    fy = y - (inner_radius * cos(degree * 3.14 / 180));   tx = x + (outer_radius * sin(degree * 3.14 / 180));   ty = y - (outer_radius * cos(degree * 3.14 / 180));   LCM_line(fx,fy,tx,ty,show);   LCM_line(fx+1,fy+1,tx+1,ty+1,show);   LCM_line(fx-1,fy-1,tx-1,ty-1,show); } */ //画进度条函数 /* void LCM_fill(int x1, int y1, int x2, int y2, uchar persent,char first) {  char M,horizon_line,horizon_line2,i,str1[10];  if(persent>100)return;  if(!first) {   LCM_line(x1,y2,x2,y2,1);  // down   LCM_line(x2,y1,x2,y2,1);  // right   LCM_line(x1,y1,x1,y2,1);  // left   first=1;  }  M=100/abs(y2-y1);   horizon_line=persent/M;  for(i=0;i 0; iq0--)  for (iq1 = 1000; iq1 > 0; iq1--);  } void main(void) // 测试用 {     LCM_init();  LCM_clear_ram(); LCM_circle(120,64,20,1); LCM_circle_half(60,64,20,1); LCM_box(150,20,180,60,1);  }

    Top_arrow
    回到顶部
    EEWORLD下载中心所有资源均来自网友分享,如有侵权,请发送举报邮件到客服邮箱bbs_service@eeworld.com.cn 或通过站内短信息或QQ:273568022联系管理员 高员外,我们会尽快处理。