51单片机控制1602LCD显示屏输出两行文字一
1.概述
这篇文章介绍1602型号显示屏的基础知识,以及使用单片机控制它输出两行内容。
2.1602基础知识
1602 液晶显示模块是一种通用的工业液晶显示模块,专门用来显示字母、数字、符号等的点阵型液晶显示模块。从名字就可以看出该液晶显示模块有 2 行,每行 16 个字符共可以显示 32 个字符。每个字符是由 5x7 或者 5x11 的点阵位组成,我们这里讲解的为 5x7 模式的模块
1602引脚说明
1602地址映射
1602的RAM存储中有80个字节,其中第一行的开始是0x00,第二行的开始是0x40
1602内部初始化指令
在操控1602前先通过内置的指令对它进行初始化,内置指令如下。
c
// 定义指令集
/*设置显示模式*/
#define LCD_MODE_PIN8 0x38 // 8位数据线,两行显示
#define LCD_MODE_PIN4 0x28 // 4位数据线,两个显示
#define LCD_SCREEN_CLR 0x01 // 清屏
#define LCD_CURSOR_RET 0x02 // 光标复位
#define LCD_CURSOR_RIGHT 0x06 // 光标右移,显示不移动
#define LCD_CURSOR_LEFT 0x04 // 光标左移,显示不移动
#define LCD_DIS_MODE_LEFT 0x07 // AC自增,画面左移
#define LCD_DIS_MODE_RIGHT 0X05 // AC自增,画面右移
/*光标开关控制*/
#define LCD_DIS_CUR_BLK_ON 0x0f // 显示开,光标开,光标闪烁
#define LCD_DIS_CUR_ON 0x0e // 显示开,光标开,光标不闪烁
#define LCD_DIS_ON 0x0c // 显示开,光标关,光标不闪烁
#define LCD_DIS_OFF 0x08 // 显示关,光标关,光标不闪烁
/*光标、显示移动*/
#define LCD_CUR_MOVE_LEFT 0x10 // 光标左移
#define LCD_CUR_MOVE_RIGHT 0x14 // 光标右移
#define LCD_DIS_MOVE_LEFT 0x18 // 显示左移
#define LCD_DIS_MOVE_RIGHT 0x1c // 显示右移
1602时序
1602操控可归纳为两个分类读和写,这两个操作都离不开时序图,它是操控1602的核心,看懂了时序图就能通过代码来控制1602输出定义的字符。
读时序图解读
将 R/W 拉高进入读操作模式,同时 RS 要么为高电平要么为低电平,高电平时为读数据操作,低电平时为读状态操作,经过 tSP1 时间之后才可将使能信号 E 拉高,并且 E 的高电平维持时间为 tPW,在使能信号 E 拉高之后不超过 tD 时间内,1602 液晶显示器将数据放在 DB0~DB7 数据线上。这时我们将数据读取并将使能 E 拉低,整个数据或状态的读取就完成了。
写时序图解读
写操作时序与读操作的基本一致,唯一不同的是,在使能信号 E 拉高之前 tSP2 单片机必须把需要写的数据送到数据端口上。当 RS=1 时,表示将要往 1602 写数据,当 RS=0 时,表示将要往 1602 里面写指令。
时序图各阶段执行时间
单片机与1602电路原理图
3. 单片机控制1602输出内容
下面使用单片机控制1602输出两行字符代码,该代码是控制1602最小程序,可以分成如下几个部分
- 定义引脚功能
- 定义单片机引脚连接1602引脚的功能
- 定义指令集
- 1602芯片内部固化了几个必备的操作指令,使用这些命令用来初始化1602
- 创建读忙检测函数
- 1602每次操作完成后才可以接收新的命令,因此在发送命令前检测1602是否忙碌。
- 创建写指令函数
- 接收1602初始化命令,以及输出数据的地址。
- 创建写数据函数
- 接收单片机字符,然后输出到1602显示
- 创建1602初始化函数
- 通过初始化设置1602默认的工作方式
- 创建输出字符函数
- 调用写命令函数接收数据显示的地址,调用写数据函数在1602指定的位置显示数据
- 创建主函数
c
#include <STC12C2052AD.H>
typedef unsigned char uint8;
// 定义引脚
#define LCD1602_DB0_DB7 P1 // 定义LCD1602的数据总线
sbit LCD1602_RS = P3 ^ 2; // 定义LCD1602的RS控制线
sbit LCD1602_RW = P3 ^ 3; // 定义LCD1602的RW控制线
sbit LCD1602_E = P3 ^ 4; // 定义LCD1602的E控制线
sbit LCD1602_Busy = P1 ^ 7; // 定义LCD1602的测忙线(与LCD1602_DB0_DB7关联)
// 定义指令集
/*设置显示模式*/
#define LCD_MODE_PIN8 0x38 // 8位数据线,两行显示
#define LCD_MODE_PIN4 0x28 // 4位数据线,两个显示
#define LCD_SCREEN_CLR 0x01 // 清屏
#define LCD_CURSOR_RET 0x02 // 光标复位
#define LCD_CURSOR_RIGHT 0x06 // 光标右移,显示不移动
#define LCD_CURSOR_LEFT 0x04 // 光标左移,显示不移动
#define LCD_DIS_MODE_LEFT 0x07 // AC自增,画面左移
#define LCD_DIS_MODE_RIGHT 0X05 // AC自增,画面右移
/*光标开关控制*/
#define LCD_DIS_CUR_BLK_ON 0x0f // 显示开,光标开,光标闪烁
#define LCD_DIS_CUR_ON 0x0e // 显示开,光标开,光标不闪烁
#define LCD_DIS_ON 0x0c // 显示开,光标关,光标不闪烁
#define LCD_DIS_OFF 0x08 // 显示关,光标关,光标不闪烁
/*光标、显示移动*/
#define LCD_CUR_MOVE_LEFT 0x10 // 光标左移
#define LCD_CUR_MOVE_RIGHT 0x14 // 光标右移
#define LCD_DIS_MOVE_LEFT 0x18 // 显示左移
#define LCD_DIS_MOVE_RIGHT 0x1c // 显示右移
/**
LCD1602忙碌状态不会接收新指令,因此在发送新指令前先检测是否忙碌。
判断LCD1602_Busy变量的值为低电平则为不忙。
*/
void LCD1602_TestBusy(void){
LCD1602_DB0_DB7 = 0xff; //将数据引脚置为高电平
LCD1602_RS = 0; // 指令状态
LCD1602_RW = 1; // 读状态
LCD1602_E = 1; // 打开LCD显示器读指令
while(LCD1602_Busy); //读取LCD1602_Busy(P1.7)为低电平则结束循环
LCD1602_E = 0; // 关闭LCD显示器读指令
}
/********************************************************************************************
// 写指令程序 //
// 向LCD1602写命令 本函数需要1个指令集的入口参数 //
/********************************************************************************************/
void LCD1602_WriteCMD(uint8 LCD1602_command) {
LCD1602_TestBusy();
//输入的命令赋值给LCD1602_DB0_DB7
LCD1602_DB0_DB7 = LCD1602_command;
LCD1602_RS = 0;
LCD1602_RW = 0;
LCD1602_E = 1;
LCD1602_E = 0;
}
/********************************************************************************************
// 写数据程序 //
// 向LCD1602写数据 //
/********************************************************************************************/
void LCD1602_WriteData(uint8 LCD1602_data){
LCD1602_TestBusy();
LCD1602_DB0_DB7 = LCD1602_data;
LCD1602_RS = 1;
LCD1602_RW = 0;
LCD1602_E = 1;
LCD1602_E = 0;
}
// LCD1602初始化
void LCD1602_Init(void){
LCD1602_WriteCMD(LCD_MODE_PIN8); // 显示模式设置:显示2行,每个字符为5*7个像素
LCD1602_WriteCMD(LCD_DIS_ON); // 显示开及光标设置:显示开,光标关
LCD1602_WriteCMD(LCD_CURSOR_RIGHT); //显示光标移动设置:文字不动,光标右移
LCD1602_WriteCMD(LCD_SCREEN_CLR); // 显示清屏
}
/*
输出字符串
x:数据地址
y:输出的行位置,第一行和第二行
str:输入字符串
*/
void print(uint8 x, uint8 y, uint8 *str){
if(0 == y){
LCD1602_WriteCMD(0x80 | x);
}
else{
// 第二行起始位置是0x40
LCD1602_WriteCMD(0x80 | (0x40+x));
}
while(*str != '\0'){
LCD1602_WriteData(*str++);
}
}
void main(){
unsigned char str[] = "Hello LCD 1602";
unsigned char str1[] = "Beyound Self";
LCD1602_Init();
print(0x00,0,str);
print(0x00,1,str1);
while(1);
}