自己写的51控制字符型LCD 源程序,希望大家一起完善.
可输出一个8位的16进制等
#ifndef __REG52_H__
#include <REG52.H>
#endif
#ifndef __INTRINS_H__
#include <INTRINS.H>
#endif
#define HIGH_LEVEL 1
#define LOW_LEVEL 0
#ifndef LCD_BUS4Bit
#define LCD_BUS4Bit 0 //定义LCD的总线宽度是否为4位 1为是 0为否
#ednif
#if LCD_BUS4Bit //此处定义LCD的4位总线是在8位中的是高4位还是低4位,只能二选一
//#define LCD_BUS4Bit_HIGH //定义LCD的4位总线是在8位中的高4位
#ifndef LCD_BUS4Bit_HIGH
#ifndf LCD_BUS4Bit_LOW
#define LCD_BUS4Bit_LOW //定义LCD的4位总线是在8位中的低4位
#endif
#endif
#endif
#ifndef LCD_RS_PORT_ADD
#define LCD_RS_PORT_ADD 0xa6 //p2.6
#endif
#ifndef LCD_RW_PORT_ADD
#define LCD_RW_PORT_ADD 0xa7 //P2.7
#endif
#ifndef LCD_EN_PORT_ADD
#define LCD_EN_PORT_ADD 0xb7 //P3.7
#endif
#ifndef LCD_BUS_PORT_ADD
#define LCD_BUS_PORT_ADD 0xa0 //P2
#endif
#ifndef LCD_X_LINE
#define LCD_X_LINE 4
#endif
#ifndef LCD_X_CHAR_1LINE
#define LCD_X_CHAR_1LINE 16
#endif
sbit LCD_RS=LCD_RS_PORT_ADD; //定义Lcd的RS脚
sbit LCD_RW=LCD_RW_PORT_ADD; //定义LCD的RW脚
sbit LCD_EN=LCD_EN_PORT_ADD; //定义LCD的EN脚
sfr LCDBUS=LCD_BUS_PORT_ADD; //定义LCD的总线端口
unsigned char code LCD_CGRAM[64]={
/* 0x1c,0x14,0x1c,0x00,0x00,0x00,0x00,0x00, //自定义字符00字符代码0x00 显示“°”
0x1f,0x00,0x00,0x00,0x00,0x00,0x00,0x00, //自定义字符01字符代码0x01 显示“°”
0x00,0x1f,0x00,0x00,0x00,0x00,0x00,0x00, //自定义字符02字符代码0x02 显示“°”
0x1f,0x1f,0x00,0x00,0x00,0x00,0x00,0x00, //自定义字符03字符代码0x03 显示“°”
0x00,0x00,0x1f,0x00,0x00,0x00,0x00,0x00, //自定义字符04字符代码0x04 显示“°”
0x1f,0x00,0x1f,0x00,0x00,0x00,0x00,0x00, //自定义字符05字符代码0x05 显示“°”
0x00,0x1f,0x1f,0x00,0x00,0x00,0x00,0x00, //自定义字符06字符代码0x06 显示“°”
0x1f,0x1f,0x1f,0x00,0x00,0x00,0x00,0x00, //自定义字符07字符代码0x07 显示“°”
*/
0x1c,0x14,0x1c,0x00,0x00,0x00,0x00,0x00, //自定义字符00字符代码0x00 显示“°”
// 0x0e,0x00,0x1f,0x0a,0x0a,0x0a,0x13,0x00, //"元"代码
0x08,0x0f,0x12,0x0f,0x0a,0x1f,0x02,0x02, //"年"代码
0x0f,0x09,0x0f,0x09,0x0f,0x09,0x11,0x00, //"月"代码
0x1f,0x11,0x11,0x1f,0x11,0x11,0x1f,0x00, //"日"代码
0x00,0x1F,0x15,0x15,0x1B,0x11,0x1F,0x00, //"四"代码
0x1F,0x08,0x1e,0x0A,0x0A,0x12,0x1F,0x00, //"五"代码
0x08,0x04,0x1F,0x00,0x0A,0x11,0x00,0x00, //"六"代码
// 0x11,0x1b,0x1f,0x1f,0x1f,0x0e,0x04,0x00,
0x1c,0x14,0x1c,0x00,0x00,0x00,0x00,0x00, //自定义字符00字符代码0x00 显示“°”
// 0x00,0x10,0x08,0x04,0x02,0x01,0x00,0x00, //"\"代码
};
//unsigned char lcdcounter;
unsigned char lcd_rddate(void) //返回LCD的数据
{
register lcdstate;
#if LCD_BUS4Bit
register i;
#endif
LCD_RS=LOW_LEVEL;
LCD_RW=HIGH_LEVEL;
#if LCD_BUS4Bit
//lcd总线为4位时的读
#ifdef LCD_BUS4Bit_HIGH //LCD总线为高4位
LCDBUS|=0xf0;
LCD_EN=HIGH_LEVEL;
_nop_();
_nop_();
_nop_();
i=LCDBUS;
lcdstate=i&0xf0;
_nop_();
_nop_();
_nop_();
LCD_EN=LOW_LEVEL;
_nop_();
_nop_();
_nop_();
LCDBUS|=0xf0;
LCD_EN=HIGH_LEVEL;
_nop_();
_nop_();
_nop_();
i=LCDBUS>>4;
i&=0x0f;
lcdstate|=i;
_nop_();
_nop_();
_nop_();
#endif
#ifdef LCD_BUS4Bit_LOW //LCD总线为低4位
LCDBUS|=0x0f;
LCD_EN=HIGH_LEVEL;
_nop_();
_nop_();
_nop_();
i=LCDBUS;
lcdstate=i<<4;
_nop_();
_nop_();
_nop_();
LCD_EN=LOW_LEVEL;
_nop_();
_nop_();
_nop_();
LCDBUS|=0x0f;
LCD_EN=HIGH_LEVEL;
_nop_();
_nop_();
_nop_();
i=LCDBUS;
i&=0x0f;
lcdstate|=i;
_nop_();
_nop_();
_nop_();
#endif
#else
LCDBUS=0xff;
LCD_EN=HIGH_LEVEL;
_nop_();
_nop_();
_nop_();
lcdstate=LCDBUS;
_nop_();
_nop_();
_nop_();
#endif
LCD_EN=LOW_LEVEL;
return(lcdstate);
}
void lcd_wrcmd(unsigned char lcd_cmd) //写LCD命令
{
unsigned int i;
i=3000;
while ((bit)(lcd_rddate()&0x80))
{
if (--i == 0) break;
}
#if LCD_BUS4Bit
//lcd总线为4位时的写
#ifdef LCD_BUS4Bit_HIGH //LCD总线为高4位
LCDBUS&=0x0f;
LCDBUS|=lcd_cmd&0xf0;
LCD_RS=LOW_LEVEL;
LCD_RW=LOW_LEVEL;
LCD_EN=HIGH_LEVEL;
_nop_();
_nop_();
_nop_();
LCD_EN=LOW_LEVEL;
_nop_();
_nop_();
_nop_();
LCDBUS&=0x0f;
LCDBUS|=lcd_cmd<<4;
LCD_EN=HIGH_LEVEL;
_nop_();
_nop_();
_nop_();
LCD_EN=LOW_LEVEL;
_nop_();
_nop_();
_nop_();
LCD_RW=HIGH_LEVEL;
LCDBUS|=0xf0;
#endif
#ifdef LCD_BUS4Bit_LOW //LCD总线为低4位
LCDBUS&=0xf0;
LCDBUS|=lcd_cmd>>4;
LCD_RS=LOW_LEVEL;
LCD_RW=LOW_LEVEL;
LCD_EN=HIGH_LEVEL;
_nop_();
_nop_();
_nop_();
LCD_EN=LOW_LEVEL;
_nop_();
_nop_();
_nop_();
LCDBUS&=0xf0;
LCDBUS|=lcd_cmd&0x0f;
LCD_EN=HIGH_LEVEL;
_nop_();
_nop_();
_nop_();
LCD_EN=LOW_LEVEL;
_nop_();
_nop_();
_nop_();
LCD_RW=HIGH_LEVEL;
LCDBUS|=0x0f;
#endif
#else
//lcd总线为8位时的写
LCDBUS=lcd_cmd;
LCD_RS=LOW_LEVEL;
LCD_RW=LOW_LEVEL;
LCD_EN=HIGH_LEVEL;
_nop_();
_nop_();
_nop_();
LCD_EN=LOW_LEVEL;
_nop_();
_nop_();
_nop_();
LCDBUS=0xff;
#endif
}
void lcd_moveto(unsigned char position)
{
register cmd=0x80;
cmd=cmd|position;
lcd_wrcmd(cmd);
}
void lcd_wrdata(char lcddata) //写LCD数据
{
unsigned int i;
i=3000;
while((bit)(lcd_rddate()&0x80))
{
if (--i == 0) break;
}
#if LCD_BUS4Bit
//lcd总线为4位时的写
#ifdef LCD_BUS4Bit_HIGH //LCD总线为高4位
LCDBUS&=0x0f;
LCDBUS|=lcddata&0xf0;
LCD_RS=HIGH_LEVEL;
LCD_RW=LOW_LEVEL;
LCD_EN=HIGH_LEVEL;
_nop_();
_nop_();
_nop_();
LCD_EN=LOW_LEVEL;
_nop_();
_nop_();
_nop_();
LCDBUS&=0x0f;
LCDBUS|=lcddata<<4;
LCD_EN=HIGH_LEVEL;
_nop_();
_nop_();
_nop_();
LCD_EN=LOW_LEVEL;
_nop_();
_nop_();
_nop_();
LCD_RW=HIGH_LEVEL;
LCDBUS|=0xf0;
#endif
#ifdef LCD_BUS4Bit_LOW //LCD总线为低4位
LCDBUS&=0xf0;
LCDBUS|=lcddata>>4;
LCD_RS=HIGH_LEVEL;
LCD_RW=LOW_LEVEL;
LCD_EN=HIGH_LEVEL;
_nop_();
_nop_();
_nop_();
LCD_EN=LOW_LEVEL;
_nop_();
_nop_();
_nop_();
LCDBUS&=0xf0;
LCDBUS|=lcddata&0x0f;
LCD_EN=HIGH_LEVEL;
_nop_();
_nop_();
_nop_();
LCD_EN=LOW_LEVEL;
_nop_();
_nop_();
_nop_();
LCD_RW=HIGH_LEVEL;
LCDBUS|=0x0f;
#endif
#else
//lcd总线为8位时的写
LCDBUS=lcddata;
LCD_RS=HIGH_LEVEL;
LCD_RW=LOW_LEVEL;
LCD_EN=HIGH_LEVEL;
_nop_();
_nop_();
_nop_();
LCD_EN=LOW_LEVEL;
_nop_();
_nop_();
_nop_();
LCDBUS=0xff;
#endif
}
void lcd_cls(unsigned char line)
{
unsigned char i;
if(line==-1) //是否为全屏清屏
{lcd_wrcmd(0x01); //全屏清屏
}
else {
//以下为单行清屏
line%=LCD_X_LINE;
switch (line)
{
case 0:
lcd_moveto(0x00);
break;
case 1:
lcd_moveto(0x40);
break;
case 2:
lcd_moveto(0x14);
break;
case 3:
lcd_moveto(0x54);
break;
}
for (i=0;i<LCD_X_CHAR_1LINE;i++)
{lcd_wrdata(0x20);
}
}
}
void lcd_string(char *strpoint)
{
register i=0;
while (strpoint[i]!=0){
lcd_wrdata(strpoint[i]);
i++;
}
}
unsigned char lcd_CR(void)
{
register ret_code=0;
register i=0;
i=lcd_rddate()&0x7f;
if (i<=0x14) //第一行的回车
{
if (LCD_X_LINE>=2)
{
lcd_moveto(0x40);
}
else
{
ret_code=-1;
}
}
else if (i<=0x27&&i>0x14) //第三行的回车
{
lcd_moveto(0x54);
}
else if (i<=0x54&&i>0x40) //第二行的回车
{
if (LCD_X_LINE>2)
{
lcd_moveto(0x14);
}
else
{
ret_code=-1;
}
}
else if (i<=0x67&&i>0x54) //第四行的回车
{
ret_code=-1;
}
return(ret_code);
}
unsigned char lcd_printf(char *strpoint)
{
register i=0;
register temp_point=0;
register ret_code=0;
while (strpoint[i]!=0){
if (strpoint[i]==0x0a)
{
if(lcd_CR()!=0)
{
ret_code=-1;
break;
}
i++;
if(strpoint[i]==0){
break;
}
}
temp_point=lcd_rddate()&0x7f;
//判断光标是否在行尾
switch (temp_point) {
case LCD_X_CHAR_1LINE :
case 0x40+LCD_X_CHAR_1LINE :
case 0x14+LCD_X_CHAR_1LINE :
case 0x54+LCD_X_CHAR_1LINE :
{
if(lcd_CR()!=0)
{
ret_code=-1;
}
break;
}
}
if(ret_code==-1)
{
break;
}
//判断是否输出到显示屏的最后一个字符
if (temp_point!=0x27){
if (temp_point!=0x67){
lcd_wrdata(strpoint[i]);
}
else {
lcd_wrdata(strpoint[i]);
if (strpoint[i+1]==0){
break;
}
else {
ret_code=-1;
break;
}
}
}
else {
lcd_wrdata(strpoint[i]);
lcd_moveto(0x54);
}
i++;
}
return(ret_code);
}
//LCD按位置输出字符串
void lcd_point_print(char *strpoint,unsigned char print_line,unsigned char start_point)
{
register unsigned char i;
print_line%=LCD_X_LINE;
if (start_point<LCD_X_CHAR_1LINE){
switch(print_line){
case 0:
lcd_moveto(0x00+start_point);
break;
case 1:
lcd_moveto(0x40+start_point);
break;
case 2:
lcd_moveto(0x14+start_point);
break;
case 3:
lcd_moveto(0x54+start_point);
break;
}
for (i=0;i<LCD_X_CHAR_1LINE-start_point;i++){
if (strpoint[i]!=0){
lcd_wrdata(strpoint[i]);
}
else {
break;
}
}
}
}
//输出单字符
void lcd_char_print(char out_char,unsigned char print_line,unsigned char start_point)
{
print_line%=LCD_X_LINE;
#ifdef DEBUG
printf("start_point=%x\n",(int)(start_point));
#endif
if (start_point<LCD_X_CHAR_1LINE){
switch(print_line){
case 0:
lcd_moveto(0x00+start_point);
break;
case 1:
lcd_moveto(0x40+start_point);
break;
case 2:
lcd_moveto(0x14+start_point);
break;
case 3:
lcd_moveto(0x54+start_point);
break;
}
lcd_wrdata(out_char);
}
}
void lcd_hex_print(unsigned char out_hex,unsigned char print_line,unsigned char start_point)
{
print_line%=LCD_X_LINE;
#ifdef DEBUG
printf("start_point=%x\n",(int)(start_point));
#endif
if (start_point<LCD_X_CHAR_1LINE){
switch(print_line){
case 0:
lcd_moveto(0x00+start_point);
break;
case 1:
lcd_moveto(0x40+start_point);
break;
case 2:
lcd_moveto(0x14+start_point);
break;
case 3:
lcd_moveto(0x54+start_point);
break;
}
if ((out_hex>>4)>9){
lcd_wrdata(0X37+(out_hex>>4));
}
else {
lcd_wrdata(0X30+(out_hex>>4));
}
if ((out_hex&0x0f)>9){
lcd_wrdata(0X37+(out_hex&0x0f));
}
else {
lcd_wrdata(0X30+(out_hex&0x0f));
}
}
}
//LCD 从行开始输出字符串
void lcd_line_print(char *strpoint,unsigned char print_line)
{
register unsigned char i;
print_line=print_line%LCD_X_LINE;
lcd_cls(print_line);
switch (print_line)
{
case 0:
lcd_moveto(0x00);
break;
case 1:
lcd_moveto(0x40);
break;
case 2:
lcd_moveto(0x14);
break;
case 3:
lcd_moveto(0x54);
break;
}
for (i=0;i<LCD_X_CHAR_1LINE;i++){
if (strpoint[i]!=0){
lcd_wrdata(strpoint[i]);
}
else{
break;
}
}
}
void lcd_init()
{
register unsigned int i;
#if LCD_BUS4Bit
lcd_wrcmd(0x28); //4BIT 2 line 5*7
#else
lcd_wrcmd(0x38); //8BIT 2 line 5*7
#endif
for (i=0;i<30000;i++) //软件延时
{
_nop_();
_nop_();
_nop_();
}
#if LCD_BUS4Bit
lcd_wrcmd(0x28); //4BIT 2 line 5*7
#else
lcd_wrcmd(0x38); //8BIT 2 line 5*7
#endif
for (i=0;i<30000;i++) //软件延时
{
_nop_();
_nop_();
_nop_();
}
#if LCD_BUS4Bit
lcd_wrcmd(0x28); //4BIT 2 line 5*7
#else
lcd_wrcmd(0x38); //8BIT 2 line 5*7
#endif
lcd_wrcmd(0x0c); //display on
lcd_wrcmd(0x06);
lcd_wrcmd(0x01);
//写CGram
lcd_wrcmd(0x40);
for (i=0;i<64;i++)
{
lcd_wrdata(LCD_CGRAM[i]);
}
}