/********************************************************************* 目 的: 建立LCD1602操作库(偏考虑效率的写法) 目标系统: 基于任何兼容C51的微处理器 应用软件: Keil C *********************************************************************/ /*01010101010101010101010101010101010101010101010101010101010101010101 ---------------------------------------------------------------------- ---------------------------------------------------------------------- 入口参数说明: sbit LCD1602_RS = P0^5; sbit LCD1602_RW = P0^6; sbit LCD1602_E = P0^7; sbit LCD1602_D4 = P2^4; sbit LCD1602_D5 = P2^5; sbit LCD1602_D6 = P2^6; sbit LCD1602_D7 = P2^7; sbit LCD1602_BUSY = P2^7; ---------------------------------------------------------------------- 待定参数说明: #define DELAY() {NOP();NOP();NOP();} ---------------------------------------------------------------------- 对外变量说明: ---------------------------------------------------------------------- 对外函数说明: ---------------------------------------------------------------------- 10101010101010101010101010101010101010101010101010101010101010101010*/ #ifndef LCD1602_H #define LCD1602_H sbit LCD1602_RS = P0^5; sbit LCD1602_RW = P0^6; sbit LCD1602_E = P0^7; sbit LCD1602_D4 = P2^4; sbit LCD1602_D5 = P2^5; sbit LCD1602_D6 = P2^6; sbit LCD1602_D7 = P2^7; sbit LCD1602_BUSY = P2^7; /* 待定参数 */ #define DELAY() {NOP();NOP();NOP();} /* 不考虑移植性的写法,KEIL专用,少占用RAM */ uint8 bdata bdat; sbit bdat0=bdat^0; sbit bdat1=bdat^1; sbit bdat2=bdat^2; sbit bdat3=bdat^3; sbit bdat4=bdat^4; sbit bdat5=bdat^5; sbit bdat6=bdat^6; sbit bdat7=bdat^7; /* 考虑移植性的写法 */ //uint8 bdat; //#define bdat0 (bdat&0x01) //#define bdat1 (bdat&0x02) //#define bdat2 (bdat&0x04) //#define bdat3 (bdat&0x08) //#define bdat4 (bdat&0x10) //#define bdat5 (bdat&0x20) //#define bdat6 (bdat&0x40) //#define bdat7 (bdat&0x80) #define TRUE 1 #define FALSE 0 bool LCD1602Err = FALSE; /*-------------------------------------------------------------------- 函数名称:LCD1602读忙 函数功能:读忙 注意事项:对于高速CPU,应加延时 提示说明: 输 入:无 返 回:无 --------------------------------------------------------------------*/ void busy(void) { uint8 busyCounter=0; bool busySta; //用于探测 lcd busy status LCD1602_D4=1; LCD1602_D5=1; LCD1602_D6=1; LCD1602_D7=1; //DELAY(); LCD1602_RS=0; //DELAY(); LCD1602_RW=1; //DELAY(); do { LCD1602_E=1; //DELAY(); /* 这里读取AC4-AC6位及BF的值,程序不需记录AC4-AC6的值,所以不存储 */ busySta=LCD1602_BUSY; LCD1602_E=0; //DELAY(); /* 读取 "BUSY"时,"D4-D7"状态可能已经改变,必须再次设为输出"1" */ LCD1602_D4=1; LCD1602_D5=1; LCD1602_D6=1; LCD1602_D7=1; //DELAY(); LCD1602_E=1; //DELAY(); /* 这里读取AC0-AC3位的值,程序不需记录AC0-AC3的值,所以不存储 */ LCD1602_E=0; //DELAY(); if(busyCounter==1000) { LCD1602Err=TRUE; //标识LCD1602错误,方便上缴系统报错 return ; //避免由于LCD1602错误而导致程序阻塞 } busyCounter++; } while(busySta); LCD1602Err=FALSE; LCD1602_E=0; } /*-------------------------------------------------------------------- 函数名称:LCD1602写操作 函数功能: 注意事项:对于高速CPU,应加延时 提示说明: 输 入: 返 回:无 --------------------------------------------------------------------*/ void write(bool flag,uint8 dat) //flag=0:command,flag=1:data { bdat=dat; busy(); LCD1602_RS=flag; //DELAY(); LCD1602_RW=0; //DELAY(); LCD1602_D4=(bool)bdat4; //可以不加(bool)类型转换 LCD1602_D5=(bool)bdat5; //加上(bool)则可以提高程序健壮性、可读性等 LCD1602_D6=(bool)bdat6; LCD1602_D7=(bool)bdat7; //DELAY(); LCD1602_E=1; //DELAY(); LCD1602_E=0; //DELAY(); LCD1602_D4=(bool)bdat0; LCD1602_D5=(bool)bdat1; LCD1602_D6=(bool)bdat2; LCD1602_D7=(bool)bdat3; //DELAY(); LCD1602_E=1; //DELAY(); LCD1602_E=0; //DELAY(); } /*-------------------------------------------------------------------- 函数名称:LCD1602命令设置 函数功能: 注意事项:对于高速CPU,应加延时 提示说明: 输 入:"CLR_SCR"/"GO_HOME"/"AC_INC"/"AC_DEC"... 返 回:无 --------------------------------------------------------------------*/ //---- function ------ 1 -------- 0 ----LcdWordPos-- // dispEn | Enable | Disable | bit2 // cursorEn | Enable | Disable | bit1 // blinkEn | Enable | Disable | bit0 //------------------------------------------------------ // isACinc | INC_AC | DEC_AC | bit1 // shiftEn | Enable | Disable | bit0 //------------------------------------------------------ void LCD1602_setCmd(uint8 *str) { static bool dispEn =0; static bool cursorEn=0; static bool blinkEn =0; static bool shiftEn =0; static bool isACinc =0; if(!strcmp(str,"CLR_SCR")) //clear screen write(0,0x01); else if(!strcmp(str,"GO_HOME")) //set AC go home write(0,0x02); /*-------------------------------------------------- isACinc & shiftEn 共用一个命令设置 --------------------------------------------------*/ else if(!strcmp(str,"INC_AC")) //set AC as inc mode { isACinc=1; if(shiftEn) write(0,0x07); else write(0,0x06); } else if(!strcmp(str,"DEC_AC")) //set AC as dec mode { isACinc=0; if(shiftEn) write(0,0x05); else write(0,0x04); } else if(!strcmp(str,"EN_SHIFT")) //enable shift { shiftEn=1; if(isACinc) write(0,0x07); else write(0,0x06); } else if(!strcmp(str,"DIS_SHIFT")) //disable shift { shiftEn=0; if(isACinc) write(0,0x05); else write(0,0x04); } /*-------------------------------------------------- dispEn & cursorEn & blinkEn共用一个命令设置 --------------------------------------------------*/ else if(!strcmp(str,"OPEN_LCD")) //open lcd { dispEn=1; if(cursorEn) if(blinkEn) write(0,0x0F); else write(0,0x0E); else if(blinkEn) write(0,0x0D); else write(0,0x0C); } else if(!strcmp(str,"CLOSE_LCD")) //close lcd { dispEn=0; if(cursorEn) if(blinkEn) write(0,0x0B); else write(0,0x0A); else if(blinkEn) write(0,0x09); else write(0,0x08); } else if(!strcmp(str,"OPEN_CURS")) //open cursor { cursorEn=1; if(dispEn) if(blinkEn) write(0,0x0F); else write(0,0x0E); else if(blinkEn) write(0,0x0B); else write(0,0x0A); } else if(!strcmp(str,"CLOSE_CURS")) //close cursor { cursorEn=0; if(dispEn) if(blinkEn) write(0,0x0D); else write(0,0x0C); else if(blinkEn) write(0,0x09); else write(0,0x08); } else if(!strcmp(str,"EN_BLINK")) //enable blink cursor { blinkEn=1; if(dispEn) if(cursorEn) write(0,0x0F); else write(0,0x0D); else if(cursorEn) write(0,0x0B); else write(0,0x09); } else if(!strcmp(str,"DIS_BLINK")) //disable blink cursor { blinkEn=0; if(dispEn) if(cursorEn) write(0,0x0E); else write(0,0x0C); else if(cursorEn) write(0,0x0A); else write(0,0x08); } /*-------------------------------------------------- dispEn & cursorEn & blinkEn共用一个命令设置 --------------------------------------------------*/ else if(!strcmp(str,"RIGHT_SCR")) //right shift screen write(0,0x1c); else if(!strcmp(str,"LEFT_SCR")) //left shift screen write(0,0x18); else if(!strcmp(str,"RIGHT_CURS")) //right shift cursor write(0,0x14); else if(!strcmp(str,"LEFT_CURS")) //left shift cursor write(0,0x10); } /*-------------------------------------------------------------------- 函数名称:LCD1602初始化 函数功能: 注意事项: 提示说明: 输 入:无 返 回:无 --------------------------------------------------------------------*/ void LCD1602_init(void) { delay50ms(1); //LCD1602_RS=0; //LCD1602_RW=0; //LCD1602_E=0; LCD1602_D7=0; LCD1602_D6=0; LCD1602_D5=1; LCD1602_D4=1; //DELAY(); LCD1602_RS=0; //DELAY(); LCD1602_RW=0; //DELAY(); LCD1602_E=1; //first pulse DELAY(); LCD1602_E=0; delay50us(200); LCD1602_E=1; //second pulse DELAY(); LCD1602_E=0; delay50us(200); LCD1602_E=1; //third pulse DELAY(); LCD1602_E=0; delay50us(200); //LCD1602_RS=0; //LCD1602_RW=0; //LCD1602_E=0; LCD1602_D7=0; LCD1602_D6=0; LCD1602_D5=1; LCD1602_D4=0; //DELAY(); LCD1602_E=1; //DELAY(); LCD1602_E=0; //DELAY(); LCD1602_setCmd("OPEN_LCD"); LCD1602_setCmd("CLR_SCR"); LCD1602_setCmd("INC_AC"); //LCD1602_setCmd("OPEN_CURS"); //LCD1602_setCmd("GO_HOME"); } /*-------------------------------------------------------------------- 函数名称:输出一个字符 函数功能: 注意事项:对于高速CPU,应加延时,好像是废话~ 提示说明:调用LCD1602_putc(0,0,'A'),则在第一行第一个字符处输出'A' 输 入: 返 回:无 --------------------------------------------------------------------*/ void LCD1602_putc(uint X,uint8 Y,uint8 ch) { uchar addr; if(Y) { addr=0xc0; } else { addr=0x80; } write(0,addr+X); write(1,ch); } /*-------------------------------------------------------------------- 函数名称:输出一个字符串 函数功能: 注意事项:无 提示说明:调用LCD1602_puts(0,0,"IloveU "),则从第一行第一个位置开始输出"IloveU" 输 入: 返 回:无 --------------------------------------------------------------------*/ void LCD1602_puts(uint8 X,uint Y,uint8 *str) { while(*str) { LCD1602_putc(X++,Y,*str++); } } #endif