51单片机之1602液晶屏

1602的相关概念这里就不赘述了,网上有好多现成的,比如1602工作原理

在里只大致记录下将时序转换成代码。

1602主要是用的最多的是写数据,接下来先讲下写操作时序。
先对使用的三个主要引脚做下解释,以下摘录自手册。

4 RS 为寄存器选择,高电平时选择数据寄存器、低电平时选择指令寄存器。
5 R/W 为读写信号线,高电平时进行读操作,低电平时进行写操作。当 RS R/W
同为低电平时可以写入指令或者显示地址,当 RS 为低电平 R/W 为高电平时可以读忙信号,
RS 为高电平 R/W 为低电平时可以写入数据。
6 E 端为使能端,当 E 端由高电平跳变成低电平时,液晶模块执行命令。

一、写操作时序

写操作时序图
写操作时序图

 在正式写指令寄器操作时(即上图中tpw开始的时间点),RS = 0, RW = 0, E = 0 所以读取数据之前直接将RS = 0, RW = 0,E = 0。设置完成之后需要在tsp1时间后才能将E拉成高电平, 且在将E拉到高电平之前需要提前效固定数据,即tsp2所示的时间,所以可以将数据写入端口,并延迟一断时间,再将E拉成高电平,延迟一断时间(tpw)等待数据操作完成。完成之后再将E拉成低电平。所以写指令的操作代码可以转换成如下:

void write_cmd(char cmd) {
	busy_check();
	RS = 0;
	RW = 0;
	EN = 0;
	P0 = cmd;
	_nop_(); // tsp2
	EN = 1;
	_nop_(); // tsw
	EN = 0;
}

1602各时序参数都是ns为单位,单片机一个指令周期是1/11.0593MHZ = 90ns, 是完全可以的。

同理写地址操作也一样,只不过RS = 1。

void write_data(char d) {
	busy_check();
	RS = 1;
	RW = 0;
	EN = 0;
	P0 = d;
	_nop_(); //tsp2
	EN = 1;
	_nop_(); // tpw
	EN = 0;
}

二、读操作时序

读操作时序这里有一个体现的地方,就是忙时检测。忙时检测时RS引脚为低电平,在正式读取数据之前可以将RS为了低电平 ,RW设置为高电平,E设置为低电平,另外需要在tsp1时间后才能将E拉成高电平,在tpw时间开始时后的td时间后才能读取有效数据,那么需要在tpw开始之后进行延时,读取完成之后将E拉成低电平即可。换算成代码如下:

void busy_check() {
	char temp = 0x80;
	P0 = 0X80;
	while(temp & 0x80) {
		RS = 0;
		RW = 1;
		EN = 0;
		_nop_(); // tsp1
		EN = 1;
		_nop_(); // td
		temp = P0;
		EN = 0;
	}
}

当然因为单片机执行的速度比液晶模块快,所以有些延迟其实是没有必要的,比如`busy_check`中的延迟都可以去掉并不影响执行结果。

三、源码(只是简单的进行显示)

#include "reg52.h"
#include <intrins.h>
#include <string.h>

#define dataBuffer P0;

sbit led = P3^7;
sbit RS = P1^0;
sbit RW = P1^1;
sbit EN = P1^4;

void Delay15ms()		//@11.0592MHz
{
	unsigned char i, j;

	i = 27;
	j = 226;
	do
	{
		while (--j);
	} while (--i);
}

void Delay5ms()		//@11.0592MHz
{
	unsigned char i, j;

	i = 9;
	j = 244;
	do
	{
		while (--j);
	} while (--i);
}

// 忙检测
void busy_check() {
	char temp = 0x80;
	P0 = 0X80;
	while(temp & 0x80) {
		RS = 0;
		RW = 1;
		EN = 0;
		_nop_(); // tscp
		EN = 1;
		_nop_(); // td
		temp = P0;
		EN = 0;
	}
}

void write_cmd(char cmd) {
	busy_check();
	RS = 0; // 写地址
	RW = 0;
	EN = 0;
	P0 = cmd;
	_nop_();
	_nop_();
	_nop_();
	EN = 1;
	_nop_();
	EN = 0;
}

void write_data(char d) {
	busy_check();
	RS = 1;
	RW = 0;
	EN = 0;
	P0 = d;
	_nop_();
	EN = 1;
	_nop_();
	_nop_();
	_nop_();
	EN = 0;
}

void init() {
	
	
	Delay15ms();
	write_cmd(0x38);
	Delay5ms();
	write_cmd(0x38);
	write_cmd(0x08);
	write_cmd(0x01);
	write_cmd(0x06);
	write_cmd(0x0c);
}

void Delay1000ms()		//@11.0592MHz
{
	unsigned char i, j, k;

	_nop_();
	i = 8;
	j = 1;
	k = 243;
	do
	{
		do
		{
			while (--k);
		} while (--j);
	} while (--i);
}



void main() {
	char temp[] = "hello everyone!"; 
	char position = 0x80;
	char dataShow = 'C';
	int i = 0;
	init();
	write_cmd(position);//选择要显示的地址
	for(i = 0; i < 15;i ++) {
		write_data(temp[i]);
		Delay1000ms();
		
	}
	//write_data(dataShow);//发送要显示的字符
	while(1);
}

四,效果图:

      

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

俯仰一世_1

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值