资源描述
T6963C的使用(C语言)
内置T6963C的128×128图形液晶显示模块
从图1我们可以看出:
(1)偏压电路的设计
液晶显示驱动电源采用了1/13偏压电路(),电阻R1~R5组成了分压电路,其中:R1=R2=R4=R5=R,R3的值为()R。
驱动负电源由接口V0提供。
(2)驱动电路的组成
在液晶显示驱动控制系统中,由两片T6A39列驱动器和两片T6A40行驱动器组成驱动电路。
(3)T6963C工作参数的设置
T6963C的工作参数设置如下:
/DUAL=1 单屏结构
SDSEL=0 一位串行数据传输
MDS=1、MDl=MD0=0 N=16即1/128占空比系数
MD2=MD3=1 M=32即256点列/行
FS0=0 通过计算机选择6×8点阵字体或8×8点阵字体
(4)晶振频率选择
根据T6963的设置参数可以求得:
Fosc= FR×64×2×M×N =60×64×2×32×16=3.932MHz。
通过查表6-32也可以得到频率值,大小也为3.932MHz。这个时候,选用4MHz的晶振。
(5)显示存储器
显示存储器为8K字节容量,存储器芯片为6264或其它SRAM。
图1 内置T6963C的128×128图形液晶显示模块的电原理图
内置T6963C控制器的液晶显示模块的接口技术
内置T6963C控制器的液晶显示模块与计算机的接口时序为Inter8080时序。本节以常用的单片机AT89C51为实验样机,以模块128128为显示样片叙述计算机与内置T6963C控制器的液晶显示模块的接口技术。
1 直接访问方式
直接访问方式是把内置T6963C控制器的液晶显示模块作为存储器或I/O设备直接挂在计算机的总线上。模块的数据线接计算机的数据总线上,片选及寄存器选择信号线由计算机的地址总线提供,读和写操作由计算机的读写操作信号控制。
计算机直接访问方式下与内置T6963C控制器的液晶显示模块的实用接口电路如图1所示。
图1 直接访问方式下接口电路图
上图所示的电路,对于完成液晶显示模块的显示来说,所用的硬件是相对比较少的,但是如果计算机需要进行扩展的话,使用上图的话不是很经济(浪费了太多的地址空间)。这个时候,可以考虑使用全地址译码或者部分地址译码的方式。
在上图所示的电路中:
●8位数据总线与AT89C51的数据总线连接
●地址线A15作为模块操作的片选线
●地址线A14作为模块的寄存器选择线C/D
这样就确定了AT89C51操作字符型液晶显示模块的唯一地址选择。
图中的电位器为V0提供了可调的驱动电压,用以实现显示对比度的调节。
以下将给出直接访问方式的驱动程序。
(1)地址定义
#include <reg51.h>
#include <stdio.h>
#include <intrins.h>
#define uchar unsigned char
#define uint unsigned int
#define nop() _nop_()
xdata uchar CmdADD _at_ 0xC000;
xdata uchar DatADD _at_ 0x8000;
#define STA0 0
#define STA1 1
#define STA2 2
#define STA3 3
#define STA6 6
(2)读状态字与状态判断
uchar ReadST(uchar Status)
{
uchar temp;
temp=CmdADD;
switch(status)
{
case 0:
temp&=0x01; /*屏蔽其余位*/
break;
case 1:
temp&=0x02; /*屏蔽其余位*/
break;
case 2:
temp&=0x04; /*屏蔽其余位*/
break;
case 3:
temp&=0x08; /*屏蔽其余位*/
break;
case 6:
temp&=0x40; /*屏蔽其余位*/
break;
default:break;
}
return temp;
}
(3)写指令和写数据
/*写入一个字节的数据*/
void WrDat(uchar dat)
{
while(ReadST(STA1)==0x00) {}
DatADD=dat;
}
/*写入无参数的命令*/
void WrCom1(uchar cmd)
{
while(ReadST(STA0)==0x00) {}
CmdADD=cmd;
}
/*写入带一个参数的命令*/
void WrCom2(uchar dat,cmd)
{
WrDat(dat);
Com1(cmd);
}
/*写入带两个参数的命令*/
void WrCom3(uchar dat1,dat2,cmd)
{
WrDat(dat1);
WrDat(dat2);
WrCom1(cmd);
}
(4)读数据
uchar RdDat(void)
{
uchar temp;
while(ReadST(STA1)==0x00) {}
temp=DatADD;
return temp;
}
2 间接控制方式
间接控制方式是将内置T6963C控制器的液晶显示模块与计算机系统中的某个并行I/O接口连接,计算机通过对该I/O接口的操作间接的实现对模块的控制。本文以AT89C51的P1和P2接口为并行接口与字符型液晶显示模块连接,图2给出了本文推荐的实用接口电路。
图2 间接控制方式下的接口电路图
图中的电位器为V0提供了可调的驱动电压,用以实现显示对比度的调节。
在编制驱动函数的时候,要注意时序的配合,根据Intel8080时序的规范,间接控制方式通过软件执行产生操作时序,所以在时间上是足够满足要求的。因此间接控制方式能够实现高速计算机与字符型液晶显示模块的连接。
(1)接口定义
#include <reg51.h>
#include <stdio.h>
#include <intrins.h>
#define uchar unsigned char
#define uint unsigned int
#define nop() _nop_()
#define STA0 0
#define STA1 1
#define STA2 2
#define STA3 3
#define STA6 6
sbit CD=P2^7;
sbit CE=P2^6;
sbit RD=P2^5;
sbit WR=P2^4;
(2)读状态字与状态判断
uchar ReadST(uchar Status)
{
uchar temp;
CE=0;
P1=0xFF;
CD=1;
RD=0;
temp=P1;
RD=1;
switch(status)
{
case 0:
temp&=0x01; /*屏蔽其余位*/
break;
case 1:
temp&=0x02; /*屏蔽其余位*/
break;
case 2:
temp&=0x04; /*屏蔽其余位*/
break;
case 3:
temp&=0x08; /*屏蔽其余位*/
break;
case 6:
temp&=0x40; /*屏蔽其余位*/
break;
default:break;
}
return temp;
}
(3)写指令和写数据
/*写入一个字节的数据*/
void WrDat(uchar dat)
{
while(ReadST(STA1)==0x00) {}
CD=0;
P1=dat;
WR=0;
WR=1;
}
/*写入无参数的命令*/
void WrCom1(uchar cmd)
{
while(ReadST(STA0)==0x00) {}
CD=1;
P1=dat;
WR=0;
WR=1;
}
/*写入带一个参数的命令*/
void WrCom2(uchar dat,cmd)
{
WrDat(dat);
Com1(cmd);
}
/*写入带两个参数的命令*/
void WrCom3(uchar dat1,dat2,cmd)
{
WrDat(dat1);
WrDat(dat2);
WrCom1(cmd);
}
(4)读数据
uchar RdDat(void)
{
uchar temp;
while(ReadST(STA1)==0x00) {}
CD=0;
P1=0xFF;
RD=0;
temp=P1;
RD=1;
return temp;
}
内置T6963C控制器型图形液晶显示模块的应用软件
内置T6963C图形液晶显示模块的应用是随应用系统的性质而定,本节将提供一些实用程序并作为示例进一步对T6963C指令的应用作一说明。
接口电路为图2和图3所示的实用电路,驱动程序也为上一节所提供的。使用的液晶显示模块的样机的电原理图为图6-66所示的128×128图形点阵的原理图,供使用者参考。
1 初始化设置
初始化设置主要是对显示区域的设置和显示方式的设置。这个程序只需在主程序对系统初始化时调用一次就可以了,除非要在应用中需要改变设置。是为了计算地址的方便,设置显示区域的宽度为10H,即16个字节(128/8=16)。初始化子程序通常在主程序开始时调用。
void Init(void)
{
WrCom3(0x00,0x00,0x40);
WrCom3(0x10,0x00,0x41);
WrCom3(0x00,0x08,0x42);
WrCom3(0x10,0x00,0x43);
WrCom1(0xA7);
WrCom1(0x80);
WrCom1(0x9C);
}
2 清显示存储器
该子程序对显示存储器完全清零,不分显示区域性质。所以在初始化时使用和在全显示存储器需要清零时使用。
void ClearLCD(void)
{
uint temp;
WrCom3(0x00,0x00,0x24);
WrCom1(0xB0);
for(temp=0;temp<8192;temp++)
{
while(ReadST(STA3)==0x00) {}
WrDat(0x00);
}
WrCom1(0xB2);
}
3 建立CGRAM
该程序是在内部CGROM有效时建立CGRAM的子程序,所以使用的字符代码是从80H开始的。
一般在建立CGRAM的时候,把CGRAM定义在SRAM的最后面的一段地址空间内,在本段代码中,因为CGROM有效,所以只能定义128个CGRAM,占用的空间为1KB,地址空间为1C00H~1FFFH。
这个时候,可以看出起始地址的偏置地址值与字符代码值的大小如下:
ad15
ad14
ad13
ad12
ad11
ad10
ad9
ad8
ad7
ad6
ad5
ad4
ad3
ad2
ad1
ad0
0
0
0
1
1
1
0
0
0
0
0
0
0
0
0
0
●偏置地址值为03H;
●字符代码从80H开始。
void WrCGRAM(uchar count,*tab)
{
uint temp,counttemp;
counttemp=count<<3;
WrCom3(0x03,0x00,0x22);
WrCom3(0x00,0x1C,0x24);
WrCom1(0xB0);
for(temp=0;temp<counttemp;temp++)
{
while(ReadST(STA3)==0x00) {}
WrDat(*(tab+temp));
}
WrCom1(0xB2);
}
4 西文字符写入(文本属性显示方式的应用)
非文本属性显示方式的西文字符写入非常简单,先设置显示地址指针(24H),再写入字符代码即可。所以这里就不再举例说明了。
该程序使用了字符代码和字符显示属性两个参数。将图形显示区域作为文本属性区。在写入字符代码后将字符的属性参数写入相应的属性区内。注意观察不同属性的显示效果。
//字模,属性,列,行
void WrTXT(uchar code,pred,o_x,o_y)
{
uchar temp,addr1,addr2;
uint addr;
addr=o_y<<4+o_x;
addr1=addr;
addr2=addr>>8;
WrCom3(addr1,addr2,0x24);
WrCom2(code,0xC4);
addr2+=8;
WrCom3(addr1,addr2,0x24);
WrCom2(pred,0xC4);
}
uchar code TXTTAB[]={
0x28,0x45,0x4C,0x4C,0x4F,0x00,0x37,0x4F,0x52,0x4C,0x44
};
void DispTXT(void)
{
uchar temp1,temp2;
WrCom1(0x84);
WrCom1(0x9F);
WrCom3(8,1,0x21);
for(temp1=0;temp1<13;temp1++)
{
for(temp2=0;temp1<11;temp2++)
{
WrTXT(*(TXTTAB+temp2),temp1,temp2,1);
}
Delayms(200);
}
}
5 汉字写入(图形方式)
在图形方式下显示汉字是比较常用的方法。汉字库作在程序区内,按排序定义各汉字的代码。写入汉字字模如同写入图形数据一般,这里提供单字节汉字代码使用的汉字写入子程序。
在这个程序段中,将128×128的液晶显示屏分成了8行8列共64个16×16的显示区域,每个区域显示一个汉字。
//显示汉字,某行某列
//这个函数将128×128分为8行8列共64个区域,每个对应一个16×16点阵的汉字
//字模数组,列,行,字模
void WrCC(uchar *zimo,o_x,o_y,uint code)
{
uchar i,addr1,addr2;
uint addr;
addr=o_y<<8+o_x<<2;
addr1=addr;
addr2=addr>>8;
code<<=5;
for(i=0;i<16;i++)
{
WrCom3(addr1+i*16,8+addr2,0x24);
WrCom2(*(zimo+code),0xC0);
code++;
WrCom2(*(zimo+code),0xC4);
code++;
}
}
uchar code CCTAB[]={
/*-- 文字: 液 代码“0x00”*/
0x40,0x40,0x20,0x20,0x27,0xFE,0x09,0x20,
0x89,0x20,0x52,0x7C,0x52,0x44,0x16,0xA8,
0x2B,0x98,0x22,0x50,0xE2,0x20,0x22,0x30,
0x22,0x50,0x22,0x88,0x23,0x0E,0x22,0x04,
/*-- 文字: 晶 代码“0x01”*/
0x00,0x00,0x0F,0xF0,0x08,0x10,0x0F,0xF0,
0x08,0x10,0x0F,0xF0,0x08,0x10,0x00,0x00,
0x7E,0x7E,0x42,0x42,0x7E,0x7E,0x42,0x42,
0x42,0x42,0x7E,0x7E,0x42,0x42,0x00,0x00,
/*-- 文字: 显 代码“0x02”*/
0x00,0x00,0x1F,0xF0,0x10,0x10,0x1F,0xF0,
0x10,0x10,0x1F,0xF0,0x04,0x40,0x04,0x40,
0x44,0x48,0x24,0x48,0x14,0x50,0x14,0x60,
0x04,0x40,0xFF,0xFE,0x00,0x00,0x00,0x00,
/*-- 文字: 示 代码“0x03”*/
0x00,0x00,0x1F,0xF8,0x00,0x00,0x00,0x00,
0x00,0x00,0x7F,0xFE,0x01,0x00,0x01,0x00,
0x11,0x20,0x11,0x10,0x21,0x08,0x41,0x0C,
0x81,0x04,0x01,0x00,0x05,0x00,0x02,0x00,
};
6 屏读演示程序段
屏读操作是依据T6963C引脚MD3,MD2设置的显示窗口长度参数操作的。在128128液晶显示模块上显示窗长度设置为256点,即32个字节长,所以在应用屏读操作时,要设置文本区和图形区的宽度与引脚设置参数相等才能正确的使用。这样做图形区的地址与文本区的地址才能对应起来。
下面提供的演示程序是将在文本显示下的“H”和“C”屏读写入相应的图形区中,然后关文本显示以观看显示效果——这两个字符依然存在。
uchar LCDRdData[8];
void LCDRead(uchar o_x,o_y)
{
uchar temp,addr1,addr2;
uint addr;
WrCom3(0x20,0x00,0x41);
WrCom3(0x20,0x00,0x43);
addr=o_x<<9+o_y;
addr1=addr;
addr2=addr>>8;
for(temp=0;temp<8;temp++)
{
WrCom3(addr1+temp<<5,addr2+8,0x24);
do
{
WrCom1(0xE0);
}
while(ReadST(STA6)==0x40);
LCDRdData[temp]=RdDat();
}
}
7 屏拷贝演示程序段
屏读操作是依据T6963C引脚MD3,MD2设置的显示窗口长度参数操作的。在128128液晶显示模块上显示窗长度设置为256点,即32个字节长,所以在应用屏读操作时,要设置文本区和图形区的宽度与引脚设置参数相等才能正确的使用。这样做图形区的地址与文本区的地址才能对应起来。
下面提供的演示程序是将在文本显示下的“H”和“C”屏拷贝写入相应的图形区中,然后关文本显示以观看显示效果——这两个字符依然存在。
void LCDCopy(uchar o_x,o_y)
{
uchar temp,addr1,addr2;
uint addr;
WrCom3(0x20,0x00,0x41);
WrCom3(0x20,0x00,0x43);
addr=o_x<<9+o_y;
addr1=addr;
addr2=addr>>8;
for(temp=0;temp<8;temp++)
{
WrCom3(addr1+temp<<5,addr2+8,0x24);
do
{
WrCom1(0xE8);
}
while(ReadST(STA6)==0x40);
}
}附录资料:不需要的可以自行删除
Abstract: Based on the comprehensive analysis on the plastic part’s structure service requirement, mounding quality and mould menu factoring cost. A corresponding injection mould of internal side core pulling was designed. By adopting the multi-direction and multi-combination core-pulling. A corresponding injection mould of internal side core pulling was designed, the working process of the mould was introduced
C语言详解 - 枚举类型
注:以下全部代码的执行环境为VC++ 6.0
在程序中,可能需要为某些整数定义一个别名,我们可以利用预处理指令#define来完成这项工作,您的代码可能是:
#define MON 1
#define TUE 2
#define WED 3
#define THU 4
#define FRI 5
#define SAT 6
#define SUN 7
在此,我们定义一种新的数据类型,希望它能完成同样的工作。这种新的数据类型叫枚举型。
1. 定义一种新的数据类型 - 枚举型
以下代码定义了这种新的数据类型 - 枚举型
enum DAY
{
MON=1, TUE, WED, THU, FRI, SAT, SUN
};
(1) 枚举型是一个集合,集合中的元素(枚举成员)是一些命名的整型常量,元素之间用逗号,隔开。
(2) DAY是一个标识符,可以看成这个集合的名字,是一个可选项,即是可有可无的项。
(3) 第一个枚举成员的默认值为整型的0,后续枚举成员的值在前一个成员上加1。
(4) 可以人为设定枚举成员的值,从而自定义某个范围内的整数。
(5) 枚举型是预处理指令#define的替代。
(6) 类型定义以分号;结束。
2. 使用枚举类型对变量进行声明
新的数据类型定义完成后,它就可以使用了。我们已经见过最基本的数据类型,如:整型int, 单精度浮点型float, 双精度浮点型double, 字符型char, 短整型short等等。用这些基本数据类型声明变量通常是这样:
char a; //变量a的类型均为字符型char
char letter;
int x,
y,
z; //变量x,y和z的类型均为整型int
int number;
double m, n;
double result; //变量result的类型为双精度浮点型double
既然枚举也是一种数据类型,那么它和基本数据类型一样也可以对变量进行声明。
方法一:枚举类型的定义和变量的声明分开
enum DAY
{
MON=1, TUE, WED, THU, FRI, SAT, SUN
};
enum DAY yesterday;
enum DAY today;
enum DAY tomorrow; //变量tomorrow的类型为枚举型enum DAY
enum DAY good_day, bad_day; //变量good_day和bad_day的类型均为枚举型enum DAY
方法二:类型定义与变量声明同时进行:
enum //跟第一个定义不同的是,此处的标号DAY省略,这是允许的。
{
saturday,
sunday = 0,
monday,
tuesday,
wednesday,
thursday,
friday
} workday; //变量workday的类型为枚举型enum DAY
enum week { Mon=1, Tue, Wed, Thu, Fri Sat, Sun} days; //变量days的类型为枚举型enum week
enum BOOLEAN { false, true } end_flag, match_flag; //定义枚举类型并声明了两个枚举型变量
方法三:用typedef关键字将枚举类型定义成别名,并利用该别名进行变量声明:
typedef enum workday
{
saturday,
sunday = 0,
monday,
tuesday,
wednesday,
thursday,
friday
} workday; //此处的workday为枚举型enum workday的别名
workday today, tomorrow; //变量today和tomorrow的类型为枚举型workday,也即enum workday
enum workday中的workday可以省略:
typedef enum
{
saturday,
sunday = 0,
monday,
tuesday,
wednesday,
thursday,
friday
} workday; //此处的workday为枚举型enum workday的别名
workday today, tomorrow; //变量today和tomorrow的类型为枚举型workday,也即enum workday
也可以用这种方式:
typedef enum workday
{
saturday,
sunday = 0,
monday,
tuesday,
wednesday,
thursday,
friday
};
workday today, tomorrow; //变量today和tomorrow的类型为枚举型workday,也即enum workday
注意:同一个程序中不能定义同名的枚举类型,不同的枚举类型中也不能存在同名的命名常量。错误示例如下所示:
错误声明一:存在同名的枚举类型
typedef enum
{
wednesday,
thursday,
friday
} workday;
typedef enum WEEK
{
saturday,
sunday = 0,
monday,
} workday;
错误声明二:存在同名的枚举成员
typedef enum
{
wednesday,
thursday,
friday
} workday_1;
typedef enum WEEK
{
wednesday,
sunday = 0,
monday,
} workday_2;
3. 使用枚举类型的变量
3.1 对枚举型的变量赋值。
实例将枚举类型的赋值与基本数据类型的赋值进行了对比:
方法一:先声明变量,再对变量赋值
#include<stdio.h>
/* 定义枚举类型 */
enum DAY { MON=1, TUE, WED, THU, FRI, SAT, SUN };
void main()
{
/* 使用基本数据类型声明变量,然后对变量赋值 */
int x, y, z;
x = 10;
y = 20;
z = 30;
/* 使用枚举类型声明变量,再对枚举型变量赋值 */
enum DAY yesterday, today, tomorrow;
yesterday = MON;
today = TUE;
tomorrow = WED;
printf("%d %d %d \n", yesterday, today, tomorrow);
}
方法二:声明变量的同时赋初值
#include <stdio.h>
/* 定义枚举类型 */
enum DAY { MON=1, TUE, WED, THU, FRI, SAT, SUN };
void main()
{
/* 使用基本数据类型声明变量同时对变量赋初值 */
int x=10, y=20, z=30;
/* 使用枚举类型声明变量同时对枚举型变量赋初值 */
enum DAY yesterday = MON,
today = TUE,
tomorrow = WED;
printf("%d %d %d \n", yesterday, today, tomorrow);
}
方法三:定义类型的同时声明变量,然后对变量赋值。
#include <stdio.h>
/* 定义枚举类型,同时声明该类型的三个变量,它们都为全局变量 */
enum DAY { MON=1, TUE, WED, THU, FRI, SAT, SUN } yesterday, today, tomorrow;
/* 定义三个具有基本数据类型的变量,它们都为全局变量 */
int x, y, z;
void main()
{
/* 对基本数据类型的变量赋值 */
x = 10; y = 20; z = 30;
/* 对枚举型的变量赋值 */
yesterday = MON;
today = TUE;
tomorrow = WED;
printf("%d %d %d \n", x, y, z); //输出:10 20 30
printf("%d %d %d \n", yesterday, today, tomorrow); //输出:1 2 3
}
方法四:类型定义,变量声明,赋初值同时进行。
#include <stdio.h>
/* 定义枚举类型,同时声明该类型的三个变量,并赋初值。它们都为全局变量 */
enum DAY
{
MON=1,
TUE,
WED,
THU,
FRI,
SAT,
SUN
}
yesterday = MON, today = TUE, tomorrow = WED;
/* 定义三个具有基本数据类型的变量,并赋初值。它们都为全局变量 */
int x = 10, y = 20, z = 30;
void main()
{
printf("%d %d %d \n", x, y, z); //输出:10 20 30
printf("%d %d %d \n", yesterday, today, tomorrow); //输出:1 2 3
}
3.2 对枚举型的变量赋整数值时,需要进行类型转换。
#include <stdio.h>
enum DAY { MON=1, TUE, WED, THU, FRI, SAT, SUN };
void main()
{
enum DAY yesterday, today, tomorrow;
yesterday = TUE;
today = (enum DAY) (yesterday + 1); //类型转换
tomorrow = (enum DAY) 30; //类型转换
//tomorrow = 3; //错误
printf("%d %d %d \n", yesterday, today, tomorrow); //输出:2 3 30
}
3.3 使用枚举型变量
#include<stdio.h>
enum
{
BELL = '\a',
BACKSPACE = '\b',
HTAB = '\t',
RETURN = '\r',
NEWLINE = '\n',
VTAB = '\v',
SPACE = ' '
};
enum BOOLEAN { FALSE = 0, TRUE } match_flag;
void main()
{
int index = 0;
int count_of_letter = 0;
int count_of_space = 0;
char str[] = "I'm Ely efod";
match_flag = FALSE;
for(; str[index] != '\0'; index++)
if( SPACE != str[index] )
count_of_letter++;
else
{
match_flag = (enum BOOLEAN) 1;
count_of_space++;
}
printf("%s %d times %c", match_flag ? "match" : "not match", count_of_space, NEWLINE);
printf("count of letters: %d %c%c", count_of_letter, NEWLINE, RETURN);
}
输出:
match 2 times
count of letters: 10
Press any key to continue
4. 枚举类型与sizeof运算符
#include <stdio.h>
enum escapes
{
BELL = '\a',
BACKSPACE = '\b',
HTAB = '\t',
RETURN = '\r',
NEWLINE = '\n',
VTAB = '\v',
SPACE = ' '
};
enum BOOLEAN {
展开阅读全文