原创 128X64点阵 液晶显示器的驱动程序

2008-7-21 10:33 4158 4 5 分类: MCU/ 嵌入式

这里选用的是OCMJ4X8C.市面上128X64的液晶模块大多用的是相同内核.下面的程序希望给大家一点参考作用.


先介绍该模块的性能


//    LCD上文本区 64 字节     LCD上图形区 1024 字节
//    ┌──────────────┐    ┌──────────────┐
//   │        第一行            │   │          前半屏            │
//   │地址x:  0x80  ---  0x87     │    │   64 * 128 点阵 = 512 Byte │
//    ├──────────────┤    │每 32*128 点阵 为一行,共2行│
//    │          第二行            │    │行0: 首址y=0x80   前半屏首  │
//   │地址x  0x90  ---  0x97      │    │行1: 首址y=0x90   址x = 0x80│
//    ├──────────────┤    ├──────────────┤
//   │          第三行            │   │          后半屏            │
//   │地址x  0x88  ---  0x8f      │   │   64 * 128 点阵 = 512 Byte │
//    ├──────────────┤   │每 32*128 点阵 为一行,共2行│
//   │          第四行            │   │行2: 首址y=0x80   后半屏首  │
//   │地址x  0x90  ---  0x9f      │   │行3: 首址y=0x90   址x = 0x88│
//    └──────────────┘    └──────────────┘


//  文本区4行,每行可显示8个汉字,或16个字符。文本区的                
//  座标位,即文本区的地址x值,如上图所示,或数组TextLine[][8]。


//  图形区分为上下两部份,即上半屏和下半屏。每个半屏的点阵 = 64 * 128,即
//  64行,每行16字节128个bit位。y 座标上下半屏相同都是: 0x80 - 0x9f 共32行。
//  每行行首的x 座标上半屏是 0x80,而下半屏是 0x88。
//  行内的16字节是地址是由操作自动+1,末位加到15,再加又回 0。


 


下面是底层驱动程序:


// ㈠ ************* 端口设置 *************  


extern void   _nop_ (void);
#define LCD ((unsigned char volatile xdata *) 0xf010) // 液晶显示器首地址


#define RS  0   // 寄存器选择选择口,=0 指令寄存器,=1 数据寄存器
#define RW  1   // 读写操作控制口,=0 写操作,=1 读操作


#define RST  2   // 液晶显示器复位口,低电平有效
#define BK     3   // 液晶显示器背光口
#define COMM 6   // 液晶显示器命令口
#define DATA 6   // 液晶显示器数据口
#define EN  7   // 液晶显示器使能口,高电平有效
#define STATE 8   // 液晶显示器状态口


 


// ㈡ ************* 底层驱动程序 *************


/****************************************
  测试液晶是否忙  LCD_Busy()
****************************************/
void LCD_Busy(void)

   LCD[DATA]=0xff;    // 数据口先送 0xff
   LCD[RS]=0;     // 指令
   LCD[RW]=1;     // 读出忙标志(BF)及地址记数器(AC)
   LCD[EN]=1;     // 使能
   while(LCD[STATE] & 0x80); // 最高位为1则忙,再读
   LCD[EN]=0;
}


 


/***************************************
 送指令或数据  LCD_cmd()
  参数 md 类别(0/1),md=0 命令 md="1" 数据
    dt 命令或数据的值
****************************************/
void LCD_cmd(char md,char dt)
{
   LCD_Busy();    // 测试液晶是否忙
 if(md) LCD[RS]=1;  // 判断是数据还是命令
   else   LCD[RS]=0;
 LCD[RW]=0;    // 写
   LCD[COMM]=dt;   // 送数据或命令
   LCD[EN]=1;     // 使能
  _nop_();
 //_nop_();
   LCD[EN]=0;
}


/****************************************
  从液晶读数据 LCD_Read()
 读一字节数据,需读2次。第一次读为空操作 
****************************************/
char LCD_Read(void)
{   LCD_Busy();   // 测试液晶是否忙   
   LCD[RS]=1;   // 数据
   LCD[RW]=1;   // 读
    LCD[EN]=1;   // 使能
    _nop_(); 
 return LCD[DATA]; // 读数据 
 //LCD[EN]=0;   
}


/****************************************
 液晶背光控制  LCD_Back(md)
 md=0xff 点亮背光,md=0 关背光 
****************************************/
void LCD_Back(unsigned char md)
{
   LCD[BK] = md;
}



// ㈢ ************* 显示基本函数 *************


code const unsigned char TextLine[][8]=  // TS7920 128x64 文本显示行列地址
 {{0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87},  //  第一行
  {0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97},  // 第二行
  {0x88,0x89,0x8a,0x8b,0x8c,0x8d,0x8e,0x8f},  // 第三行
 {0x98,0x99,0x9a,0x9b,0x9c,0x9d,0x9e,0x9f}};  // 第四行



/****************************************
  液晶显示器初始化 LCD_init()
****************************************/
void LCD_init(void)
{
   LCD[BK]=0;
 LCD[RST]=1;
 LCD_cmd(0,0x34);  // 关闭图形显示 * 
   LCD_cmd(0,0x30);  // 基本指令动作  
   LCD_cmd(0,0x01);  // 清屏,地址指针指向00H
   LCD_cmd(0,0x06);    // 光标的移动方向
   LCD_cmd(0,0x0c);    // 开显示,关光标
 ClearGraph();   // 清图形区
 ClearText(4);   // 清文本区
}


/****************************************
 清图形区  ClearGraph()
****************************************/
void ClearGraph(void)
{   xdata char i,j,k,x;
   
 x=0x80;       // 图型上半区开始位置
   for(k=0;k<2;k++)
    { for(j=0;j<32;j++)
     {  LCD_cmd(0,0x34);   // 扩充指令,关图形显示
       LCD_cmd(0,0x80+j);  // 确定垂值座标
          LCD_cmd(0,x);   // 确定水平座标
       LCD_cmd(0,0x30);   // 基本指令动作 
          for(i=0;i<16;i++)     
     LCD_cmd(1,0);   // 送数据 0 
     }
    x="0x88";      // 图型下半区开始位置
     }
 LCD_cmd(0,0x36);    // 扩充指令集动作且开图形显示 
}


/****************************************
  清文本区  ClearText(row)
  参数 row 行号(0-4),若 row="4" 清屏   
****************************************/
void ClearText(char row)
{   xdata char k,i=0;  
 LCD_cmd(0,0x30);     // 基本指令动作
 LCD_cmd(0,0x0c);       // 开显示,关光标
 if (row>4) return;
 if (row==4)
   for (k=0;k<4;k++,i=0)    // 清四行  
    {LCD_cmd(0,TextLine[k][0]);  // 送出行地址 
    while (i++<16) LCD_cmd(1,0x20);
       }  
 else
     {  LCD_cmd(0,TextLine[row][0]);    // 送出行地址 
     while (i++<16) LCD_cmd(1,0x20);
     }       
}



/****************************************
 显示一屏汉字或字符 DisplayScreen(*p)
参数: *p 待显字符串指针
说明:  数组第2行和第3行显示时将被对调
****************************************/
void DisplayScreen(char *p)
{   xdata char k,i=0;   
 LCD_cmd(0,0x30);     // 基本指令动作
    LCD_cmd(0,0x0c);       // 开显示,关光标   
    for (k=0;k<4;k++,i=0)     {
       LCD_cmd(0,TextLine[k][0]);  // 送出行地址      
  while (*p && i++<16)      
      LCD_cmd(1,*p++);
  if (!(*p)) break;
     }
}


/****************************************
 显示一行字符串 DisplayRow(row,*p)
 参数 row 行号(0-3)
   *p 待显字符串指针
****************************************/
void DisplayRow(char row,char *P)
{   char i="0"; 
 
 if (row>3) return;    
 LCD_cmd(0,0x30);     // 基本指令动作
    LCD_cmd(0,0x0c);       // 开显示,关光标 *
   LCD_cmd(0,TextLine[row][0]);  // 送出行地址 
 while (*P && i++<16)
    LCD_cmd(1,*P++);
       
}


结束.

PARTNER CONTENT

文章评论1条评论)

登录后参与讨论

用户1079511 2008-7-22 08:10

你这块屏用的ST7920控制器,12864点阵屏常用的两钟控制器是KS0108(不带字库)和ST7920(带字库)。
相关推荐阅读
用户151500 2008-07-17 11:15
51系统中分页技术的应用
大家都知道,51系统最大的寻址空间是64K. 但我们可能有时候会碰到要求更大的空间内的寻址,这时就需要用到分页技术.<?xml:namespace prefix = o ns = "urn:sc...
用户151500 2008-07-14 10:08
通讯状态机
在最近做的一个LED显示的项目中,所有的控制,数据和测试命令全部是由上位机用通讯方式下发的.由于之前对通讯问题没有很好重视,所以在这个项目中,认真的解决了这个问题.通讯报文的处理方式很多.状态机的方式...
用户151500 2008-07-11 11:02
C语言中指针的学习
指针是C语言中最诡异的数据类型.复杂的指针应用就更让人头晕.下面给出一个平时积累的一些东西.供有兴趣的朋友看看.其实大多数应用不会这么复杂.仅供学习.①    下面是字符串指针的定义例子。(有些是要有...
我要评论
1
4
关闭 站长推荐上一条 /1 下一条