51 マイクロコントローラー 4 線同時 IO ポート制御 1602LCD
1。概要
この記事では、マイクロコントローラーが 4 つの同時 IO ポート データ ラインを使用して LCD 表示文字を制御し、マイクロコントローラー用に 4 つの IO ポートを節約する方法を紹介します。
マイクロコントローラーの 4 つの IO ポートを使用して LCD を制御する原理は、元の 1 バイト 8 ビット データを 2 つの読み取りと書き込みに分割し、最初に上位 4 ビット データを読み取り、次に下位 4 ビットを読み取ります。データ、1 バイトのデータを読み取るための 4 つの IO ポートを実現し、1602LCD ディスプレイ画面を制御して文字を表示します。
2. 4つのIOポート制御LCD
2.1.原則
4 つの IO ポートで LCD を制御するには、次の場所のコードを変更して実現する必要があります。
- ビジー検出機能の
LCD1602_DB4_DB7
ピンアサインは上位 4 ビットを 1 に設定するだけでよく、下位 4 ビットは元の状態でなければなりません。
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显示器读指令
}
- 書き込み命令関数は
4 本のデータ ラインを使用して 8 ビット命令を書き込むため、2 回の書き込みに分割する必要があります。1 回目はデフォルトで上位 4 ビット命令が書き込まれ、2 回目は下位 4 ビット命令が上位 4 ビットに移動されて再度書き込まれ、1 バイトの書き込みが 2 回完了します。
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;
}
- データ書き込み機能は
4 本のデータ ラインを使用して 8 ビット データを書き込むため、2 回の書き込みに分割する必要があります。1 回目はデフォルトで上位 4 ビットのデータを書き込み、2 回目は下位 4 ビットのデータを上位 4 ビットに移動して再度書き込み、1 バイトの書き込みが 2 回完了します。
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_WriteCMD(LCD_MODE_PIN4);
4線式モードに設定されています
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. ソースコード
#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);
}