|
//******************************************************************************
// 用于河北北方学院宣化教学部2005级单片机课程实验的
// 128x64点阵带汉字库串行接口液晶显示器C51驱动代码
//
// 代码沿革
// 创建: 2015年4月1日,
// 修改: 2015年4月4日,代码优化
// 2015年4月9日,注释
// 2015年4月13日,修改一处错误,LCD_Write(...)函数中有一处需要加一点延时
// 版权声明
// 1.版权拥有者是河北北方学院宣化教学部2005级单片机课程全体学生及该课程任课
// 教师.
// 2.任何团体或个人均可无条件使用本代码, 但版权拥有者不对由此引起的任何直接
// 或间接后果负担任何法律责任
// 3.一旦部分或全部使用本代码,则必须在源程序文档中无条件包含本版权声明
//******************************************************************************
#include "LCD.h"
#include "reg52.h"
//******************************************************************************
// LCD复位函数:LCD_Reset(void)
//******************************************************************************
void LCD_Reset(void)
{
uint ns=1000;
LCD_CS = 1;
LCD_CLK = 1;
LCD_RST = 0;
while(ns--);
LCD_RST = 1; ns=1000,while(ns--);
LCD_CS = 1; }
//******************************************************************************
// LCD写字节函数:LCD_Write(char inst, uchar x)
// 入口参数 inst=1/0: 命令/数据标志
// x : 命令/数据字节
//******************************************************************************
void LCD_Write(char inst, uchar x)
{
uchar i;
long int q;
if(!inst) q = 0x00fa0000; //数据:0000 0000 1111 1010 0000 0000 0000 0000
else q = 0x00f80000; //命令:0000 0000 1111 1000 0000 0000 0000 0000
q += (((x)&0xf0)<<8) + ((x<<4)&0xf0);//0000 0000 1111 10?0 hofx 0000 lofx 0000
q <<= 8; //1111 10?0 hofx 0000 lofx 0000 0000 0000
LCD_CS = 1; //选中LCD模块
for(i=0;i<24;i++) //串行传送24个二进制位
{ //从最高位开始传送
if(q & 0x80000000) LCD_SID = 1; //最高位为1时
else LCD_SID = 0; //最高位为0时
LCD_CLK = 0; //拉低CLK引脚,准备产生上升沿
LCD_CLK = 1; //拉高CLK引脚,产生一个上升沿,最高位被传送到LCD模块中
LCD_CLK = 1; //延长CLK高电平持续时间,不这样搞一下,就不行,大家注意了!
LCD_CLK = 1; //进一步延长CLK高电平持续时间,更保险了
q <<= 1; //左移一位,准备下一个待传送的位 }
LCD_CS = 0; //撤消LCD模块选中,防止干扰
}
//******************************************************************************
// LCD清除屏幕函数:ClearScreen(void)
//******************************************************************************
void ClearScreen(void)
{
LCD_Write(1, 0x01);
}
//******************************************************************************
// LCD打开显示函数:DisplayOn(void)
//******************************************************************************
void DisplayOn(void)
{
LCD_Write(1, 0x0c);
}
//******************************************************************************
// LCD字符串显示函数:Disp_Str(uchar x, uchar y, char *str)
// 入口参数 x: 字符串起始显示位置的x坐标
// y: 字符串起始显示位置的y坐标
// str: 指向待显示字符串的字符指针,字符串以'\0'结尾
//
// 关于行定义的特别说明:
// 按照数据手册介绍,本LCD模块的行由上到下依次为0,1,2,3行,但对应的行显示缓冲区地
// 址不是按行序排列的,其中
// 0行的显示缓冲区为:80H~87H
// 2行的显示缓冲区为:88H~8FH
// 1行的显示缓冲区为:90H~87H
// 3行的显示缓冲区为:98H~9FH
// 从视觉观看的角度说, 自上而下的行顺序依次为0,1,2,3行
// 从显示缓冲区地址连续的角度说,自上而下的行顺序依次为0,2,1,3行
// 考虑到显示字符串的长度是不定的,可能出现换行,程序中对此必须加以考虑调整
//
// 关于显示起始位置的说明:汉字显示时, 显示位置x坐标为0~7,显示西文字符时显示位置
// x坐标也是0~7,但每个显示位置可以显示两个西文字符,当中西文混合显示时, 注意西文
// 子串应包含偶数个西文字符.
//******************************************************************************
void Disp_Str(uchar x, uchar y, char *str)
{
uchar addr, i = 0;
if(x>7) x = 7;
if(y>3) y = 3;
switch(y) //根据x,y坐标确定显示缓冲区地址
{
case 0: addr = 0x80 + x; break;
case 1: addr = 0x90 + x; break;
case 2: addr = 0x88 + x; break;
case 3: addr = 0x98 + x; break;
}
LCD_Write(1, addr); //设置DDRAM地址
while(*str)
{ //下一行:从设置好的DDRAM地址开始写字符并准备好指向下一个字符的指针
LCD_Write(0, *str++);
i++;
if(i==2)
{
i = 0;
addr++; //每写俩字节DDRAM地址会自动增量,跟踪DDRAM的地址变化,以便换行调整
if( (addr&0x07) == 0 ) //当addr=88H,90H,98H,a0H时,说明DRAM地址需要重新指定
{
switch(addr)
{
case 0x88: addr = 0x90; break;
case 0x98: addr = 0x88; break;
case 0x90: addr = 0x98; break;
case 0xa0: addr = 0x80; break;
}
LCD_Write(1, addr); //设置被重新指定了的DDRAM地址
}
}
}
}
//******************************************************************************
// LCD十进制整数显示函数:Disp_Digital_Str(uchar x, uchar y, uint val,uchar len)
// 入口参数 x: 显示位置x坐标
// y: 显示位置y坐标
// val: 待显示的整数
// len: 显示位数
//******************************************************************************
void Disp_Digital_Str(uchar x, uchar y, uint val, uchar len)
{
char i, temp[11];
if( len > 10 ) len = 10;
if(len == 0) len = 1;
temp[10] = 0;
for(i=0; i<10; i++)
{
temp[9-i] = (val%10) + '0';
val /= 10;
}
Disp_Str(x, y, &temp[10-len]);
}
//******************************************************************************
// LCD十进制小数显示函数:
// Disp_Digital_Str_Dec(uchar x, uchar y, uint val, uchar len, uchar dotpos)
// 入口参数 x: 显示位置x坐标
// y: 显示位置y坐标
// val: 待显示的数
// len: 显示位数,包括小数点
// dotpos: 小数点位置
//******************************************************************************
void Disp_Digital_Str_Dec(uchar x, uchar y, uint val, uchar len, uchar dotpos)
{
char i, temp[12];
if(len > 10) len = 10;
if(len < 1) len = 1;
if(dotpos > (len-1)) dotpos = len-1;
temp[11] = 0;
for(i=0; i<11; i++)
{
if(i == dotpos) temp[10-i] ='.'; else
{
if(i < dotpos) temp[10-i] = (val%10) + '0'; else
temp[10-i] = (val%10) + '0';
val /= 10;
}
}
Disp_Str(x, y, &temp[10-len]);
}
//******************************************************************************
// LCD十六进制长整数显示函数:Disp_Hex_StrL(uchar x,uchar y, ulong val,uchar len)
// 入口参数 x: 显示位置x坐标
// y: 显示位置y坐标
// val: 待显示的数
// len: 显示位数
//******************************************************************************
void Disp_Hex_StrL(uchar x, uchar y, ulong val, uchar len)
{
char i, temp[9];
if(len > 8) len = 8;
if(len == 0) len = 1;
temp[len] = 0;
for(i=0; i<len; i++)
{
temp[len-1-i] = (val&0x0f);
if( (temp[len-1-i]) < 0x0a ) temp[len-1-i] += 0x30;
else temp[len-1-i] += 0x37;
val >>= 4;
}
Disp_Str(x, y, temp);
}
//******************************************************************************
// LCD十六进制整数显示函数:Disp_Hex_StrI(uchar x, uchar y, uint val, uchar len)
// 入口参数 x: 显示位置x坐标
// y: 显示位置y坐标
// val: 待显示的数
// len: 显示位数
//******************************************************************************
void Disp_Hex_StrI(uchar x, uchar y, uint val, uchar len)
{
char i, temp[5];
if(len > 4) len = 4;
if(len == 0) len = 1;
temp[len] = 0;
for(i=0; i<4; i++)
{
temp[len-1-i] = (val&0x0f);
val >>= 4;
if( (temp[len-1-i]) < 0x0a ) temp[len-1-i] += 0x30;
else temp[len-1-i] += 0x37;
}
Disp_Str(x, y, temp);
}
//******************************************************************************
// LCD十六进制短整数显示函数:Disp_Hex_StrC(uchar x,uchar y, uint val,uchar len)
// 入口参数 x: 显示位置x坐标
// y: 显示位置y坐标
// val: 待显示的数
// len: 显示位数
//******************************************************************************
void Disp_Hex_StrC(uchar x, uchar y, uchar val, uchar len)
{
char i, temp[3];
if(len > 2) len = 2;
if(len == 0) len = 1;
temp[2] = 0;
for(i=0; i<2; i++)
{
temp[len-1-i] = (val&0x0f);
val >>= 4;
if( (temp[len-1-i]) < 0x0a ) temp[len-1-i] += 0x30;
else temp[len-1-i] += 0x37;
}
Disp_Str(x, y, temp);
}
//******************************************************************************
// 字符串中填十进制数函数:
// Fill_Dec_Str(char * str,int v,unsigned char len,unsigned char pos, char sig)
// 入口参数str: 原始字符串
// v: 待填的数
// len: 数的位数
// pos: 填的位置
// sig: 符号位0+/1-
//******************************************************************************
void Fill_Dec_Str(char * str,int v,unsigned char len,unsigned char pos,char sig)
{
char i;
int x = 1;
if(sig)
{
if(v>=0) str[pos]='+';
else { str[pos]='-'; v = -v;}
pos++; len--;
}
for(i=1; i<len; i++)
x = (x<<3) + (x<<1);
for(i=pos; i<pos+len; i++)
{
str[ i]=v/x + '0';
v %= x;
x /= 10;
}
}
//******************************************************************************
// LCD初始化函数:LCD_Init()
//******************************************************************************
void LCD_Init()
{
LCD_Reset(); //LED显示器复位
DisplayOn();
} |
|