引 言
液晶显示器具有显示信息多、体积小、功耗低等特点,被广泛用于终端显示、人机接口。它与高性能的RabbitCore RCM2200模块配合使用,可以组成高级智能化仪器。在我们开发的蓝牙无线数据接收与发送系统中用于蓝牙设备链接信息及数据的发送和接收量等相关信息的显示具有相当重要的作用。本文给出RabbitCore
RCM2200模块与M12864-7A7实用的接口电路及软件设计。
Rabbit2000及RabbitCore RCM2200简介
Rabbit2000是8位微处理器,它和Z80系列微处理器有相似的结构和高度的兼容性,但性能有很大的提高。它具有4个串行端口,40个通用I/O引脚,内建日历、时钟、看门狗、定时器、多级中断、双DMA通道,可外扩4~8MB
Flash,用于数据存储。对于8位总线的微处理器,Rabbit构造了其大部分外部8位总线并且具有简嗟闹噶罴希蚨阅苡胄矶?6位处理器一样棒,可执行许多16位操作。Rabbit2000用1根接口电缆把PC串口和基于Rabbit2000的目标系统连接起来就可实现软件的开发,并得到Dynamic
C编译器的支持,这种编译器的特点是有一个交互式编译程序、编辑程序和调试程序。汇编语言代码可嵌入Dynamic C代码中,或作为一个独立的功能使用。编译和调试可在不脱离Dynamic
C开发环境下实现,既缩短了开发时间,也更易于编程。
RabbitCore RCM2200模块采用Rabbit 2000微处理器,有256K的Flash及128K的SRAM,4个串口,26个I/O口,10Base-T
以态网口。使用RCM2200能够通过网络或Internet来控制、监测及调试嵌入式系统。有支持RCM2200的软件工具包,提供TCP/IP协议和Dynamic
C系统软件。
KS0108B液晶控制器
KS0108B液晶显示控制器多用于中小模块的图形点阵液晶显示器件(日立的HD61202与其完全兼容,可直接替代)。KS0108B的特点是内置64
64位的显示存储器,显示屏上各象素点的显示状态与显示存储器的各位数据一一对应,显示存储器的数据直接作为图形显示的驱动信号:显示数据为"1"相应的象素点显示,为"0"时相应的象素点不显示。KS0108B需要与相应的带振荡器和显示时序发动器的行驱动器KS0107B配套才能形成一个完整的液晶驱动和控制系统。KS0108B指令及其功能表1所示。
表1 KS0108B指令及其功能说明表(略)
表2 外部接口信号(略)
M12864-7A7液晶模块框图及引脚说明
M12864-7A7液晶显示模块使用两片KS0108B作为列驱动器,同时使用一片KS0107B作为行驱动器,KS0107B不与MCU发生联系只要提供电源就能产生行驱动信号和各种同步信号。图1是液晶模块的框图和接口引脚说明。
外部接口信号如表2所示:
硬件接口电路及说明
内置KS0108B图形点阵液晶显示模块与MCU(单片机或Rabbit2000等)的连接方式有两种:直接访问方式和间接控制方式。直接访问方式是将液晶显示模块的接口作为存储器或I/O设备直接挂在MCU总线上,MCU以访问存储器或I/O设备的方式操作液晶显示模块的工作。间接控制方式是MCU通过自身或系统中的并行接口与液晶显示模块连接,下面给出的应用中就是用到了RCM2200的并行端口中的PA口及PB,PD,PE口中的某些引脚。MCU通过对这些接口的操作以达到对液晶显示模块的控制。
图1 显示模块框图及接口引脚说明(略)
图2 M12864-7A7与RCM2200的间接控制方式接口电路(略)
图2的电路中以RCM2200的PA口作为数据口,PB7为RET,PD3为D/I,PD4为R/W,PD5为E,PE5为CS1和PE7为CS2等信号。V0是液晶需要的负压,可通过与它相连的电位器来调节电压大小(电压变化范围为-10~0V),从而达到调节显示对比度的目的。
Dynamic C源程序及说明
程序说明
本段重点讲述显示汉字的子程序,它可以在指定位置显示指定的汉字。7个子程序分别为初始化LCD子程序、清屏子程序、写指令子程序、写数据子程序、延时子程序、指定位置显示单个汉字和信息显示子程序。
下面给出的是图2所示的间接控制方式的一些子程序,所有的程序都是用Dynamic C 7.32TSE版本编译器来编译调试并通过的。
源程序及解释
/*-----------定义寄存器的指令代码----------*/
#define Disp_On 0x3f
#define Disp_Off 0x3e
#define Col_Add 0x40
#define Page_Add 0xb8
#define Start_Line 0xc0
const char xian[]={ /*--文字: 显,宋体12;此字体下对应的点阵为:宽x高=16x16 --*/
0x00,0x00,0x00,0x3E,0x2A,0xEA,0x2A,0x2A,0x2A,0xEA,0x2A,0x3E,0x00,0x00,0x00,0x00,
0x20,0x21,0x22,0x2C,0x20,0x3F,0x20,0x20,0x20,0x3F,0x28,0x24,0x23,0x20,0x20,0x00
}
const char shi[]={ /*--文字: 示,宋体12;此字体下对应的点阵为:宽x高=16x16 --*/
0x10,0x08,0x04,0x03,0x00,0x40,0x80,0x7F,0x00,0x00,0x01,0x02,0x0C,0x18,0x00,0x00
}
/*------――-延时子程序--------------*/
void Delay(unsigned int t)
{
unsigned int i,j;
for(i=0;i<t;i++)
for(j=0;j<10;j++) ;
}
/*---------写命令到LCD-------------*/
void Write_Command(char cmdcode)
{
WrPortI(PDDDR,&PDDDRShadow,PDDDRShadow|0x18); //PD3, PD4 为输出
BitWrPortI(PDDR,&PDDRShadow,0,3); //D/I=0
BitWrPortI(PDDR,&PDDRShadow,0,4); //R/W=0
WrPortI(PADR,&PADRShadow,cmdcode);
WrPortI(SPCR,&SPCRShadow,0x84); //使PA口为输出
Delay(0);
WrPortI(PDDDR,&PDDDRShadow,PDDDRShadow|0x20); //PD5为 输出
BitWrPortI(PDDR,&PDDRShadow,1,5); //E=1
Delay(0);
BitWrPortI(PDDR,&PDDRShadow,0,5); //E=0
}
/*------------写数据到LCD-------------*/
void Write_Data(char Dispdata)
{
WrPortI(PDDDR,&PDDDRShadow,PDDDRShadow|0x18); //PD3, PD4为输出
BitWrPortI(PDDR,&PDDRShadow,1,3); //D/I=1
BitWrPortI(PDDR,&PDDRShadow,0,4); //R/W=0
WrPortI(PADR,&PADRShadow,Dispdata);
WrPortI(SPCR,&SPCRShadow,0x84); //使PA口为 输出
Delay(0);
WrPortI(PDDDR,&PDDDRShadow,PDDDRShadow|0x20); //PD5为 输出
BitWrPortI(PDDR,&PDDRShadow,1,5); //E=1
Delay(0);
BitWrPortI(PDDR,&PDDRShadow,0,5); //E=0
}
/*-------------初始化LCD屏-------------*/
void Lcd_Init()
{ BitWrPortI(PBDR, &PBDRShadow, 0, 7); //RET=0,复位
Delay(100);
BitWrPortI(PBDR, &PBDRShadow, 1, 7); //RET=1
Delay(100);
WrPortI(PEDDR,&PEDDRShadow,PEDDRShadow|0xa0); //PE5, PE7为输出
BitWrPortI(PEDR,&PEDRShadow,1,5); //CS1=1
BitWrPortI(PEDR,&PEDRShadow,1,7); //CS2=1
Delay(100);
Write_Command(Disp_Off); //关显示
Write_Command(Page_Add+0);
Write_Command(Start_Line+0); //设置首行为起始行
Write_Command(Col_Add+0);
Write_Command(Disp_On); //开显示
}
/*-------------清屏--------------*/
void Clr_Screen()
{
char j,k;
WrPortI(PEDDR,&PEDDRShadow,PEDDRShadow|0xa0);
BitWrPortI(PEDR,&PEDRShadow,1,5); //CS1=1
BitWrPortI(PEDR,&PEDRShadow,1,7); //CS2=1
Write_Command(Page_Add+0);
Write_Command(Col_Add+0);
for(k=0;k<8;k++)
{
Write_Command(Page_Add+k);
for(j=0;j<64;j++)
Write_Data(0x00); //往每点送0x00h
}
}
/*--―-----指定位置显示汉字16*16---------*/
void Hz_Display(char pag, char col, char *hzk)
{
char j,i;
for(j=0;j<2;j++)
{
Write_Command(Page_Add+pag+j);
Write_Command(Col_Add+col);
for(i=0;i<16;i++)
{
Write_Data(hzk[16*j+i]);
}
}
}
/*------------信息显示--------------*/
void Msg(void)
{ //在第三、四行的左半屏显示"显",右半屏显示"示"
Clr_Screen();
WrPortI(PEDDR,&PEDDRShadow,PEDDRShadow|0xa0);
BitWrPortI(PEDR,&PEDRShadow,1,5); //CS1=1
BitWrPortI(PEDR,&PEDRShadow,0,7); //CS2=0
Hz_Display(3,48,xian);
Delay(2000);
WrPortI(PEDDR,&PEDDRShadow,PEDDRShadow|0xa0);
BitWrPortI(PEDR,&PEDRShadow,0,5);//CS1=0
BitWrPortI(PEDR,&PEDRShadow,1,7);//CS2=1
Hz_Display(3,0,shi);
Delay(2000);
}
液晶模块M12864-7A7是128 64点阵,每个汉字是16 16点阵,所以每行可以显示8个汉字,一屏可以显示4行,因而整屏最多显示32个汉字。
函数中的参数pag和col表示页地址(X地址)和Y地址,*hzk为指向需显示汉字点阵的指针。其中0<=pag<=7,col为0、16、32或48中的任一个值;由pag和col便可确定待显示汉字的位置。由表1可以知道页地址(X地址)的起始值为0xb8(程序中已定义为Page_Add),同时显示一个汉字要跨越两页,所以页地址的计算公式为:Page_Add+pag+j,0<=j<=1;而Y地址的开始值为0x40(程序中已定义为Col_Add),显示每个汉字要16列,因此计算Y地址的公式为:Col_Add+col。Y地址计算器具有自动加一功能,在每次读/写数据后他将自动加一,所以在连续进行读/写数据时,Y地址计数器不必每次都设置一次。
程序开始必须先饔肔CD初始化子程序,接着清屏,再视待显示的汉字是显示在左屏还是右屏来将液晶开为左屏或右屏显示,然后将数据送给液晶显示,直到32个字节的汉字完全显示完;多个汉字的显示同理进行操作。
对于多信息的显示可以将void Msg(void)改为void Msg(flag),既通过flag的不同值来标识不同的待显示信息,然后在实际使用中通过调用void
Msg(flag)即可实现。
结束语
液晶模块M12864-7A7与RabbitCore RCM2200模块的连接采用间接控制方式的特点是电路简单,控制时序由软件实现,可以实现高速MCU与液晶显示模块的接口。而采用Dynamic
C可以很方便的实现汇编语言要用较复杂的逻辑才能实现液晶模块的显示功能,而且可以减少开发和调试的时间。
|