📄 lcd12864.c
字号:
/***************************************************************************
12864液晶模块(ST7920控制器) Keil C51 并行口驱动程序
s_yqzhan@stu.edu.cn
OFourME@163.com 2007-9-29
/**************************************************************************/
#define FILE_IN_LCD1286
#include"LCD12864.h"
// #define NOP
/* 通过define NOP 决定是否在程序中插入nop指令
** 因为LCD可能对电平保持时间有一定的要求 */
/**************************************************************************/
#ifdef NOP
#include<intrins.h>
#endif
/*////////////////////////////////////////////////////////////////////////*/
/* 初始化12864液晶模块 */
void init_LCD(void)
{
RST = 0;
delay(50);
RST = 1;
#ifdef NOP
_nop_();
#endif
PSB = 1;
send_i(ext8);
send_i(bas8);
send_i(clr);
send_i(cursor_1);
send_i(texton);
}
/*////////////////////////////////////////////////////////////////////////*/
/* 等待,直到12864液晶模块处于就绪状态 */
void chk_busy(void)
{
BF = 1;
DI = 0;
RW = 1;
E = 1;
while(BF);
E = 0;
}
/*////////////////////////////////////////////////////////////////////////*/
/* 向12864液晶模块传输指令 */
void send_i(cmd12864 instrution)
{
chk_busy();
DI = 0;
RW = 0;
DB = instrution;
E = 1;
#ifdef NOP
_nop_();
_nop_();
#endif
E = 0;
}
/*////////////////////////////////////////////////////////////////////////*/
/* 向12864液晶模块传输数据 */
void send_d(int8u dt)
{
chk_busy();
DI = 1;
RW = 0;
DB = dt;
E = 1;
#ifdef NOP
_nop_();
_nop_();
#endif
E = 0;
}
/*////////////////////////////////////////////////////////////////////////*/
/* 从12864液晶模块读取数据 */
int8u read_d()
{
int8u dt;
chk_busy();
DI = 1;
RW = 1;
E = 1;
#ifdef NOP
_nop_();
#endif
dt = DB;
E = 0;
return dt;
}
/*////////////////////////////////////////////////////////////////////////*/
/* 从12864液晶模块读取指令、状态 */
int8u read_i()
{
int8u dt;
chk_busy();
DI = 0;
RW = 1;
E = 1;
#ifdef NOP
_nop_();
#endif
dt = DB;
E = 0;
return dt;
}
/*////////////////////////////////////////////////////////////////////////*/
/* 设置文本输出位置;x取值范围:0~7;y取值范围:0~3 */
void gotoxy(int8u x, int8u y)
{
switch(y)
{
case 0: send_i(0x80+x);break;
case 1: send_i(0x90+x);break;
case 2: send_i(0x88+x);break;
case 3: send_i(0x98+x);break;
}
}
/*////////////////////////////////////////////////////////////////////////*/
/* 设置图形模式输出位置;x取值范围(byte):0~7,单位为16位/2个字节,共128位;
y取值范围(bit):0~63
*/
void setxy(int8u x, int8u y)
{
send_i(ext8);
if( y & 0xe0 ) /* y>=32 */
{
send_i(gdbas+y-32);
send_i(page1+x);
}
else
{
send_i(gdbas+y);
send_i(page0+x);
}
send_i(bas8);
}
/*////////////////////////////////////////////////////////////////////////*/
/* 屏幕闪烁 */
void flash()
{
send_i(textoff); /* 关闭显示 */
delay(250);
send_i(texton); /* 开显示,关光标,不闪烁 */
delay(250);
send_i(textoff);
delay(250);
send_i(texton);
delay(250);
send_i(textoff);
delay(250);
send_i(texton);
}
/*////////////////////////////////////////////////////////////////////////*/
/* 清屏 */
void clrddram()
{
send_i(clr);
send_i(ext8);
send_i(bas8);
}
/*////////////////////////////////////////////////////////////////////////*/
/* 连续向LCD发送string指向的num个数据 */
/* 注意其和LCD_putsram的区别,TAB*指向的是rom空间,而int8u*指向的是ram空间。
失之毫厘,谬以千里,这个错误浪费了我近2天的时间,编译器在串行口仿真方面
的bug是其中一个原因。 当然的,如果用send_d()传送单个字节则没有这个问题。
*/
void LCD_puts(TAB* string, int8u num)
{
while(num--)
{
send_d(*string++);
}
}
void LCD_putsram(int8u* string, int8u num)
{
while(num--)
{
send_d(*string++);
}
}
/*////////////////////////////////////////////////////////////////////////*/
/* 全屏显示图形子程序 */
void pho_disp(BMP12864* tab)
{
int8u i, j, k, lcd_x, lcd_y;
lcd_x = 0x80;
for(i=3 ; --i; )
{
for(j=33, lcd_y=0x80; --j; lcd_y++)
{
send_i(ext8);
send_i(lcd_y);
send_i(lcd_x);
send_i(bas8);
for(k=17; --k; )
send_d(*(tab++));
}
lcd_x = 0x88;
}
send_i(grapon);
send_i(bas8);
}
/*////////////////////////////////////////////////////////////////////////*/
/* 显示点阵子程序,以lcd_data填充图形显示空间(GDRAM) */
void lat_disp(int8u lcd_data)
{
int8u i, j, k;
int8u lcd_x, lcd_y;
lcd_x=0x80;
i=2;
do
{ j=32; lcd_y=0x80;
do
{ send_i(ext8);
send_i(lcd_y);
send_i(lcd_x);
send_i(bas8);
k=16;
do
{ send_d(lcd_data);
}while(k--);
lcd_y++;
}while(--j);
lcd_x = 0x88;
}while(--i);
send_i(grapon);
send_i(bas8);
}
/*////////////////////////////////////////////////////////////////////////*/
/* 造字功能,最多自定义4的字,word的范围为0~3 */
void setcgram(int8u word, BMP1616* map)
{
int i;
send_i(cgbas+16*word);
for(i=0; i<32; i++)
send_d( *map++ );
}
/*////////////////////////////////////////////////////////////////////////*/
/* 清空点阵区 */
void clrgdram()
{
lat_disp(0);
}
/*////////////////////////////////////////////////////////////////////////*/
/* x代表要输出的目标行地址,其取值范围是0~ 7,单位是2个字节,即16位 */
/* y代表要输出的目标列地址,其取值范围是0~63,单位是1位 */
/* l代表图形文件的长度,单位是2个字节,即16位 */
/* w代表图形文件的宽度,单位是1位 */
/* 如果要使一幅32*7的图形在屏幕的左上角坐标为(16,5),
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -