下面是51单片机驱动1602液晶的电路图:
程序一共有3个文件:
/**********************
lcd.h 头文件
**********************/
#ifndef _LCD_H_
#define _LCD_H_
#include <reg51.h>
extern void lcd_init();
extern void lcd_busy();
extern void lcd_write_dat(unsigned char dat);
extern void lcd_write_com(unsigned char dat);
extern void lcd_xy(unsigned char x,unsigned char y);
#endif
/**********************
lcd.c 文件
**********************/
#include "lcd.h"
//#define uchar unsigned char
//#define uint unsigend int
#define port P0
unsigned char table[]="0123456789";
unsigned char table1[]="abcdefABCDEF";
sbit rs=P2^0;
sbit rw=P2^1;
sbit e=P2^2;
/***********************************
***00000 5*7 -> 0xff
*****0** /5*8 0x40
*****0** 0x40 ----> I
*****0** 0x40 ---->
*****0** 0x40
*****0** 0x40
***00000 0x1f
添加自己的自定义字符
***********************************/
code unsigned char ziku[]=
{
0x0f,0x09,0x09,0x0f,0x09,0x09,0x0f,0x00, //汉字“日”
0x0F,0x09,0x0F,0x09,0x0F,0x09,0x11,0x00, //汉字“月”
0x01,0x02,0x03,0x05,0x09,0x03,0x00,0x00, //汉字“年”左半部
0x00,0x00,0x1e,0x08,0x08,0x1e,0x08,0x08 //汉字“年”右半部
};
/*****************
读取lcd1602状态
*****************/
unsigned char lcd_read()
{
unsigned char temp;
e=0;
port=0xff;
rs=0;
rw=1;
e=1;
temp=port;
e=0;
return temp;
}
/***************************************
检测 lcd 是否忙碌
***************************************/
void lcd_busy()
{
unsigned char temp;
do{
temp=lcd_read();
}while((temp&0x80)==0x80);
}
/*****************************************
向lcd里写命令
*****************************************/
void lcd_write_com(unsigned char dat)
{
lcd_busy();
e=0;
port=dat;
rs=0;
rw=0;
e=1;
e=0;
}
/***************************************
读取lcd对应地址数据
*****************************************/
unsigned char lcd_read_dat()
{
unsigned char temp;
lcd_busy();
e=0;
port=0xff;
rs=1;
rw=1;
e=1;
temp=port;
e=0;
return temp;
}
/****************************************
向lcd里写数据
****************************************/
void lcd_write_dat(unsigned char dat)
{
lcd_busy();
e=0;
port=dat;
rs=1;
rw=0;
e=1;
e=0;
}
/****************************************
向lcd写字符串
*****************************************/
void lcd_gets(char *dat)
{
while(*dat!=0)
{
lcd_write_dat(*dat);
dat++;
}
}
/*****************************************
确定要写的位子即x y 坐标
******************************************/
void lcd_xy(unsigned char x,unsigned char y)
{
switch(y)
{
case 0:lcd_write_com(0x80+x);break;//第一行第X个位置
case 1:lcd_write_com(0xc0+x);break;//0xc0==0x80+0x50 第二行第X个位置
case 2:lcd_write_com(0x94+x);break;//
case 3:lcd_write_com(0xd4+x);break;//4*20
}
}
/****************************************************
单行显示才有5*10 其他5*8 MODE=1 5*8 MODE=0 5*10
****************************************************/
add_custom_word(unsigned char *dat,unsigned char len,unsigned char mode)
{
unsigned char n,m;
for(n=0;n<len;n++)
{
if(mode)
{
lcd_write_com(0x40+8*n);
for(m=0;m<8;m++)
{
lcd_write_dat(*dat);
dat++;
}
}
else
{
lcd_write_com(0x40+10*n);
for(m=0;m<10;m++)
{
lcd_write_dat(*dat);
dat++;
}
}
}
}
/********************************************
初始化lcd
********************************************/
void lcd_init()
{
lcd_write_com(0x01) ;//清屏
lcd_write_com(0x03) ;
lcd_write_com(0x3c) ;
lcd_write_com(0x40) ;
lcd_write_com(0x0c) ;
add_custom_word(ziku,4,1); //初始化自定义字符
}
/********************************************
1ms 为基本单位的延时函数
********************************************/
void delay(unsigned char z)
{
unsigned char x,y,a;
for(x=z;x>0;x--)
for(y=110;y>0;y--)
for(a=1;a>0;a--) ;
}
/******************************************
main.c 主文件
******************************************/
#include<reg51.h>
#include"lcd.h"
main()
{
lcd_init();
lcd_busy();
lcd_xy(6,0);
lcd_write_dat('b');
while(1);
}