📄 lcd.c
字号:
#include "GLOBAL.H"
/* Define the register command code */
#define Disp_On 0x3f /*显示开*/
#define Disp_Off 0x3e /*显示关*/
#define Col_Add 0x40 /*列地址设置指令*/
#define Page_Add 0xb8 /*行地址设置指令*/
#define Start_Line 0xc0 /*显示起始行*/
#define LCD_BUS PDR2 //MCU P2<------> LCM 数据寄存器
#define LCD_BUS_DIR DDR2 //MCU P2<------> LCM 方向寄存器
#define MCS PDR5_P51 //Master chip enable
#define SCS PDR5_P52 //Slave chip enable
#define Enable PDR3_P37 //6800 mode Enable single
#define DI PDR5_P56 //Data or Instrument Select RS
#define RW PDR5_P57 //Write or Read
uchar cursor_x,cursor_y,cursor_mode;
uchar const hex2asc[] = {'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};
uchar const hex2asc1[] = {' ','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};
uchar scr[16][4];
/*------------------延时子程序-----------------------------*/
void delay(uint t)
{
uint i,j;
for(i=0; i<t; i++)
{
for(j=0; j<10; j++);
}
}
/*************************************************
* 名称:Read_Status
* 功能:读lcd 的状态,在操作之前要查询busy状态以确定是否可以操作
* 输出:
* 返回:状态1: 内部在工作;0: 正常状态
**************************************************/
/*uchar Read_Status()
{
uchar status;
LCD_BUS_DIR = 0x00;
DI=0;
RW=1;
status = LCD_BUS;
return (status & 0x80);
}*/
/*------------------写命令到LCD------------------------------*/
void LCD_CMD(uchar cmdcode)
{
uchar i;
LCD_BUS_DIR = 0xff;
DI=0;
RW=0;
LCD_BUS=cmdcode;
Enable=1;
for(i = 0;i < 13;i++)
{
__wait_nop();
}
Enable=0;
}
/*-------------------写数据到LCD----------------------------*/
void WRITE_LCD_DAT(uchar Dispdata)
{
uchar i ;
LCD_BUS_DIR = 0xff;
DI=1;
RW=0;
LCD_BUS=Dispdata;
Enable=1;
for(i = 0;i < 7;i++)
{
__wait_nop();
}
Enable=0;
}
/*-------------------读数据到LCD----------------------------*/
uchar READ_LCD_DAT()
{
uchar i;
uchar lcd_data;
LCD_BUS_DIR = 0x00;
DI=1;
RW=1;
Enable=1;
for (i=0;i< 5;i++) /*320ns 16*/
__wait_nop(); /*20ns*/
lcd_data = LCD_BUS; /*高电平期间读数据*/
Enable=0;
return lcd_data;
}
/*------------------设置光标---------------*/
void set_cursor(uchar x,uchar y)
{
cursor_x = x;
cursor_y = y;
}
/*------------------清除内存---------------*/
void Clr_Scr()
{
uchar j,k;
MCS = 1;
SCS = 1;
LCD_CMD(Page_Add+0);
LCD_CMD(Col_Add+0);
for(k=0; k<8; k++)
{
LCD_CMD(Page_Add+k);
for(j=0; j<64; j++)
{
WRITE_LCD_DAT(0x00);
}
}
MCS = 0;
SCS = 0;
for (j = 0; j < 16; j++)
{
for (k = 0; k < 4; k++)
{
scr[j][k] = 0x20;
}
}
}
/*************************************************
* 名称:putpoint
* 功能:输出点
* 输入:
x 横坐标 0 - 127
y 纵坐标 0 - 63
* 输出:
* 返回:无
**************************************************/
void putpoint(uchar x,uchar y)
{
uchar z0 ;
uchar dataold;
y = y & 0x3f; /*保证y在0-63之内*/
z0 = ( 1 << (y & 7) ); /*对应点点亮,1左移多少位*/
y = y >> 3; /*每页对应一个字节的数据,共8页*/
if (x < 64)
{
MCS = 1;
SCS = 0;
}
else
{
x &= 0x3f; /*第二块液晶*/
MCS = 0;
SCS = 1;
}
LCD_CMD(Page_Add + y); /*先读一下数据,防止原来输出的被覆盖*/
LCD_CMD(Col_Add + 63 - x);
READ_LCD_DAT(); /*空读操作,协议要求*/
dataold = READ_LCD_DAT();
z0 = ( z0 | dataold );
LCD_CMD(Page_Add + y);
LCD_CMD(Col_Add + 63 - x);
WRITE_LCD_DAT(z0);
MCS = 0;
SCS = 0;
}
/*---------------------指定位置显示汉字16*16-----------------------*/
/* x = 0 - 127: 代表一个像素增量; y = 0-7 代表 8 个像素增量 */
void puthz16(uchar x,uchar y, uint index)
{
uchar i=0,j=0,k=0,x0,y0;
uchar *p;
uchar const offset[] = {15,7,31,23};
uchar const xoffset[] = {15,7,15,7};
x <<= 3;
for (i = 0; i < 4; i++)
{
x0 = x + xoffset[i];
if (x0 < 64)
{
MCS = 1;
SCS = 0;
}
else
{
x0 &= 0x3f;
MCS = 0;
SCS = 1;
}
if (i < 2)
{
LCD_CMD(Page_Add+7-y);
}
else
{
LCD_CMD(Page_Add+6-y);
}
LCD_CMD(Col_Add+63-x0);
p = (uchar *)(hzk[index] + offset[i]);
for(j = 0; j < 8; j++)
{
WRITE_LCD_DAT(*p);
p--;
}
}
MCS = 0;
SCS = 0;
}
void putasc16(uint x,uint y,uchar ch)
{
uchar i=0,j=0,k=0;
uchar *p;
uchar x0;
x0 = x << 3;
if (x0 < 64)
{
MCS = 1;
SCS = 0;
}
else
{
x0 &= 0x3f;
MCS = 0;
SCS = 1;
}
LCD_CMD(Page_Add+7-y);
LCD_CMD(Col_Add+56-x0);
p = (uchar *)(ascii[ch] + 7);
if ((cursor_x == x) && (cursor_y == y) && cursor_mode)
{
for(j = 0; j < 8; j++)
{
WRITE_LCD_DAT(~(*p));
p--;
}
}
else
{
for(j = 0; j < 8; j++)
{
WRITE_LCD_DAT(*p);
p--;
}
}
LCD_CMD(Page_Add+6-y);
LCD_CMD(Col_Add+56-x0);
p = (uchar *)(ascii[ch] + 15);
if ((cursor_x == x) && (cursor_y == y))
{
if (cursor_mode)
{
for(j = 0; j < 8; j++)
{
WRITE_LCD_DAT(~(*p));
p--;
}
}
else
{
for(j = 0; j < 8; j++)
{
WRITE_LCD_DAT(*p | 1);
p--;
}
}
}
else
{
for(j = 0; j < 8; j++)
{
WRITE_LCD_DAT(*p);
p--;
}
}
MCS = 0;
SCS = 0;
}
/*------------------初始化LCD屏--------------------------*/
void init_lcd()
{
MCS = 1;
SCS = 1;
delay(100);
LCD_CMD(Disp_Off);
LCD_CMD(Page_Add+0);
LCD_CMD(Start_Line+0);
LCD_CMD(Col_Add+0);
LCD_CMD(Disp_On);
MCS = 0;
SCS = 0;
Clr_Scr();
set_cursor(0xff,0xff);
}
/*************************************************
* 名称:gethzindex
* 功能:获得汉字的索引
* 输入:
buf 指向要查询索引的汉字
* 输出:
* 返回:索引值
**************************************************/
uint gethzindex(char *buf)
{
uint i=0, j=0, k=0;
k = strlen((char *)hzk_index)-2;
for(i=0,j=0; i < k; i += 2,j++)
{
if ( ((uchar)*buf == hzk_index[i]) && ((uchar)*(buf + 1) == hzk_index[i + 1]) )
{
return j;
}
}
return 0;
}
/*************************************************
* 名称:sprfi
* 功能:有符号数格式化输出
* 输入:
buf 输出指针
num 要输出的数值
dot 小数点的位置 例如1.00,则 dot = 2
len num的长度,例如: num = 128,则 len = 3
* 输出: buf
* 返回:无
**************************************************/
void sprfi(char *buf,uint num,uchar dot,uchar len)
{
uchar sign;
uchar i,j,k;
k = len;
if (dot == 0) buf[0] = ' ';
sign = 1;
if (num > 0x7fff)
{
k++;
sign = 0;
num = ~num + 1;
}
for (i = 1; i <= len;i++)
{
j = num % 10;
num = num / 10;
if ((i > dot + 1) && (num == 0)) buf[k] = hex2asc1[j];
else buf[k] = hex2asc[j];
k--;
if (i == dot)
{
buf[k] = '.';
k--;
}
}
if (sign == 0)
{
buf[k] = '-';
}
}
/*************************************************
* 名称:sprfu
* 功能:无符号数格式化输出
* 输入:
buf 输出指针
num 要输出的数值
dot 小数点的位置,例如1.00,则 dot = 2
len num的长度,例如: num = 128,则 len = 3
* 输出: buf
* 返回:无
**************************************************/
void sprfu(char *buf,ulong num,uchar dot,uchar len)
{
uchar i,j,k;
if (dot == 0) k = len - 1;
else k = len;
for (i = 1; i <= len; i++)
{
j = num % 10;
num = num / 10;
if ((i > dot + 1) && (num == 0)) buf[k] = hex2asc1[j];
else buf[k] = hex2asc[j];
k--;
if (i == dot)
{
buf[k] = '.';
k--;
}
}
}
/* 二进制数格式化输出
void sprfb(char *buf,uint num,uchar len)
{
uchar i,j,k;
k = len - 1;
for (i = 0; i < len; i++)
{
buf[k] = hex2asc[num & 1];
num >>= 1;
k--;
}
} */
/*************************************************
* 名称:sprfb
* 功能:二进制数格式化输出
* 输入:
buf 输出指针
num 要输出的二进制数
len num的长度,例如: num = 101,则 len = 3
* 输出: text
* 返回:无
**************************************************/
void sprfb(char *buf,uint num,uchar len)
{
uchar i,j,k;
k = 0;
for (i = 0; i < len; i++)
{
buf[k] = hex2asc[num & 1];
num >>= 1;
k++;
}
}
/*************************************************
* 名称:display_str
* 功能:字符串格式化输出
* 输入:
x 横坐标位置: 对应液晶长: 0-15
y 横坐标位置: 对应液晶宽: 0-6
text 要输出的字符串的指针
* 输出: text
* 返回:无
**************************************************/
void display_str(uint x,uint y,char *text)
{
char *p;
uint index,y0;
uchar code0,code1;
p = text;
y0 = y / 2;
while(*p)
{
code0 = *p;
code1 = *(p+1);
if((code0 >= 0xa0) && (code1 >= 0xa0)) // 汉字
{
if ((code0 != scr[x][y0]) || (code1 != scr[x+1][y0]))
{
index = gethzindex(p);
puthz16(x,y,index);
scr[x][y0] = code0;
scr[x+1][y0] = code1;
}
x += 2;
p += 2;
}
else // ASC 字库
{
if ((x == cursor_x) && (y == cursor_y)) // 光标位置要刷新
{
scr[x][y0] = 0;
}
if (code0 != scr[x][y0])
{
putasc16(x,y,code0);
if ((x == cursor_x) && (y == cursor_y)) // 光标位置要刷新
{
scr[x][y0] = 1;
}
else
{
scr[x][y0] = code0;
}
}
x += 1 ;
p++;
}
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -