经过几天的测试,驱动LCD5110显示屏的代码终于移植成功,下面是测试过程的图片:
这是显示的效果:
在移植过程中,字库文件的函数定义花费了不少时间。由于有些时间没有接触C51了,我一尝试用ARM的定义方式将字库数据存放到EEPROM中,反复用static和const来定义字库文件,编译总出错,提示数据太大。在沁恒技术人员的提示下,改为用code来定义,编译就顺利通过了。下面是LCD5110的驱动代码:
#include ".\Public\CH549.H"
#include ".\Public\DEBUG.H"
#include ".\mydrive\lcd_5110.h"
#include ".\mydrive\ascii5x8.h" //5x8ASCII字符集
#include ".\mydrive\charcode.h" //12x16(14)汉字子集
#include ".\mydrive\asciicode.h" //5x8(8)ASCII子集
/*********************************************
* 函数名称:Delay
* 函数功能:延时毫秒
* 入口参数:xms :毫秒数
* 出口参数:无
* 备注:
*********************************************/
void Delay(UINT8 xms)
{
UINT8 x,y;
for(x=xms;x>0;x--)
for(y=10;y>0;y--); //for(y=110;y>0;y--)
}
/*********************************************
* 函数名称:LCD_write_byte
* 函数功能:模拟SPI接口时序写数据/命令LCD
* 入口参数:data :写入的数据;
* dc :写数据1/命令0选择
* 出口参数:无
* 备注:管脚D/C(LCD_DC)用于选择写的是命令(D/C=0)还是数据(D/C=1)
*********************************************/
void LCD_write_byte(UINT8 dat,UINT8 dc)
{
UINT8 i;
LCD_CLK = 0; //先拉低时钟CLK
LCD_CE = 0; //选择5110
LCD_DC = dc; //dc=0数据,dc=1命令
for(i=0; i<8; i++) //发送8位
{
if (dat & 0x80){
LCD_DIN = 1;
}
else{
LCD_DIN = 0;
}
LCD_CLK = 1;
Delay(1);
dat = dat << 1; //移位,准备发送下一位
LCD_CLK = 0; //发送同步时钟
}
LCD_CE = 1; //关闭5110
}
/*********************************************
* 函数名称:LCD_set_XY
* 函数功能:设置LCD坐标函数
* 入口参数:X :0-83;
* Y :0-5
* 出口参数:无
* 备注:
*********************************************/
void LCD_set_XY(UINT8 X,UINT8 Y)
{
LCD_write_byte(0x40 | Y,0); //column?
LCD_write_byte(0x80 | X,0); //row?
}
/*********************************************
* 函数名称:LCD_clear
* 函数功能:5110清屏(用空白写满屏幕)
* 入口参数:无
* 出口参数:无
* 备注:、
*********************************************/
void LCD_clear(void)
{
UINT8 i,j;
LCD_set_XY(0,0); //定位左上角
for (i=0; i<6; i++)
{
for (j=0; j<84; j++)
{
LCD_write_byte(0x00,1);
}
}
}
/*********************************************
* 函数名称:LCD_init
* 函数功能:5110初始化
* 入口参数:无
* 出口参数:无
* 备注:接通电源后需要一个RES低电平脉冲复位,当VDD变为高电平之后
* 最多100ms,RST输入低电平(<0.3VDD)
*********************************************/
void LCD_init(void)
{
// LCD_Config(); //配置LCD连线
LCD_RST = 0; //复位LCD5110
Delay(2);
LCD_RST = 1;
LCD_CE = 0; //关闭LCD
Delay(2);
LCD_CE = 0; //关闭LCD
LCD_write_byte(0x21,0); //使用扩展LCD令设置LCD模式
LCD_write_byte(0xc8,0); //设置液晶偏置电压
LCD_write_byte(0x06,0); //温度校正(温度系数2)
LCD_write_byte(0x13,0); //1:48
LCD_write_byte(0x20,0); //使用基本命令,V=0,水平寻址
LCD_write_byte(0x0c,0); //设定显示模式,正常显示
LCD_clear(); //清屏
LCD_CE = 0; //关闭LCD
}
/*********************************************
* 函数名称:LCD_write_ASCII
* 函数功能:显示字符串5*7(8)
* 入口参数:x,y,cid :显示ASCII字符
* 出口参数:无 编号(行号)32~127
* 备注:ASCII码表的数组ASC_5[95][8]来寻址
*********************************************/
void LCD_write_ASCII(UINT8 X,UINT8 Y,UINT8 *stru)
{
UINT8 i;
// j = cid - 32;
LCD_set_XY(X,Y); //定位(左上角)
while (1)
{
for ( i=0; i<5; i++) //输出一个5*7字符
{
LCD_write_byte(ASC_5[*stru-32],1);
}
stru++;
LCD_write_byte(0x00,1); //插入空列
if(*stru == '\0') break; //在每个字符串的最后,会有一个'\0'
}
}
/*********************************************
* 函数名称:LCD_write_ASCII
* 函数功能:显示单个字符5*7(8)
* 入口参数:x,y,cid :显示ASCII字符
* 出口参数:无 编号(行号)32~127
* 备注:ASCII码表的数组ASC_5[95][8]来寻址
*********************************************/
void LCD_write_ASC_SIN(UINT8 X,UINT8 Y,UINT8 cid)
{
UINT8 i;
LCD_set_XY(X,Y); //定位(左上角)
for ( i=0; i<5; i++) //输出一个5*7字符
{
LCD_write_byte(ASC_5[cid-32],1);
}
}
/*********************************************
* 函数名称:LCD_write_ASC7x12
* 函数功能:显示自定义字符7*12(16)
* 入口参数:x,y,cid :显示的字符 0 1 2 3 4 5 6 7 8 9 = m s
* 出口参数:无 编号(行号)0,1,2,3,4,5,6,7,8,9,10,11,12
* 备注:ASCII码表的数组ASC_7[13][14]来寻址
*********************************************/
void LCD_write_ASC7x12(UINT8 X,UINT8 Y,UINT8 cid)
{
UINT8 i;
LCD_set_XY(X,Y); //定位{左上角)
for (i=0; i<7; i++) //显示字符的上半部分(7列)
{
LCD_write_byte(ASC_7[cid],1);
}
LCD_set_XY(X,Y+1); //显示字符的下半部分
for (i=7; i<14; i++)
{
LCD_write_byte(ASC_7[cid],1);
}
}
/*********************************************
* 函数名称:LCD_write_CHAR
* 函数功能:显示自定义字符12*14(16)
* 入口参数:x,y,cid :显示的字符 电子点焊机接间隔毫秒时
* 出口参数:无 编号(行号)0,1,2,3,4,5,6,7,8,9,10
* 备注:CHAR字库的数组CHAR_12[11][24]来寻址
***********************************************/
void LCD_write_char(UINT8 x,UINT8 y,UINT8 cid)
{
UINT8 i;
LCD_set_XY(x,y); //定位(左上角)
for (i=0; i<12; i++) //写字符的上半部分(12列)
{
LCD_write_byte(CHAR_12[cid],1);
}
LCD_set_XY(x,y+1); //写字符的下半部分
for (i=12; i<24; i++)
{
LCD_write_byte(CHAR_12[cid],1);
}
}
/*********************************************
* 函数名称:LCD_write_string
* 函数功能:显示汉字字符串
* 入口参数:x,y,*stru :显示的字符串
* 出口参数:无
* 备注:根据汉字内码从二维数组cid_12中找到字库中的行号,再逐个调用显示
***********************************************/
void LCD_write_string(UINT8 x,UINT8 y,UINT8 *stru)
{
UINT8 j,n;
while(1)
{
// for (j = 0; j < 38; j++) //查找汉字对应字库的行号
j = 0;
while(1)
{
n = 0; //查找失败,用首个字替代
if((stru[0] == cid_12[j][0]) && (stru[1] == cid_12[j][1]))
{
n = j; //找到行号,结束跳出
break;
}
j++;
if(*cid_12 == '\0') break;
}
LCD_write_char(x, y, n);
x += 12;
stru += 2;
if(*stru == '\0') break; //在每个字符串的最后,会有一个'\0'
LCD_write_byte(0x00,1); //插入空列
}
}
/*********************************************
* 函数名称:LCD_write_value
* 函数功能:显示变量字符5*7(8)或7*12(16)
* 入口参数:x,y,L,val :座标、长度、小数、前导零(1显示 0不显示)、变量
* 出口参数:无 编号(行号)
* 备注:ASCII码表的数组ASC_5[95][8]来寻址
*********************************************/
void LCD_write_value(UINT8 X,UINT8 Y,UINT8 L,UINT8 D,UINT8 Z,UINT16 val)
{
UINT8 i,j,f = 0; //列循环、字循环、显示标志
UINT16 t,cid; //当前余数、当前数字
UINT32 n; //当前倍数
t = val;
n = 1;
if(Z == 1)
f = 16; //空格=0,“0”=16
for (j = 0; j < L; j++)
n = n * 10;
LCD_set_XY(X,Y); //定位(左上角)
for (j = L; j > 0; j--) //字符循环开始
{
n = j < 2 ? 1: n / 10; //计算当前的倍数
cid = t / n; //当前位数字
t = t - (cid * n);
if ((cid > 0)|(j-1 == D)) //显示字符0
f = 16;
for ( i=0; i<5; i++) //写一个5*7字符
{
LCD_write_byte(ASC_5[cid + f],1);
}
if ( D > 0 & D == (j - 1))
{
for ( i=0; i<5; i++) //写小数点
{
LCD_write_byte(ASC_5[14],1);
}
}
else
if(j>1) LCD_write_byte(0x00,1);//插入空列
}
}