【51单片机快速入门指南】6.1:LCD1602的八线、四线控制及自定义符号,完美兼容Proteus仿真
目錄
- 硬知識
- 顯示特性
- 接口定義
- 操作時序
- 寫操作時序
- 讀操作時序
- 寄存器
- 忙標志位BF
- 地址計數器(AC)
- 顯示數據寄存器(DDRAM)
- CGROM
- CGRAM
- 指令
- 清屏指令
- 光標歸位指令
- 進入模式設置指令
- 顯示開關控制指令
- 設定顯示屏或光標移動方向指令
- 功能設定指令
- 設定CGRAM地址指令
- 設定DDRAM地址指令
- 讀取忙信號或AC地址指令
- 數據寫入DDRAM或CGRAM指令
- 從 CGRAM或DDRAM讀出數據的指令
- 示例程序
- LCD1602.c
- LCD1602.h
- 測試程序
- main.c
- 實驗現象
- 仿真現象
- 八線制
- 四線制
普中51-單核-A2
STC89C52
Windows 10 20H2
Proteus 8 Frofessional v8.9 SP2
Keil uVision V5.29.0.0
PK51 Prof.Developers Kit Version:9.60.0.0
硬知識
???????摘自《通用1602 液晶顯示模塊使用手冊》、《液晶LCD1602(中文資料)—— ball 2010-5-13整理》
顯示特性
???????單5V電源電壓,低功耗、長壽命、高可靠性
???????內置192種字符(160個5x7點陣字符和32個5x10點陣字符)
???????具有64個字節的自定義字符RAM,可自定義8個5x8點陣字符或四個5x11點陣字符
???????顯示方式:STN、半透、正顯
???????驅動方式:1/16DUTY,1/5BIAS
???????視角方向:6點
???????背光方式:底部LED
???????通訊方式:4位或8位并口可選
???????標準的接口特性,適配MCS1和M6800系列MPU的操作時序。
接口定義
操作時序
寫操作時序
讀操作時序
寄存器
???????本模塊內部具有兩個8位寄存器:指令寄存器(IR)和地址寄存器(DR),用戶可以通過RS和R/W輸入信號的組合選擇指定的寄存器,進行相應的操作。下表中列出了組合選擇方式。
???????指令寄存器IR,內部存儲DDRAM和CGRAM中的數據顯示的指令代碼和地址信息,只能由MPU對其執行寫操作:
???????數據寄存器DR,內部暫時存儲MPU與模塊內部DDRAM和CGRAM之間的傳送數據,內部操作使DR與DDRAM或者CGRAM之間的數據傳送自動進行:
忙標志位BF
???????忙標志BF-1時,表明模塊正在進行內部操作,此時不接受任何外部指令和數據。當Rs-0,RW-1以及E為高電平時,BF輸出到DB7,每次操作之前最好先進行狀態字檢測,只有在確認BF-0之后,MPU才能訪問模塊
地址計數器(AC)
???????AC地址計數器是DDRAM或者CGRAM的地址指針。隨著IR中指令碼的寫入,指令碼中攜帶的地址信息自動送入AC中,并行做出AC作為DDRAM的地址指針還是CGRAM的地址指針的選擇。
???????AC具有自動加1或者減1的功能。當DR與DDRAM或者CGRAM之間完成一次數據傳后,AC自動會加1或減1,在RS=0,R/W=1且E為高電平時,AC的內容送到DB6 ~ DB0;
顯示數據寄存器(DDRAM)
???????DDRAM存儲顯示字符的字符碼,其容量的大小決定著模塊最多可顯示的字符數目.DDRAM地址與LCD顯示屏上的顯示位置的對應關系如下:
???????執行顯示移位操作時,對應的DDRAM地址也發生移位,以每行16個字符的顯示為例,移位前后的地址對應關系如下:
CGROM
???????HD44780內置了192個常用字符的字模,存于字符產生器CGROM(Character Generator ROM)中。在CGROM中,模塊已經以8位二進制數的形式,生成了5x8點陣的字符字模組字符字模(一個字符對應一組字模),字符字模是與顯示字符點陣相對應的8x8矩陣位圖數據(與點陣行相對應的矩陣行的高三位為“0"),同時每一組字符字模都有一個由其在CGROM中存放地址的高八位數據組成的字符碼對應。
CGRAM
???????另外還有8個允許用戶自定義的字符產生RAM,稱為CGRAM(Character Generator RAM)
???????就單屏結構的模塊而言,字符碼地址范圍為00H ~ FFH,其中00H ~ 07H字符碼與用戶在CGRAM中生成的自定義圖形字符的字模組相對應:至于雙屏或者多屏結構的模塊,由于各顯示屏結構部分的工作分別由獨立的使能信號E控制,因而各結構部分間字符的發生互不影響,每一顯示屏結構部分的字符碼地址范圍為00H ~ FFH,其中00H ~ 07H字符碼與用戶在CGRAM中生成的自定義圖形字符的字模組相對應。
指令
清屏指令
光標歸位指令
進入模式設置指令
顯示開關控制指令
設定顯示屏或光標移動方向指令
功能設定指令
設定CGRAM地址指令
設定DDRAM地址指令
讀取忙信號或AC地址指令
數據寫入DDRAM或CGRAM指令
從 CGRAM或DDRAM讀出數據的指令
示例程序
???????stdint.h見【51單片機快速入門指南】1:基礎知識和工程創建
LCD1602.c
#include <STC89C5xRC.H> #include "stdint.h" #include "LCD1602.h"//******************以下內容移植時需修改******************void delay_ms(int i);#define LCD1602_Port P0sbit RS_Pin = P2 ^ 6; //寄存器選擇位,RS位 sbit WR_Pin = P2 ^ 5; //讀寫選擇位,RW sbit EN_Pin = P2 ^ 7; //使能信號位,E位void LCD1602_Delay() { //主頻快就加延時 }void LCD1602_RS_H() {RS_Pin = 1; }void LCD1602_RS_L() {RS_Pin = 0; }void LCD1602_WR_H() {WR_Pin = 1; }void LCD1602_WR_L() {WR_Pin = 0; }void LCD1602_EN_H() {EN_Pin = 1; }void LCD1602_EN_L() {EN_Pin = 0; }void LCD1602_Write_Port(uint8_t Data) { #ifdef USE_4_PinLCD1602_Port &= 0x0F;LCD1602_Port |= (Data << 4); #elseLCD1602_Port = Data; #endif }uint8_t LCD1602_Read_Port() { #ifdef USE_4_Pin //4線下好像沒有意義return 0; #elsereturn LCD1602_Port; #endif }//******************以上內容移植時需修改******************unsigned char code LCD1602_DIY_Char[64]= //8個自定義字符 地址為0x00~0x07 {0x02,0x04,0x0F,0x12,0x0F,0x0A,0x1F,0x02,//年0x0F,0x09,0x0F,0x09,0x0F,0x09,0x09,0x11,//月0x1F,0x11,0x11,0x1F,0x11,0x11,0x1F,0x00,//日0x16,0x09,0x08,0x08,0x08,0x09,0x06,0x00,//℃0x00,0x11,0x0A,0x04,0x0A,0x11,0x00,0x00,//×0x00,0x04,0x00,0x1F,0x00,0x04,0x00,0x00,//÷0x00,0x0E,0x11,0x11,0x11,0x0A,0x1B,0x00,//Ω0x00,0x11,0x11,0x11,0x19,0x16,0x10,0x00,//μ };/***************************************************** 函數功能:判斷液晶模塊的忙碌狀態 返回值:1: 忙碌; 0: 不忙 ***************************************************/ uint8_t LCD1602_Busy_Test(void) { #ifdef USE_4_Pindelay_ms(2);return 0; #elsereturn ((LCD1602_Operation(0, 1, 0) & 0x80) && 1); #endif }uint8_t LCD1602_Operation(uint8_t Cmd_Data_Flag, uint8_t Write_Read_Flag, uint8_t Data) {if(Cmd_Data_Flag)LCD1602_RS_H();elseLCD1602_RS_L();if(Write_Read_Flag)LCD1602_WR_H();elseLCD1602_WR_L();LCD1602_Delay(); //給硬件反應時間if(Write_Read_Flag){LCD1602_EN_H();LCD1602_Delay(); //給硬件反應時間Data = LCD1602_Read_Port();}else{LCD1602_EN_L();LCD1602_Write_Port(Data);LCD1602_Delay(); //給硬件反應時間LCD1602_EN_H();LCD1602_Delay(); //給硬件反應時間}LCD1602_EN_L();return Data; }/***************************************************** 函數功能:將一個字節寫入液晶模塊 入口參數:Byte 字節, Cmd_Data_Flag 0為命令, 1為數據 ***************************************************/ void LCD1602_Write_Byte(uint8_t Byte, uint8_t Cmd_Data_Flag) {while (LCD1602_Busy_Test()); //如果忙就等待 #ifdef USE_4_PinLCD1602_Operation(Cmd_Data_Flag, 0, Byte >> 4);while (LCD1602_Busy_Test());LCD1602_Operation(Cmd_Data_Flag, 0, Byte & 0x0F); #elseLCD1602_Operation(Cmd_Data_Flag, 0, Byte); #endif }void LCD1602_DIY_Char_Init(void) {unsigned char i;LCD1602_Write_Byte(LCD1602_Set_CGRAM_Addr, 0); //開始寫入你要顯示的自定義字符、漢字代碼 for(i = 0; i < 64; i++){LCD1602_Write_Byte(LCD1602_DIY_Char[i], 1); //開始寫入你要顯示的自定義字符、漢字代碼} }/***************************************************** 函數功能:指定字符顯示的實際地址 入口參數:row 行:0或1 col:列 ***************************************************/ void LCD1602_Write_Address(uint8_t row, uint8_t col) {if(row)LCD1602_Write_Byte(col | 0xc0, 0); elseLCD1602_Write_Byte(col | 0x80, 0); //顯示位置的確定方法規定為"80H+地址碼x" }void LCD1602_Write_Str(char *Str) {while (*Str) //檢測字符串結束標志{LCD1602_Write_Byte(*Str++, 1); //發送當前字符} }/***************************************************** 函數功能:對LCD的顯示模式進行初始化設置 ***************************************************/ void LCD1602_Init(void) { #ifdef USE_4_PinLCD1602_Write_Byte(LCD1602_Cursor_Return, 0);LCD1602_Write_Byte(LCD1602_Config | LCD1602_4PIN | LCD1602_2Row | LCD1602_5X7, 0); #elseLCD1602_Write_Byte(LCD1602_Config | LCD1602_8PIN | LCD1602_2Row | LCD1602_5X7, 0); #endifLCD1602_Write_Byte(LCD1602_Display_Switch | Display_Enable | Cursor_Enable | Cursor_Blink_Enable, 0);LCD1602_Write_Byte(LCD1602_Cursor_Screen_Mode | Cursor_Right_Mode | Screen_Static_Mode, 0);LCD1602_DIY_Char_Init();LCD1602_Write_Byte(LCD1602_Clr, 0); //清屏幕指令,將以前的顯示內容清除 }LCD1602.h
#ifndef LCD1602_H_ #define LCD1602_H_#define USE_8_Pin //#define USE_4_Pin#ifdef USE_8_Pin #ifdef USE_4_Pin #error #endif #endif#define LCD1602_Clr 0x01 #define LCD1602_Cursor_Return 0x02#define LCD1602_Cursor_Screen_Mode 0x04#define Cursor_Left_Mode 0x00 #define Cursor_Right_Mode 0x02#define Screen_Static_Mode 0x00#define Screen_Right_Mode 0x01#define LCD1602_Display_Switch 0x08#define Display_Disable 0x00#define Display_Enable 0x04#define Cursor_Disable 0x00#define Cursor_Enable 0x02#define Cursor_Blink_Disable 0x00#define Cursor_Blink_Enable 0x01#define LCD1602_Cursor_Screen_Move 0x10#define Cursor_Left 0x00#define Cursor_Right 0x04#define Screen_Left 0x08#define Screen_Right 0x0c#define LCD1602_Config 0x20#define LCD1602_4PIN 0x00#define LCD1602_8PIN 0x10#define LCD1602_1Row 0x00#define LCD1602_2Row 0x08#define LCD1602_5X7 0x00#define LCD1602_5X10 0x04#define LCD1602_Set_CGRAM_Addr 0x40 #define LCD1602_Set_DDRAM_Addr 0x80uint8_t LCD1602_Busy_Test(void); uint8_t LCD1602_Operation(uint8_t Cmd_Data_Flag, uint8_t Write_Read_Flag, uint8_t Data); void LCD1602_Write_Byte(uint8_t Byte, uint8_t Cmd_Data_Flag); void LCD1602_Write_Address(uint8_t row, uint8_t col); void LCD1602_Write_Str(char *Str); void LCD1602_Init(void);#endif測試程序
四線和八線在LCD1602.h中控制
main.c
#include <STC89C5xRC.H> #include "intrins.h" #include "stdint.h" #include "LCD1602.h"void Delay1ms() //@11.0592MHz {unsigned char i, j;_nop_();i = 2;j = 199;do{while (--j);} while (--i); }void delay_ms(int i) {while(i--)Delay1ms(); }void main(void) {char i;LCD1602_Init();LCD1602_Write_Address(0, 0);LCD1602_Write_Str("0123456789ABCDEF");LCD1602_Write_Address(1, 0);for(i = 0; i < 8; ++i)LCD1602_Write_Byte(i, 1);while(1){ } }實驗現象
仿真現象
需要注意的是,Proteus仿真時存儲模式需設為Small才能正確顯示,很神秘。
八線制
四線制
總結
以上是生活随笔為你收集整理的【51单片机快速入门指南】6.1:LCD1602的八线、四线控制及自定义符号,完美兼容Proteus仿真的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 提供程序未返回 ProviderMani
- 下一篇: Ubuntu16.04中php如何切换版