Chinaunix首页 | 论坛 | 博客
  • 博客访问: 961956
  • 博文数量: 210
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 2070
  • 用 户 组: 普通用户
  • 注册时间: 2014-11-19 21:54
文章分类

全部博文(210)

文章存档

2020年(2)

2019年(18)

2018年(27)

2017年(5)

2016年(53)

2015年(88)

2014年(17)

分类: 嵌入式

2015-05-09 23:21:15

1.原理图:

2.源代码

/*lcd1602
显示16*2个字母或者数字
RS  数据/指令引脚,0代表指令,1代表数据
RW  读/写控制引脚,0代表写,1代表读
E   使能位,1打开,0关闭
D0~D7 数据/地址总线,数据和指令都通过这里传输


先发指令,后发数据
1602操作过程:
1)初始化,指定1602如何显示
2)发送地址,指定数据要显示在屏幕的哪个地方
3)发数据,指定屏幕上显示什么


关于手册:时序图,指令1、2、3、4、6、8、9
*/
#include


#define uchar unsigned char 
sbit LCD_1602_RS=P2^0;
sbit LCD_1602_RW=P2^1;
sbit LCD_1602_EN=P2^5;


/*****************************************************
函数功能:延时1ms
(3j+2)*i=(3×33+2)×10=1010(微秒),可以认为是1毫秒
***************************************************/
void delay_1ms()
{
   float i,j;
for(i=0;i<4;i++)
 for(j=0;j<33;j++)
  ;  
  i++;
}
/**************************************************
函数功能:延时10微妙
程序调用 2us + 子程序返回 2us + R7赋值 1us
**************************************************/
 void delay_10us()
 {
  unsigned int i = 100;
i--;
i--;
i--;
i--;
i--;
i--;
 } 


//读忙标志,LCD工作速度较慢,只有它不忙的时候才可以接受单片机的指令
int lcd_1602_busy()
{
uchar tmp;
P0 = 0xff;
LCD_1602_RW = 1;
LCD_1602_RS = 0;


LCD_1602_EN = 1;
delay_10us();
tmp = P0;
LCD_1602_EN = 0;


//强制转换,将一个8位二进制转换成1位的
//bit是位数据
//如果1602忙,那么tmp的最高位是1
return (bit)(0x80 & tmp);


}


void lcd_1602_write_cmd(uchar cmd)
{
//等待1602不忙
  while(lcd_1602_busy());

LCD_1602_RW = 0;
LCD_1602_RS = 0;
P0 = cmd;


LCD_1602_EN = 1;
delay_10us();
LCD_1602_EN = 0;
}


void lcd_1602_write_data(uchar dat)
{
while(lcd_1602_busy());


LCD_1602_RW = 0;
LCD_1602_RS = 1;
P0 = dat;


LCD_1602_EN = 1;
delay_10us();
LCD_1602_EN = 0;
}


void lcd_1602_init()
{
lcd_1602_write_cmd(0x01); //指令1,发送清屏指令
lcd_1602_write_cmd(0x0c); //指令4,打开显示开关,没有光标
lcd_1602_write_cmd(0x38);    //指令6,8位总线,双行显示,5*7点阵
lcd_1602_write_cmd(0x05); //指令3,光标左移,屏幕上的字左移
lcd_1602_write_cmd(0x01); //清屏,所有的配置完成之后,需要清屏
delay_1ms();
}


void lcd_1602_write_char(uchar x, uchar y, uchar dat)
{
if(x == 0)
{
lcd_1602_write_cmd(0x80 + y%16);
lcd_1602_write_data(dat);
}
else
{
lcd_1602_write_cmd(0xc0 + y%16);
lcd_1602_write_data(dat);
}
}


void lcd_1602_write_string(uchar x, uchar y, uchar *string)
{
int i=0;
while(i<15-y)
{
lcd_1602_write_char(x, y++, *(string++));
}
}
void delay()
{
int i,j;
for(i=0;i<1000;i++)
for(j=0;j<100;j++);
}


void lcd_1602_write_left(uchar x, int len, char *string)
{
int i = 0;
while(i {
delay();
lcd_1602_write_string(x, 15-i, string);
i++;
}
}
void main() // 00001 110
{

char str[5]="12345";
lcd_1602_init();

lcd_1602_write_string(0,10, "hello");
lcd_1602_write_char(1, 1, 'a');
lcd_1602_write_left(1, 5, str);
}


3.说明


lcd1602
显示16*2个字母或者数字
RS  数据/指令引脚,0代表指令,1代表数据
RW  读/写控制引脚,0代表写,1代表读
E   使能位,1打开,0关闭
D0~D7 数据/地址总线,数据和指令都通过这里传输


写指令:
RS = 0;
RW = 0;
P0 = 0x01;
delay_10us();
E = 1;
delay_10us();
E = 0;


写数据:
RS = 1;
RW = 0;
P0 = data;
delay_10us();
E = 1;
delay_10us();
E = 0;


读指令:
RS = 0;
RW = 1;
delay_10us();
E = 1;
delay_10us();
temp = P0;
E = 0;


读数据:
RS = 1;
RW = 1;
delay_10us();
E = 1;
delay_10us();
temp = P0;
E = 0;




阅读(1887) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~