12864LCD资料
LCD_V1.h:
(这是一个可以精确到像素级的JM12864G的LCD头文件,用户可以使用里面的API完成这样的功能:把某个图片显示在屏
幕坐标系的任意位置,超出屏幕部分不显示,不自动换行,而不只是在纵坐标上具体到像素级,而横坐标只能是“第几个字”的位置)
#ifndef __LCD_V1_H__
#define __LCD_V1_H__
// write your header here
///////////////////LCD////////////////////////////////
#define IO_Data_LCD *P_IOA_Data
#define IO_Dir_LCD *P_IOA_Dir
#define IO_Attrib_LCD *P_IOA_Attrib
#define Dir_OUT 0xE000//0x0700
#define Attrib_OUT 0xE000//0x0700
#define Dir_IN 0xAFFF
#define Attrib_IN 0xAFFF
#define SCLK_H_LCD 0x8000//0x0400
#define STD_H_LCD 0x4000//0x0200
#define CS_H_LCD 0x2000//0x0100
#define SCLK_L_LCD 0x0000
#define STD_L_LCD 0x0000
#define CS_L_LCD 0x0000
///////////////////////////////////////////////////////
//***********************模块联合配置*************************
//把使能端设为正向输出并输出非使能信号,
//其他端设为带下拉电阻的输入。
#define Watchdog_Clear *P_Watchdog_Clear
#define CD *P_Watchdog_Clear=1; #define Dir_Disable CS_H_LCD//只设置使能端,其他位为输入
#define Attrib_Disable CS_H_LCD//只设置使能端属性,其他位为非悬浮输入
#define Data_Disable CS_L_LCD//使使能端产生(输入或输出)非使能信号;其他位为低电平 //************************************************************
#define CMD_LENGTH_LCD 8
#define UPPER_LEFT 0x80//屏幕左上角坐标值
#define LOWER_RIGHT 0x9f//屏幕右下角坐标值
#define LINE_WIDTH 8//每行最多可以显示的汉字个数
#define IsData 1
#define IsCmd 0
#define IsFirst 1
#define NotFirst 0
const int MASK10[]={0x0001,0x0002,0x0004,0x0008,
0x0010,0x0020,0x0040,0x0080,
0x0100,0x0200};
const char DAY_CN[]="日一二三四五六";
typedef enum {CLEAR=0x01,RESET_ADDRESS=0x02,WRT_CMD_PRE=0x0000,WRT_DAT_PRE=0x0200} CMD;
//串行写入命令字,如果是数据,则isData非0,否则为写控制字,两者差别在于完整10位控制字的最高最是否为1.
//其中指令cmd有效位只有低8位。JM12864G的完整指令字是10位,最高位为0表示操作命令,否则表示操作数据;次
高位
//为0表示写否则表示读。
void write_lcd(int cmd,int isData){
int t1;
int i;
const int half_cmd=CMD_LENGTH_LCD>>1;
IO_Dir_LCD=Dir_Disable|Dir_OUT;
IO_Attrib_LCD=Attrib_Disable|Attrib_OUT;
IO_Data_LCD=Data_Disable;
t1=Data_Disable|CS_H_LCD|STD_H_LCD;
for(i=0;i<5;i++){
IO_Data_LCD=t1|SCLK_L_LCD;
IO_Data_LCD=t1|SCLK_H_LCD;
}
//R/W为写
t1=Data_Disable|CS_H_LCD|STD_L_LCD;
IO_Data_LCD=t1|SCLK_L_LCD;
IO_Data_LCD=t1|SCLK_H_LCD;
if(isData)//写数据
t1=Data_Disable|CS_H_LCD|STD_H_LCD;
else//写指令
t1=Data_Disable|CS_H_LCD|STD_L_LCD;
IO_Data_LCD=t1|SCLK_L_LCD;
IO_Data_LCD=t1|SCLK_H_LCD;
//写0
t1=Data_Disable|CS_H_LCD|STD_L_LCD;
IO_Data_LCD=t1|SCLK_L_LCD;
IO_Data_LCD=t1|SCLK_H_LCD;
for(i=CMD_LENGTH_LCD-1;i>=half_cmd;i--){
if(cmd&MASK10[i])
t1=Data_Disable|CS_H_LCD|STD_H_LCD;
else
t1=Data_Disable|CS_H_LCD|STD_L_LCD;
IO_Data_LCD=t1|SCLK_L_LCD;
IO_Data_LCD=t1|SCLK_H_LCD;
}
t1=Data_Disable|CS_H_LCD|STD_L_LCD;
for(i=0;i
=0;i--){
if(cmd&MASK10[i])
t1=Data_Disable|CS_H_LCD|STD_H_LCD;
else
t1=Data_Disable|CS_H_LCD|STD_L_LCD;
IO_Data_LCD=t1|SCLK_L_LCD;
IO_Data_LCD=t1|SCLK_H_LCD;
}
t1=Data_Disable|CS_H_LCD|STD_L_LCD;
for(i=0;i>1;
IO_Dir_LCD=Dir_Disable|Dir_OUT;
IO_Attrib_LCD=Attrib_Disable|Attrib_OUT;
IO_Data_LCD=Data_Disable|SCLK_H_LCD;
t1=Data_Disable|CS_H_LCD|STD_H_LCD;
for(i=0;i<5;i++){
IO_Data_LCD=t1;
IO_Data_LCD=t1|SCLK_H_LCD;
}
//R/W为读
t1=Data_Disable|CS_H_LCD|STD_H_LCD;
IO_Data_LCD=t1;
IO_Data_LCD=t1|SCLK_H_LCD;
//读指令
t1=Data_Disable|CS_H_LCD;
IO_Data_LCD=t1;
IO_Data_LCD=t1|SCLK_H_LCD;
//写0
t1=Data_Disable|CS_H_LCD;
IO_Data_LCD=t1;
IO_Data_LCD=t1|SCLK_H_LCD;
//开始读数据
IO_Dir_LCD=(Dir_Disable&Dir_IN)|SCLK_H_LCD;
for(i=CMD_LENGTH_LCD-1;i>=half_cmd;i--){
t1=IO_Data_LCD;
if(t1&STD_H_LCD)
data|=MASK10[i];
IO_Data_LCD=Data_Disable|CS_H_LCD;
IO_Data_LCD=Data_Disable|CS_H_LCD|SCLK_H_LCD;
}
for(i=0;i=0;i--){
t1=IO_Data_LCD;
if(t1&STD_H_LCD)
data|=MASK10[i];
IO_Data_LCD=Data_Disable|CS_H_LCD;
IO_Data_LCD=Data_Disable|CS_H_LCD|SCLK_H_LCD;
}
for(i=0;i>1;
int ori_add;//原始地址
IO_Dir_LCD=Dir_Disable|Dir_OUT;
IO_Attrib_LCD=Attrib_Disable|Attrib_OUT;
IO_Data_LCD=Data_Disable|SCLK_H_LCD;
t1=Data_Disable|CS_H_LCD|STD_H_LCD;
for(i=0;i<5;i++){
IO_Data_LCD=t1;
IO_Data_LCD=t1|SCLK_H_LCD;
}
//R/W为读
t1=Data_Disable|CS_H_LCD|STD_H_LCD;
IO_Data_LCD=t1;
IO_Data_LCD=t1|SCLK_H_LCD;
t1=Data_Disable|CS_H_LCD|STD_H_LCD;
IO_Data_LCD=t1;
IO_Data_LCD=t1|SCLK_H_LCD;
//写0
t1=Data_Disable|CS_H_LCD;
IO_Data_LCD=t1;
IO_Data_LCD=t1|SCLK_H_LCD;
ori_add=isBusy()&0xff;//记录原始地址
setXY_local(x,y);//设置地址
//开始读
IO_Dir_LCD=Dir_Disable&Dir_IN;
for(i=CMD_LENGTH_LCD-1;i>=half_cmd;i--){
t1=IO_Data_LCD;
if(t1&STD_H_LCD)
data|=MASK10[i];
t1=Data_Disable|CS_H_LCD;
IO_Data_LCD=t1;
IO_Data_LCD=t1|SCLK_H_LCD;
}
for(i=0;i=0;i--){
t1=IO_Data_LCD;
if(t1&STD_H_LCD)
data|=MASK10[i];
t1=Data_Disable|CS_H_LCD;
IO_Data_LCD=t1;
IO_Data_LCD=t1|SCLK_H_LCD;
}
for(i=0;i=UPPER_LEFT)){
write_lcd(t1,0);
return 1;
}
else
return 0;
}
//针对于我组分到的特殊LCD,对LCD的坐标控制特作如下调整:将1,2行调换
int setXY_local(int x,int y){
switch(y){
case 0:
return setXY(x,0);
case 1:
return setXY(x,2);
case 2:
return setXY(x,1);
case 3:
return setXY(x,3);
}
return 0;
}
//从x,y处开始显示字符,超出屏幕长度的字符不显示,返回已显示的半字个数。参数不做检查,要显示字符必须以\0结尾或
//长度为len显示时将显示以\0结尾的字符串的长度和len中最小者个数。若是该位置的第一个字符,则isFirst必须非零。
int display_str(int startX,int startY,char* c,int len,int isFirst){
int i=0;//字符串c的计数变量
int half_word=0;//半字个数//
int x=startX,y=startY;
write_lcd(0x20,IsCmd);
if(!isFirst){//若不是第一个半字,则补充空格
setXY_local(x,y);
write_lcd(' ',1);
half_word++;
}
while(1){
if(!(half_word&0x01))
setXY_local(x,y);
write_lcd(c[i++],1);
half_word++;
if(c[i]&&i=0xa1&&c[i-1]<0xa1){
write_lcd(' ',1);
half_word++;
}
}
else
break;
x=startX+((half_word>>1)&0x07);
y=startY+(half_word>>4);
}
if(x==0x07)
setXY_local(0,y+1);
else
setXY_local(x+1,y);
return half_word;
}
//
void lcd_init(){
write_lcd(RESET_ADDRESS,0);
write_lcd(0x0d,0);//设置显示状态,整体显示ON,游标与游标位置ON//write_lcd(0x0d,0)
write_lcd(0x30,0);//功能设置,基本指令
write_lcd(0x18,0);//游标与显示移位控制
write_lcd(CLEAR,0);
}
//从x,y处开始写入img数组的start(包含)到end(不包含)的数据。(start与end都是之"字格")只显示一行,超出屏幕部分
不换行,不显示
void display_img_line(char* img,const int start,const int end,int x,int y){
int i;
if(x>=0&&x<=0x0f&&y>=0&&y<=0x1f){
for(i=start;i=end)
break;
write_lcd(img[i],IsData);
if((x&0x07)!=0x07){
x++;
}
CD
}
write_lcd(0x26,IsCmd);
}
}
//用p填充整个屏幕填充整个屏幕从而达到清除图片的效果
void fill_img(const char p){
int i,j;
for(i=0;i<0x20;i++){
write_lcd(0x24,IsCmd);
write_lcd(0x80|i,IsCmd);
write_lcd(0x80,IsCmd);
write_lcd(0x20,IsCmd);
for(j=0;j<0x10;j++){
write_lcd(p,IsData);
CD
}
CD
}
for(i=0;i<0x20;i++){
write_lcd(0x24,IsCmd);
write_lcd(0x80|i,IsCmd);
write_lcd(0x88,IsCmd);
write_lcd(0x20,IsCmd);
for(j=0;j<0x10;j++){
write_lcd(p,IsData);
CD
}
CD
}
write_lcd(0x26,IsCmd);
}
//用p填充整个屏幕填充x,y(像素级别)开始的xl*yl范围内的区域(像素级别不跨屏幕)
void fill_area(int x,int y,int xl,int yl,const char p){
/*int i,j;
xl+=x;
xl--;
x>>=4;
xl>>=4;
yl+=y;
for(i=y;i>=4;
xl>>=4;
yl+=y;
for(i=y;i>4;
px=x;
bit_offset=x&0x0f;
write_lcd(0x24,IsCmd);
write_lcd(0x80|y,IsCmd);
write_lcd(0x80|dx,IsCmd);
write_lcd(0x20,IsCmd);
if(bit_offset==0){
as=0;
for(i=offset;i>bit_offset,IsData);
as=1;
for(i=offset+1;i>bit_offset)|(img[i-1]<<(8-bit_offset)),IsData);
as++;
if((as&0x01)==0){
if((dx&0x07)!=0x07)
dx++;
else
break;
}
CD
}
write_lcd((img[ae-1]<<(8-bit_offset)),IsData);
}else{//bit_offset>8
bit_offset-=8;
write_lcd(0,IsData);
write_lcd(img[offset]>>bit_offset,IsData);
as=2;
dx++;
for(i=offset+1;i>bit_offset)|(img[i-1]<<(8-bit_offset)),IsData);
as++;
if((as&0x01)==0){
if((dx&0x07)!=0x07)
dx++;
else
break;
}
}
CD
write_lcd((img[ae-1]<<(8-bit_offset)),IsData);
}
write_lcd(0x26,IsCmd);
}
#endif