51 microcontroller 4-wire concurrent IO port control 1602LCD

51 microcontroller 4-wire concurrent IO port control 1602LCD

1 Overview

This article introduces how the microcontroller uses 4 concurrent IO port data lines to control LCD display characters, saving 4 IO ports for the microcontroller.
The principle of using the 4 IO ports of the microcontroller to control the LCD is to split the original 1 byte 8-bit data into 2 readings and writes. First, read the high 4-bit data, and then read the low 4-bit data, achieving 4 IO ports to read 1 Bytes of data, control the 1602LCD display screen to display characters.

2. 4 IO ports control LCD

2.1.Principle

To control the LCD with 4 IO ports, you need to modify the code in the following locations to achieve it.

  • Busy detection function
    LCD1602_DB4_DB7pin assignment only needs to set the high 4 bits to 1, and the low 4 bits should be in their original state.
void LCD1602_TestBusy(void){
    
    
	LCD1602_DB4_DB7 = 0xf0;	//高4位IO口设置为1,低4位IO口保持原态
	LCD1602_RS = 0; // 指令状态
	LCD1602_RW = 1;	// 读状态
	LCD1602_E = 1;
	while(LCD1602_Busy);	//读取LCD1602_Busy(P1.7)为低电平则结束循环
	LCD1602_E = 0;	// 关闭LCD显示器读指令
}
  • Write instruction function
    uses 4 data lines to write 8-bit instructions, which needs to be divided into two writes. The first time the high 4-bit instruction is written by default, the second time the low 4-bit instruction is moved to the high 4 bits and written again, and the writing of one byte is completed twice.
void LCD1602_WriteCMD(uint8 LCD1602_command) {
    
     
	LCD1602_TestBusy();
	LCD1602_RS = 0;
	LCD1602_RW = 0;
	//输入的命令高4位赋值给LCD1602_DB4_DB7
	LCD1602_DB4_DB7 = LCD1602_command;
	DELAY_MS(1);
	LCD1602_E = 1;
	LCD1602_E = 0;
	//将命令低4位移到高四位供IO口读取
	LCD1602_DB4_DB7 = LCD1602_command << 4;
	DELAY_MS(1);
	LCD1602_E = 1;
	LCD1602_E = 0;
}
  • Write data function
    uses 4 data lines to write 8-bit data, which needs to be divided into two writes. The first time, the high 4-bit data is written by default, and the second time, the low 4-bit data is moved to the high 4-bits and written again. The writing of one byte is completed twice.
void LCD1602_WriteData(uint8 LCD1602_data){
    
     
	LCD1602_TestBusy();
	
	LCD1602_RS = 1;
	LCD1602_RW = 0;
	//写入高4位数据
	LCD1602_DB4_DB7 = LCD1602_data;
	DELAY_MS(1);
	LCD1602_E = 1;
	LCD1602_E = 0;
	//将低4位数据移到高4位IO口写入
	LCD1602_DB4_DB7 = LCD1602_data << 4;
	DELAY_MS(1);
	LCD1602_E = 1;
	LCD1602_E = 0;
}
  • Initialization function
    LCD1602_WriteCMD(LCD_MODE_PIN4);is set to 4-wire mode
void LCD1602_Init(void){
    
    
	// 设置4线并行口
	LCD1602_WriteCMD(LCD_MODE_PIN4);	// 显示模式设置:显示2行,每个字符为5*7个像素
	LCD1602_WriteCMD(LCD_DIS_ON); 	// 显示开及光标设置:显示开,光标关
	LCD1602_WriteCMD(LCD_CURSOR_RIGHT);		//显示光标移动设置:文字不动,光标右移
	LCD1602_WriteCMD(LCD_SCREEN_CLR);	// 显示清屏
}

2.2. Source code

#include <STC12C2052AD.H>
#include <string.h> 
typedef unsigned char uint8;
// 定义引脚
#define	LCD1602_DB4_DB7	P1		// 定义高4位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_DB4_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	// 显示右移

void DELAY_MS (unsigned int a){
    
    
	unsigned int i;
	while( --a != 0){
    
    
		for(i = 0; i < 600; i++);
	}
}

/**
LCD1602忙碌状态不会接收新指令,因此在发送新指令前先检测是否忙碌。
判断LCD1602_Busy变量的值为低电平则为不忙。
*/
void LCD1602_TestBusy(void){
    
    
	LCD1602_DB4_DB7 = 0xf0;	//高4位IO口设置为1,低4位IO口保持原态
	LCD1602_RS = 0; // 指令状态
	LCD1602_RW = 1;	// 读状态
	LCD1602_E = 1;
	while(LCD1602_Busy);	//读取LCD1602_Busy(P1.7)为低电平则结束循环
	LCD1602_E = 0;	// 关闭LCD显示器读指令
}


/********************************************************************************************
// 写指令程序 //
// 向LCD1602写命令 本函数需要1个指令集的入口参数 //
/********************************************************************************************/
void LCD1602_WriteCMD(uint8 LCD1602_command) {
    
     
	LCD1602_TestBusy();
	LCD1602_RS = 0;
	LCD1602_RW = 0;
	//输入的命令高4位赋值给LCD1602_DB4_DB7
	LCD1602_DB4_DB7 = LCD1602_command;
	DELAY_MS(1);
	LCD1602_E = 1;
	LCD1602_E = 0;
	//将命令低4位移到高四位供IO口读取
	LCD1602_DB4_DB7 = LCD1602_command << 4;
	DELAY_MS(1);
	LCD1602_E = 1;
	LCD1602_E = 0;
}
/********************************************************************************************
// 写数据程序 //
// 向LCD1602写数据 //
/********************************************************************************************/
void LCD1602_WriteData(uint8 LCD1602_data){
    
     
	LCD1602_TestBusy();
	
	LCD1602_RS = 1;
	LCD1602_RW = 0;
	//写入高4位数据
	LCD1602_DB4_DB7 = LCD1602_data;
	DELAY_MS(1);
	LCD1602_E = 1;
	LCD1602_E = 0;
	//将低4位数据移到高4位IO口写入
	LCD1602_DB4_DB7 = LCD1602_data << 4;
	DELAY_MS(1);
	LCD1602_E = 1;
	LCD1602_E = 0;
}


// LCD1602初始化
void LCD1602_Init(void){
    
    
	// 设置4线并行口
	LCD1602_WriteCMD(LCD_MODE_PIN4);	// 显示模式设置:显示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 code str[] = "Hello LCD 1602";
	unsigned char code str1[] = "ABCDEFGHIGKLMNOP";
	LCD1602_Init();
	print(0,0,str);
	print(0,1,str1);
	while(1);
}

Guess you like

Origin blog.csdn.net/m0_38039437/article/details/135070492