|
2#
楼主 |
发表于 2009-4-25 17:13:49
|
只看该作者
续1:用PICC写高质量的12864显示C代码
二:对LCD的低层操作。
对LCD操作有2种数据,一是控制指令,二是显示数据。
指 令 名 称
控制信号
控 制 代 码
RS
R/W
D7
D6
D5
D4
D3
D2
D1
D0
显示开关设置
0
0
0
0
1
1
1
1
1
D
显示起始行设置
0
0
1
1
L5
L4
L3
L2
L1
L0
页面地址设置
0
0
1
0
1
1
1
P2
P1
P0
列地址设置
0
0
0
1
C5
C4
C3
C2
C1
C0
读取状态字
0
1
BUSY
0
ON/OFF
RESET
0
0
0
0
写显示数据
1
0
数 据
读显示数据
1
1
数 据
并且在送数据之前要判断LCD是否处于忙状态。于是就先写判断LCD状态的函数:
void check_busy(){
CS1=1;CS2=1;
RS=0;RW=1; //按照上表,设定好读取LCD状态字的控制线。
do{
E=0;
E=1;
}while(Lcd_IO&0x80); //判断最高位状态,如果是1,则反复送E时续,直到LCD空闲
CS1=0;CS2=0;
E=0; //及时拉低E,使DB口处于高阻状态,提高可靠性
if(L_lcd)
CS1=1;
if(R_lcd)
CS2=1; //通过全局BIT变量L_Lcd\R_lcd传递LCD左右屏幕参数
SetLcd_IO=0; //使IO口处于输出状态,为向LCD写数据作准备。
}
后面当然就是向LCD写数据和指令的函数了:
void LCD_Write_Com(unsigned char val)
{
check_busy(); //检查LCD是否空闲
RS=0;RW=0; //根据上表设定控制脚,CS1、2在check_busy();里事先有设定
E=1;
Lcd_IO=val; //E时续下降沿输入数据
E=0;
SetLcd_IO=0xff; //写完数据,立即把IO口设定成高阻,提高可靠性。
}
void LCD_Write_Dat(unsigned char val)
{
check_busy();
RS=1;RW=0;
E=1;
Lcd_IO=val;
E=0;
SetLcd_IO=0xff;
}
续2:用PICC写高质量的12864显示C代码
四:LCD显示之前当然要对其清屏,避免出现色癍。
清屏幕就是对LCD内部DRAM全写0。
void LCD_Clr(void)
{
unsigned char i,j;
L_lcd=1,R_lcd=1; //用2个全局BIT变量传递左右屏幕,因为check_busy()函数里面有可能
//改变 CS1、CS2
// LCD_Write_Com(0x3e); //关闭LCD显示,因为清屏幕极快,不要这句也罢。
LCD_Write_Com(0xc0);
for(j=8;j>0;j--){
LCD_Write_Com(0xb8|j);
LCD_Write_Com(0x40);
for(i=64;i>0;i--){
LCD_Write_Dat(0x00); //对8个页面的DRAM全部送0
}
}
LCD_Write_Com(0x3f); //打开LCD显示
}
五:上面4个步骤就是LCD的低层操作了。下面就是显示字符的应用函数:
先要明白LCD的显示字符的原理,一般字符取磨都是按照8x8,8x16,16x16来的,分别适合小字体阿拉伯数字,大字体阿拉伯数字,汉字。
事先要把显示的字符取摸:
如:8x8的0-9,:
const char a[12][8]={
{0,62,65,65,62,0,0,0}, //0
{0,66,127,64,0,0,0,0}, //1
{0,98,81,73,70,0,0,0},
{0,34,73,73,54,0,0,0},
{0,56,38,127,32,0,0,0},
{0,79,73,73,49,0,0,0},
{0,62,73,73,50,0,0,0},
{0,3,113,9,7,0,0,0},
{0,54,73,73,54,0,0,0},
{0,38,73,73,62,0,0,0}, //9
{0,0,0,204,204,0,0,0}, //:
{0,0,0,0,0,0,0,0} //最后全0,是为了对某个位置的数字清0
};
显示8x8的函数:
void display8x8(uchar x,uchar y,const char *p){ //x表示屏幕的 x行(0-7),y表示屏幕的y列(0-15)
uchar i;
y<<=3;
L_lcd=1;R_lcd=0;
if(y&0x40){
L_lcd=0;R_lcd=1; //判断y,来选择左右屏幕
}
y&=0x3f;
LCD_Write_Com(0xb8|x);
LCD_Write_Com(0x40|y);
for(i=8;i>0;i--){
LCD_Write_Dat(*p++);
}
}
调用这个应用函数示例:
display8x8(0, 0, a[0 ]); //在屏幕0行0列显示字符0
display8x8(0, 15, a[9 ]); // 0行15列显示9
display8x8(7, 8, a[10 ]); //7行8列显示:号
下面分别是8x16,16x16的函数:
void display8x16(unsigned char x,unsigned char y,const char *p){
unsigned char i;
x<<=1;
y<<=3;
L_lcd=1;R_lcd=0;
if(y&0x40){
L_lcd=0;R_lcd=1;
}
y&=0x3f;
LCD_Write_Com(0xb8|x);
LCD_Write_Com(0x40|y);
for(i=8;i>0;i--){
LCD_Write_Dat(*p++);
}
LCD_Write_Com(0xb9|x);
LCD_Write_Com(0x40|y);
for(i=8;i>0;i--){
LCD_Write_Dat(*p++);
}
}
void display16x16(uchar x,uchar y,const char *p){
uchar i;
x<<=1;
y<<=4;
L_lcd=1;R_lcd=0;
if(y&0x40){
L_lcd=0;R_lcd=1;
}
y&=0x3f;
LCD_Write_Com(0xb8|x);
LCD_Write_Com(0x40|y);
for(i=16;i>0;i--){
LCD_Write_Dat(*p++);
}
LCD_Write_Com(0xb9|x);
LCD_Write_Com(0x40|y);
for(i=16;i>0;i--){
LCD_Write_Dat(*p++);
}
}
当然8x16和16x16的字符取摸要按照规定来,存放格式雷同上面的a二维数组。
注意,8x16函数只能显示4x16 个字符,16x16 只能显示4x8个字符,调用函数时候,x,y参数不能超过这个数值。
最后不要忘了在代码前加上全局BIT变量:
bit L_lcd,R_lcd;
此代码经过产品的长期考验,事实证明是非常可靠的。至于代码是否简洁,大家编译后就知道了。 |
|