📄 lcd.c~
字号:
#include <delay.h>
#include <ctype.h>
#include "lcd.h"
//#include "hz_db.h"
//#include "ascii_db.h"
/******************************************************************************************
note : (for ACM12864I)
XY地址计数器:
九位计数器,头三位为X地址(页地址),后六位为Y地址
地址X没有自动计数功能必须通过指令来设置 - DDRAM的页指针
地址Y有自动计数功能数据写入后指针自动加1 - DDRAM的Y地址指针
显示数据RAM(DDRAM):
存储图形显示数据,1 - 显示选择,0 - 显示非选择
DDRAM地址与显示位置对照表:
CS = 1 CS = 2
Y=0 Y=1 ... Y=6 Y=7 Y=0 Y=1 ... Y=6 Y=7
DB0 DB0 DB0 DB0 DB0 DB0 DB0 DB0
X=0 DB1 DB1 DB1 DB1 DB1 DB1 DB1 DB1
.....................
DB7 DB7 DB7 DB7 DB7 DB7 DB7 DB7
...
DB0 DB0 DB0 DB0 DB0 DB0 DB0 DB0
X=7 DB1 DB1 DB1 DB1 DB1 DB1 DB1 DB1
.....................
DB7 DB7 DB7 DB7 DB7 DB7 DB7 DB7
Z地址记数器:
显示行扫描同步,显示屏幕的起始行(0~64)
指令集:
格式:R/W,D/I,DB7~DB0
1.显示开关控制
00 0011-111x,x=1开,x=0关
2.设置显示起始行
00 11xx-xxxx,xxxxxx自动送入Z地址记数器 - 0xc0~0xff
3.设置页地址
00 1011-1xxx,复位后页地址为0 - 0xb8~0xbf
4.设置Y地址
00 01xx-xxxx,自动增量 - 0x40~0x7f
5.读状态(E信号此时为H状态)
10 B0DR-0000,B - 1:忙,0:空闲 D - 1:开显示,0:关显示 R - 1:初始化中,系统忙
6.写显示数据
01 xxxx-xxxx
7.读显示数据
11 xxxx-xxxx
硬件接口:
A15---E A14--- D/I A13---CS1 A12---CS2 A11---R/W
note : 1.ACM12864的坐标系统定义如下:
以平面直角坐标系的原点为圆心,逆时针旋转90度构成。从12864液晶平面的正面看,左上角
为坐标原点,纵轴为横坐标(X),横轴为纵坐标(Y),范围:X - 0~64,Y - 0~128。实际上,
X/8对应于页地址,Y/2对应于y地址。
2.从12864液晶平面的正面看,cs=1对应其右半部分平面,cs=2对应其左半部分平面
******************************************************************************************/
/******************************************************************************************
全局宏定义
******************************************************************************************/
#define TRUE 1
#define FALSE 0
/*
PC0 PC1 PC2 PC3 PC4 PC5 PC6 PC7
- - - R/W CS1 CS2 RS -
*/
#define LCD_DATA_WADDR *(unsigned char *) 0xf000 //1111 0000,数据写地址-cs12
#define LCD_DATA_WADDR1 *(unsigned char *) 0xd000 //1101 0000,数据写地址-cs1
#define LCD_DATA_RADDR1 *(unsigned char *) 0xd800 //1101 1000,数据读地址-cs1
#define LCD_DATA_WADDR2 *(unsigned char *) 0xe000 //1110 0000,数据写地址-cs2
#define LCD_DATA_RADDR2 *(unsigned char *) 0xe800 //1110 1000,数据读地址-cs2
#define LCD_INST_ADDR *(unsigned char *) 0xb000 //1011 0000,指令写地址-cs12
#define LCD_INST_ADDR1 *(unsigned char *) 0x9000 //1001 0000,指令写地址-cs1
#define LCD_INST_ADDR2 *(unsigned char *) 0xa000 //1010 0000,指令写地址-cs2
#define LCD_STATE_R_ADDR *(unsigned char *) 0xb800 //1011 1000,状态读地址-cs12
#define LCD_STATE_R_ADDR1 *(unsigned char *) 0x9800 //1001 1000,状态读地址-cs1
#define LCD_STATE_R_ADDR2 *(unsigned char *) 0xa800 //1010 1000,状态读地址-cs2
#define LCD_OFF_COM 0x3e //0011 1110,关显示
#define LCD_ON_COM 0x3f //0011 1111,开显示
#define LCD_D_S_LINE 0xc0 //1100 0000,显示起始行
#define LCD_SET_D_LINE_COM(x) LCD_D_S_LINE |(x) //设置显示起始行
#define LCD_PAGE_ADDR 0xb8 //1011 1000,页地址
#define LCD_SET_PAGE_COM(x) LCD_PAGE_ADDR|(x) //设置页地址
#define LCD_Y_ADDR 0x40 //0100 0000,Y地址
#define LCD_SET_Y_COM(x) LCD_Y_ADDR|(x) //设置Y地址
#define detect_busy(x) ((((x)&0x80)||((x)&0x10))?1:0) //1 - busy,0 - idle
#define detect_disp(x) (((x)&0x20)?1:0) //1 - disp,0 - off
#define chkbit(x,y) ((x)&(1<<y)) //位检测
#define setbit(x,y) ((x)|(1<<y)) //位设置
#define clrbit(x,y) ((x)&(~(1<<y))) //位清除
/******************************************************************************************
全局变量定义
******************************************************************************************/
//内部专用
//unsigned char Disp_buf[8][128]; //显示缓存
//bit Disp_buf_chg=0; //标志显示是否需要刷新1-Y,0-N
typedef struct flash_data
{
unsigned char x; //坐标值(bit7活动位)
unsigned char y; //坐标值
unsigned int code; //汉字内码
unsigned char mode; //显示模式
}LCD_FLASH_DATA;
LCD_FLASH_DATA Flash_data_buf[32]; //元素空间0~31
bit Flash_state; //标志闪烁状态标志
bit Flash_state_ascii;
typedef struct flash_data_ascii
{
unsigned char x; /*x bit7活动位,bit4~bit5显示模式*/
unsigned char y;
unsigned char code;
unsigned char mode;
}LCD_FLASH_DATA_ASCII;
LCD_FLASH_DATA_ASCII Flash_data_buf_ascii[64];
//外部
unsigned char Lcd_flash_timer; //闪烁频率
/******************************************************************************************
绝对值
******************************************************************************************/
unsigned char abs_c(unsigned char x)
{
if(x>0)
return x;
else return -x;
}
/******************************************************************************************
检测LCD忙状态
return : TRUE - 忙,FALSE - 空闲
******************************************************************************************/
char Lcd_detect_busy(void)
{
unsigned char state;
state = LCD_STATE_R_ADDR;
// putchar(state);
return detect_busy(state);
}
/******************************************************************************************
检测LCD显示是否已经打开
return : TRUE - 打开状态,FALSE - 关闭状态
******************************************************************************************/
char Lcd_detect_disp(void)
{
unsigned char state;
state = LCD_STATE_R_ADDR;
return detect_disp(state);
}
/******************************************************************************************
开关LCD显示功能
******************************************************************************************/
void Lcd_turn_on(void)
{
while(Lcd_detect_busy());
LCD_INST_ADDR = LCD_ON_COM;
}
void Lcd_turn_off(void)
{
while(Lcd_detect_busy());
LCD_INST_ADDR = LCD_OFF_COM;
}
/******************************************************************************************
设置显示起始行
in : line_num 显示起始行行号 0~63
******************************************************************************************/
void Lcd_set_start_line(unsigned char line_num)
{
while(Lcd_detect_busy());
LCD_INST_ADDR = LCD_SET_D_LINE_COM(line_num);
}
/******************************************************************************************
设置页地址和Y地址
in : addr_num - 页地址 0~7,Y地址 0~63
chip_num - 芯片编号 1~2
addr_type - 地址类型 0 - 页地址,1 - Y地址, 2 - 行地址
******************************************************************************************/
void Lcd_set_addr(unsigned char addr_num,unsigned char chip_num,unsigned char addr_type)
{
unsigned char op_code;
if(addr_type == 0)
op_code = LCD_SET_PAGE_COM(addr_num);
else if(addr_type == 1)
op_code = LCD_SET_Y_COM(addr_num);
delay_us(10);
if(chip_num == 1)
LCD_INST_ADDR1 = op_code;
else if(chip_num == 2)
LCD_INST_ADDR2 = op_code;
}
/******************************************************************************************
写入显示数据
in : data - 显示数据 0x00~0xff
chip_num - 芯片编号 1~2
******************************************************************************************/
void Lcd_write_data(unsigned char data,unsigned char chip_num)
{
delay_us(10);
if(chip_num == 1)
LCD_DATA_WADDR1 = data;
else if(chip_num ==2)
LCD_DATA_WADDR2 = data;
}
/******************************************************************************************
读显示数据
in : chip_num - 芯片编号
******************************************************************************************/
unsigned char Lcd_read_data(unsigned char chip_num)
{
unsigned char data;
delay_us(10);
if(chip_num == 1)
data = LCD_DATA_RADDR1;
else if(chip_num ==2)
data = LCD_DATA_RADDR2;
return data;
}
/******************************************************************************************
填充屏幕函数
note : 1.以指定的数据填充整个屏幕
2.当data=0x00时,相当于清屏指令
当data=0xff时,相当于黑屏指令
in : data - 填充的数据
******************************************************************************************/
void Lcd_fill_scr(unsigned char data)
{
unsigned char i,j;
for(i=0;i<8;i++)
{
while(Lcd_detect_busy());
LCD_INST_ADDR = LCD_SET_PAGE_COM(i);
while(Lcd_detect_busy());
LCD_INST_ADDR = LCD_SET_Y_COM(0);
for(j=0;j<65;j++)
{
while(Lcd_detect_busy());
LCD_DATA_WADDR = data;
}
}
}
/******************************************************************************************
初始化
******************************************************************************************/
void Lcd_init(void)
{
Lcd_turn_on();
Lcd_fill_scr(0x00);
}
/******************************************************************************************
显示汉字
note : 显示一个16X16大小的字符,详细说明参考Lcd_putsf()
in : disp_data - 显示汉字的内码
x - 显示位置的横坐标0~7
y - 显示位置的纵坐标0~127
mode - 显示模式
0x0 : 正常模式
0x1 : 反显模式
0x4 :闪烁模式
注:显示模式可以组合 eg:0x00|0x01|0x04
******************************************************************************************/
void Lcd_disp_hz(unsigned int disp_data,unsigned char x,unsigned char y,unsigned char mode)
{
unsigned char i,j,hz_pos,k=0;
unsigned char tempc;
unsigned char cs;
unsigned char cs_bck=1;
unsigned char draw_y;
unsigned char xx,yy;
xx = x;
yy = y;
for(hz_pos=0;hz_pos<Db_len;hz_pos++)
{
if(disp_data == Hz_16[hz_pos].index)
break;
}
if(hz_pos == Db_len)
return;
if(y>127)
return;
if(chkbit(x,7) == 0)
{
Lcd_flash_preproc(disp_data,x,y,mode);
if(chkbit(mode,2))
return;
}
else
{
x = clrbit(x,7);
}
if(y>63)
{
y -= 64;
cs_bck = 2;
}
for(i=0;i<2;i++)
{
draw_y = y;
cs = cs_bck;
x += i;
if(x>7)
break;
Lcd_set_addr(x,cs,0);
Lcd_set_addr(y,cs,1);
for(j=0;j<16;j++)
{
tempc = Hz_16[hz_pos].data[k++];
if(chkbit(mode,0))
tempc = ~tempc;
Lcd_write_data(tempc,cs);
draw_y++;
if((draw_y > 63)&&(cs == 1))
{
cs = 2;
Lcd_set_addr(x,cs,0);
Lcd_set_addr(draw_y-64,cs,1);
}
else if((draw_y >63)&&(cs == 2)&&(cs_bck == 2))
{
k = 16;
break;
}
}
}
}
/******************************************************************************************
显示ASCII
note : 显示一个16X8大小的字符,详细说明参考Lcd_putsf()
in : disp_data - ASCII码
x - 显示位置的横坐标0~7
y - 显示位置的纵坐标0~127
mode - 显示模式
0x0 : 正常模式
0x1 : 反显模式
0x4 :闪烁模式
注:显示模式可以组合 eg:0x00|0x01|0x04
******************************************************************************************/
void Lcd_disp_ascii(unsigned char disp_data,unsigned char x,unsigned char y,unsigned char mode)
{
unsigned char i,j,ascii_pos,k=0;
unsigned char tempc;
unsigned char cs;
unsigned char cs_bck=1;
unsigned char draw_y;
unsigned char xx,yy;
xx = x;
yy = y;
if(y>127)
return;
if(chkbit(x,7) == 0)
{
Lcd_flash_preproc_ascii(disp_data,x,y,mode);
if(chkbit(mode,2))
return;
}
else
{
x = clrbit(x,7);
}
if(y>63)
{
y -= 64;
cs_bck = 2;
}
for(i=0;i<2;i++)
{
draw_y = y;
cs = cs_bck;
x += i;
if(x>7)
break;
Lcd_set_addr(x,cs,0);
Lcd_set_addr(y,cs,1);
for(j=0;j<8;j++)
{
tempc = Ascii_16[disp_data][k++];
if(chkbit(mode,0))
tempc = ~tempc;
Lcd_write_data(tempc,cs);
draw_y++;
if((draw_y > 63)&&(cs == 1))
{
cs = 2;
Lcd_set_addr(x,cs,0);
Lcd_set_addr(draw_y-64,cs,1);
}
else if((draw_y >63)&&(cs == 2)&&(cs_bck == 2))
{
k = 8;
break;
}
}
}
}
void Lcd_putsf_ascii(unsigned char flash *data_str,unsigned char x,unsigned char y,unsigned char mode)
{
unsigned char data;
while(*data_str)
{
data = toascii(*data_str++);
if(y>120)
{
y = 0;
x += 2;
}
if(x>6)
continue;
Lcd_disp_ascii(data,x,y,mode);
y += 8;
}
}
void Lcd_puts_ascii(unsigned char *data_str,unsigned char x,unsigned char y,unsigned char mode)
{
unsigned char data;
while(*data_str)
{
data = toascii(*data_str++);
if(y>120)
{
y = 0;
x += 2;
}
if(x>6)
continue;
Lcd_disp_ascii(data,x,y,mode);
y += 8;
}
}
/******************************************************************************************
显示汉字字符串
note : 1.ACM12864的坐标系统定义如下:
以平面直角坐标系的原点为圆心,逆时针旋转90度构成。从12864液晶平面的正面看,左上角
为坐标原点,纵轴为横坐标(X),横轴为纵坐标(Y),范围:X - 0~64,Y - 0~128。实际上,
X/8对应于页地址,\\main.cof
Y/2对应于y地址。
2.从12864液晶平面的正面看,cs=1对应其右半部分平面,cs=2对应其左半部分平面
3.本函数显示的是16X16点阵字库
4.本函数保证显示出的是个完整的字型,当位置不足以显示一个完整的字型时,做换行处理。当
连换行也不能显示一个完整的字型时,做空白处理
5.当字型位置处于cs1和cs2之间时,函数自动完成字型的拼接
6.12864显示16X16点阵字型时,范围为8X4,即满屏4行,每行8个字
in : data_str - 要显示的汉字内码字符串
x - 字串显示位置的横坐标,0~6
y - 字串显示位置的纵坐标,0~128
mode - 显示模式
0正常模式
1反显模式
4闪烁模式
注:显示模式可以组合 eg:0x00|0x01|0x02|0x04
******************************************************************************************/
void Lcd_putsf(unsigned char flash *data_str,unsigned char x,unsigned char y,unsigned char mode)
{
unsigned int data;
while(*data_str)
{
data = *data_str++;
data = (data<<8)|*data_str++;
if(y>112)
{
y = 0;
x += 2;
}
if(x>6)
continue;
Lcd_disp_hz(data,x,y,mode);
y += 16;
}
}
void Lcd_puts(unsigned char *data_str,unsigned char x,unsigned char y,unsigned char mode)
{
unsigned int data;
while(*data_str)
{
if(*data_str > 0xa0)
{
data = *data_str++;
data = (data<<8)|*data_str++;
}
else
data = *data_str++;
if(y>112)
{
y = 0;
x += 2;
}
if(x>6)
continue;
Lcd_disp_hz(data,x,y,mode);
y += 16;
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -