作者:hackett
一、LCD1602簡介
LCD1602液晶顯示器是廣泛使用的一種字符型液晶顯示模塊。它是由字符型液晶顯示屏(LCD)、控制驅(qū)動主電路HD44780及其擴展驅(qū)動電路HD44100,以及少量電阻、電容元件和結(jié)構(gòu)件等裝配在PCB板上而組成。
LCD1602應用很廣泛,無論是各大電子公司的產(chǎn)品上還是各大高校電賽的比賽作品上都能看到它的身影,下面來細說一下怎么驅(qū)動這塊1602液晶屏。
二、LCD1602引腳
圖1:引腳說明
一、我們重點關(guān)注幾個引腳:
- 液晶顯示偏壓:VL對應原理圖V0引腳,作用是調(diào)整1602的顯示對比度,可外接電位器進行調(diào)節(jié)對比度,上圖原理圖接地引腳電壓為0這時候?qū)Ρ榷茸罡摺?/li>
- 數(shù)據(jù)/命令選擇端:RS對應原理圖RES引腳,引腳高電平:進行數(shù)據(jù)字節(jié)傳輸,引腳低電平:進行命令字節(jié)傳輸。
- 讀/寫選擇端:R/W對應原理圖R/W引腳,引腳高電平:對1602進行讀數(shù)據(jù),引腳低電平:對1602進行寫數(shù)據(jù),一般應用都是直接拉低只進行寫數(shù)據(jù)。
- 使能信號:E對應原理圖E引腳,該引腳上升沿代表對1602開始數(shù)據(jù)傳輸,下降沿代表數(shù)據(jù)傳輸結(jié)束。
- 背光控制:原理圖K+引腳,該引腳高電平:背光關(guān)閉,引腳低電平:背光打開。
二、我們只需要寫數(shù)據(jù)給1602顯示,只看寫操作時序:
2寫指令跟4寫數(shù)據(jù)對比可看出RW讀寫引腳為低電平,E為高電平,D0~D7為傳輸?shù)臄?shù)據(jù)是命令/數(shù)據(jù),RS數(shù)據(jù)/命令選擇端(高:數(shù)據(jù) , 低:命令)。
三、常用的寫指令如下,其他指令可去查1602的datasheet:
四、數(shù)據(jù)寫入CGRAM指令:
此指令可以自定義顯示一個字符,我們寫地址的絲毫應該是0x40+Address
三、LCD1602驅(qū)動(11腳)
51單片機跟STM32單片機的驅(qū)動基本一致主要是引腳的配置不怎么一樣,特別注意STM32驅(qū)動寫指令/數(shù)據(jù)GPIO_Write(GPIOA,(GPIO_ReadOutputData(GPIOA) & 0xff00) | cmd/data)為對電平的讀取再寫數(shù)據(jù),其他均與51驅(qū)動一致。
1、51單片機:LCD1602.h
#ifndef __LCD1602_H #define __LCD1602_H
#define LCD1602_BKL_ON 0 //背光開 #define LCD1602_BKL_OFF 1 //背光關(guān)
#define LCD1602_DB P2 //數(shù)據(jù)端口 D0~D7 sbit LCD_RES = P4^1; //1602的數(shù)據(jù)/指令選擇控制線 sbit LCD_EN = P4^2; //1602的使能控制線 sbit Lcd1602_light = P0^2; //背光引腳
/*****************************************************************************/ void LCD1602_Init(); void LCD1602_Clear();
void LCD1602_write_cmd(unsigned char cmd); void LCD1602_write_data(unsigned char date); void LCD1602_wtire_CGRAM();
void LCD1602_SetCursor(unsigned char x,unsigned char y); void LCD1602_ShowChar(unsigned char xpos,unsigned char ypos,unsigned char xsz); void LCD1602_ShowStr(unsigned char xpos,unsigned char ypos,char *p); void LCD1602_ShowNum(char x, char y, unsigned int num);
void LCD1602_BKLSet(unsigned char val); unsigned char LCD1602_BKLGet();
void Delay_ms(unsigned int nms); #endif
2、51單片機:LCD1602.h
#include "LCD1602.h"
/****************************************************************************** * 函數(shù)名稱:void Delay_ms(unsigned int nms) * * 函數(shù)功能:寫命令函數(shù) * * 輸入?yún)?shù): //nms為要延時的ms數(shù) * * 返回值 :無 * * 其他說明: * ******************************************************************************/ void Delay_ms(unsigned int nms) //@11.0592MHz{ unsigned char i, j; //用單片機小工具根據(jù)自己的單片機類型及晶振直接生成對應的延時函數(shù)即可 while(nms--) { i = 15; j = 90; do { while (--j); } while (--i); } } /****************************************************************************** * 函數(shù)名稱:void LCD1602_write_cmd(unsigned char cmd) * * 函數(shù)功能:寫命令函數(shù) * * 輸入?yún)?shù): cmd 命令 * * 返回值 :無 * * 其他說明: * ******************************************************************************/ void LCD1602_write_cmd(unsigned char cmd) { LCD1602_DB=cmd; LCD_RES=0; LCD_EN=1; Delay_ms(10); LCD_EN=0; } /****************************************************************************** * 函數(shù)名稱:void LCD1602_write_data(unsigned char date) * * 函數(shù)功能:寫數(shù)據(jù)函數(shù) * * 輸入?yún)?shù): date 數(shù)據(jù) * * 返回值 :無 * * 其他說明: * ******************************************************************************/
void LCD1602_write_data(unsigned char date) { LCD1602_DB=date; LCD_RES=1; LCD_EN=1; Delay_ms(10); LCD_EN=0; } /****************************************************************************** * 函數(shù)名稱:void LCD1602_Init(void) * * 函數(shù)功能:1602初始化函數(shù) * * 輸入?yún)?shù): 無 * * 返回值 :無 * * 其他說明: * ******************************************************************************/
void LCD1602_Init() { LCD1602_BKLSet(LCD1602_BKL_ON); //背光開啟 LCD1602_write_cmd(0x01); //顯示清屏 LCD1602_write_cmd(0x38); //顯示模式設(shè)置 LCD1602_write_cmd(0x0C); //顯示開及光標設(shè)置 LCD1602_write_cmd(0x06); //顯示光標移動位置 } /****************************************************************************** * 函數(shù)名稱:void LCD1602_Clear(void) * * 函數(shù)功能:1602清屏函數(shù) * * 輸入?yún)?shù): 無 * * 返回值 :無 * * 其他說明: * ******************************************************************************/ void LCD1602_Clear(){ LCD1602_write_cmd(0x01); }
/****************************************************************************** * 函數(shù)名稱:void LCD1602_BKLSet(unsigned char val) * * 函數(shù)功能:打開1602背光函數(shù) * * 輸入?yún)?shù): LCD1602_BKL_ON 開LCD1602_BKL_OFF 關(guān) * * 返回值 :無 * * 其他說明: * ******************************************************************************/ void LCD1602_BKLSet(unsigned char val){ Lcd1602_light = val; } /****************************************************************************** * 函數(shù)名稱:unsigned char LCD1602_BKLGet() * * 函數(shù)功能:獲取1602背光函數(shù) * * 輸入?yún)?shù):無 * * 返回值 : 0 開1 關(guān) * * 其他說明: * ******************************************************************************/ unsigned char LCD1602_BKLGet(){ return Lcd1602_light; } /****************************************************************************** * 函數(shù)名稱:void LCD1602_SetCursor(unsigned char x,unsigned char y) * * 函數(shù)功能:設(shè)置1602位置函數(shù) * * 輸入?yún)?shù):x 橫坐標 y 縱坐標 * * 返回值 : 無 * * 其他說明: * ******************************************************************************/ void LCD1602_SetCursor(unsigned char x,unsigned char y){ unsigned char addr; if(y==0) addr=0x00+x; else addr=0x40+x; LCD1602_write_cmd(addr | 0x80); } /****************************************************************************** * 函數(shù)名稱:void LCD1602_ShowNum(char x, char y, unsigned int num) * * 函數(shù)功能:指定位置顯示數(shù)字函數(shù) * * 輸入?yún)?shù):x 橫坐標 y 縱坐標 num 數(shù)字 * * 返回值 : 無 * * 其他說明: * ******************************************************************************/ void LCD1602_ShowNum(char x, char y, unsigned int num){ unsigned int i,j,k,l,n; i=num/10000; j=(num-10000*i)/1000; k=(num-10000*i-1000*j)/100; l=(num-10000*i-1000*j-100*k)/10; n=num%10; LCD1602_SetCursor(x,y); if(i!=0)LCD1602_write_data(i+0x30); if((i!=0)||(j!=0))LCD1602_write_data(j+0x30); if((i!=0)||(j!=0)||(k!=0))LCD1602_write_data(k+0x30); if((i!=0)||(j!=0)||(k!=0)||(l!=0))LCD1602_write_data(l+0x30); LCD1602_write_data(n+0x30); } /****************************************************************************** * 函數(shù)名稱:void LCD1602_ShowChar(unsigned char xpos,unsigned char ypos,char xsz) * * 函數(shù)功能:指定位置顯示字符函數(shù) * * 輸入?yún)?shù):xpos 橫坐標 ypos 縱坐標 xsz 字符 * * 返回值 : 無 * * 其他說明: * ******************************************************************************/ void LCD1602_ShowChar(unsigned char xpos,unsigned char ypos,char xsz) { ypos%=2; if(ypos==0) { LCD1602_write_cmd(0x80+xpos); } else { LCD1602_write_cmd(0x80+0x40+xpos); } LCD1602_write_data(xsz); } /****************************************************************************** * 函數(shù)名稱:void LCD1602_ShowStr(unsigned char xpos,unsigned char ypos,char *p) * * 函數(shù)功能:指定位置顯示字符串函數(shù) * * 輸入?yún)?shù):xpos 橫坐標 ypos 縱坐標 *p 字符串 * * 返回值 : 無 * * 其他說明: * ******************************************************************************/ void LCD1602_ShowStr(unsigned char xpos,unsigned char ypos,char *p){ if(ypos>1)return; while(*p!='\0') { LCD1602_ShowChar(xpos++,ypos,*p++); if(*p=='\n') { xpos=0; ypos++; p++; } } } unsigned char code code_Y[8]={0x11,0x0A,0x04,0x04,0x04,0x04,0x04,0x00};//類似Y的字模 /****************************************************************************** * 函數(shù)名稱:void LCD1602_wtire_CGRAM(void) * * 函數(shù)功能:自定義顯示字符函數(shù) * * 輸入?yún)?shù): 無 * * 返回值 : 無 * * 其他說明: * ******************************************************************************/ void LCD1602_wtire_CGRAM(){ unsigned char num; LCD1602_write_cmd(0x40); //對CGRAM第一個自定義字符操作,若是第二個則為0x48, //其次類推(上面有對頂?shù)年P(guān)系) for(num=0;num<8;num++) { LCD1602_write_data(code_Y[num]); } LCD1602_write_cmd(0x80); //規(guī)定顯示在第一行第一個位置 LCD1602_write_data(0x00); //顯示第一個自定義字符 (0x40對應第一個:0x00)
} /********************************************************************/
3、STM32:LCD1602.h
#ifndef __LCD1602_H #define __LCD1602_H
/***************************根據(jù)自己的硬件引腳做修改*****************************/ #define LCD_RS_Set() GPIO_SetBits( GPIOB, GPIO_Pin_12 )//1602的數(shù)據(jù)/指令選擇控制線 #define LCD_RS_Clr() GPIO_ResetBits( GPIOB, GPIO_Pin_12 )
#define LCD_RW_Set() GPIO_SetBits( GPIOB, GPIO_Pin_13 )//1602的讀寫控制線 #define LCD_RW_Clr() GPIO_ResetBits( GPIOB, GPIO_Pin_13 )
#define LCD_EN_Set() GPIO_SetBits( GPIOB, GPIO_Pin_14 )//1602的使能控制線 #define LCD_EN_Clr() GPIO_ResetBits( GPIOB, GPIO_Pin_14 )
#define DATAOUT( x ) GPIO_Write( GPIOA, x ) //1602的8條數(shù)據(jù)控制線
void GPIO_Configuration();
void LCD1602_Init();
void LCD1602_Wait_Ready();
void LCD1602_Write_Cmd( u8 cmd );
void LCD1602_Write_Dat( u8 data );
void LCD1602_ClearScreen();
void LCD1602_Set_Cursor( u8 x, u8 y );
void LCD1602_Show_Str( u8 x, u8 y, u8 *str );
#endif
4、STM32:LCD1602.c
#include "LCD1602.h" /****************************************************************************** * 函數(shù)名稱:void GPIO_Configuration() * * 函數(shù)功能:LCD1602引腳初始化 * * 輸入?yún)?shù):無 * * 返回值 :無 * * 其他說明: * ******************************************************************************/ /*******************根據(jù)自己的硬件引腳做修改*****************************************/ void GPIO_Configuration(){ GPIO_InitTypeDef GPIO_InitStructure; RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOB, ENABLE ); GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12 | GPIO_Pin_13 | GPIO_Pin_14; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;//選擇工作頻率 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;//設(shè)置工作模式 GPIO_Init( GPIOB, &GPIO_InitStructure );
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_3 | GPIO_Pin_4 | GPIO_Pin_5 | GPIO_Pin_6 | GPIO_Pin_7; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;//設(shè)置工作模式 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;//選擇工作頻率 GPIO_Init( GPIOA, &GPIO_InitStructure ); } /****************************************************************************** * 函數(shù)名稱:void LCD1602_Init() * * 函數(shù)功能:LCD1602初始化 * * 輸入?yún)?shù):無 * * 返回值 :無 * * 其他說明: * ******************************************************************************/ void LCD1602_Init(){ GPIO_Configuration(); //初始化引腳
LCD1602_Write_Cmd( 0x38 ); //顯示模式設(shè)置 delay_ms( 5 ); LCD1602_Write_Cmd( 0x0c ); //顯示開及光標設(shè)置 delay_ms( 5 ); LCD1602_Write_Cmd( 0x06 ); //顯示光標移動位置 delay_ms( 5 ); LCD1602_Write_Cmd( 0x01 ); //顯示清屏 delay_ms( 5 ); } /****************************************************************************** * 函數(shù)名稱:void LCD1602_Write_Cmd(u8 cmd) * * 函數(shù)功能:寫命令函數(shù) * * 輸入?yún)?shù): cmd 命令 * * 返回值 :無 * * 其他說明: * ******************************************************************************/ void LCD1602_Write_Cmd( u8 cmd ){ LCD_RS_Clr(); LCD_RW_Clr(); LCD_EN_Set();
GPIO_Write( GPIOA, (GPIO_ReadOutputData( GPIOA ) & 0xff00) | cmd );//對電平的讀取
DATAOUT( cmd ); delay_ms( 5 ); LCD_EN_Clr(); }
/****************************************************************************** * 函數(shù)名稱:void LCD1602_Write_Dat(u8 date) * * 函數(shù)功能:寫數(shù)據(jù)函數(shù) * * 輸入?yún)?shù): date 數(shù)據(jù) * * 返回值 :無 * * 其他說明: * ******************************************************************************/ void LCD1602_Write_Dat( u8 data ){ LCD_RS_Set(); LCD_RW_Clr(); LCD_EN_Set();
GPIO_Write( GPIOA, (GPIO_ReadOutputData( GPIOA ) & 0xff00) | data );//對電平的讀取
delay_ms( 5 ); LCD_EN_Clr(); }
/****************************************************************************** * 函數(shù)名稱:void LCD1602_ClearScreen() * * 函數(shù)功能:1602清屏函數(shù) * * 輸入?yún)?shù):無 * * 返回值 :無 * * 其他說明: * ******************************************************************************/ void LCD1602_ClearScreen(){ LCD1602_Write_Cmd( 0x01 ); }
/****************************************************************************** * 函數(shù)名稱:void LCD1602_Set_Cursor(u8 x, u8 y) * * 函數(shù)功能:設(shè)置1602位置函數(shù) * * 輸入?yún)?shù):x 橫坐標 y 縱坐標 * * 返回值 :無 * * 其他說明: * ******************************************************************************/ void LCD1602_Set_Cursor( u8 x, u8 y ){ u8 addr;
if ( y == 0 ) addr = 0x00 + x; else addr = 0x40 + x; LCD1602_Write_Cmd( addr | 0x80 ); }
/****************************************************************************** * 函數(shù)名稱:void LCD1602_Show_Str( u8 x, u8 y, u8 *str ) * * 函數(shù)功能:指定位置顯示字符串函數(shù) * * 輸入?yún)?shù):x 橫坐標 y 縱坐標 *str 字符串 * * 返回值 : 無 * * 其他說明: * ******************************************************************************/ void LCD1602_Show_Str( u8 x, u8 y, u8 *str ){ LCD1602_Set_Cursor( x, y ); while ( *str != '\0' ) { LCD1602_Write_Dat( *str++ ); } }
四、LCD1602 STM32驅(qū)動(6線)
LCD1602 的接口形式是并行的,它有 8 條數(shù)據(jù)線、3 條控制線。這樣就需要 11 條線來控制它的正常工作。雖然它還可以工作在 4 位數(shù)據(jù)線的形式,最精簡的形式是 6 條線。
我們可以用74HC595 進行串-并轉(zhuǎn)換,74HC595 是“串入并出”的移位寄存器芯片,它需要用 3 條線控制數(shù)據(jù)的輸入,才能正常的輸出 8 位數(shù)據(jù),總共6條線即可進行LCD1602的控制。
這里多用了一塊芯片但是省了5個IO口,對于某些項目單片機引腳不夠用的情況下可以應用上。
原理圖如下:
1、STM32:LCD1602.h
#ifndef __LCD1602_H #define __LCD1602_H //1602液晶指令/數(shù)據(jù)或選擇引腳 #define LCD_RS_PORT GPIOB #define LCD_RS_PIN GPIO_Pin_10
#define LCD_RS_0 GPIO_ResetBits(LCD_RS_PORT, LCD_RS_PIN) #define LCD_RS_1 GPIO_SetBits(LCD_RS_PORT, LCD_RS_PIN)
//1602液晶使能引腳 #define LCD_EN_PORT GPIOB #define LCD_EN_PIN GPIO_Pin_11 //PB11
#define LCD_EN_0 GPIO_ResetBits(LCD_EN_PORT, LCD_EN_PIN) #define LCD_EN_1 GPIO_SetBits(LCD_EN_PORT, LCD_EN_PIN)
//1602液晶數(shù)據(jù)端口 #define MOSIO PBout(0) #define R_CLK PCout(5) #define S_CLK PCout(4)
/*********************函數(shù)聲明*****************/ void LCD1602_Init(void); void LCD1602_Clear(void); void LCD1602_ShowStr(unsigned char xpos,unsigned char ypos,char *p); void LCD1602_BKLSet(unsigned char on); unsigned char LCD1602_BKLGet(void); void LCD1602_ShowLineStr(unsigned char xpos,unsigned char ypos,char *p); void LCD1602_ShowState(unsigned char Signal, unsigned char GprsState); /**********************************************/ #endif
2、STM32:LCD1602.c
#include "LCD1602.h" #include "delay.h"http://程序中的延時函數(shù)根據(jù)自己32單片機來就行
void hc595SendData(unsigned char sendVal){ unsigned char i; //從CPU中向595一位一位發(fā)送,595一位一位接收 for(i = 0; i 8; i++) { if((sendVal <0x80) MOSIO = 1; else MOSIO = 0; S_CLK = 0; S_CLK = 1;
} //CPU發(fā)送完后,R_CLK將數(shù)據(jù)并行輸出, //實現(xiàn)了只占用CPU一個輸出口就可以輸出8bit數(shù)據(jù) R_CLK = 0; R_CLK = 1;
}
void LCD1602_write_com(unsigned char com) { hc595SendData(com); LCD_RS_0; LCD_EN_0; delay_ms(10); LCD_EN_1; }
void LCD1602_write_data(unsigned char date) { hc595SendData(date); LCD_RS_1; LCD_EN_0; delay_ms(10); LCD_EN_1; }
void LCD1602_Init(void) { GPIO_InitTypeDef GPIO_InitStructure; RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOB | RCC_APB2Periph_GPIOC, ENABLE ); GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP; //推挽輸出 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_Pin = LCD_RS_PIN | LCD_EN_PIN | GPIO_Pin_0; GPIO_Init(GPIOB, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP; //推挽輸出 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4 | GPIO_Pin_5; GPIO_Init(GPIOC, &GPIO_InitStructure); LCD1602_write_com(0x01); LCD1602_write_com(0x38); LCD1602_write_com(0x0C);//開顯示,不需要光標 LCD1602_write_com(0x06); }
void LCD1602_Clear(void){ LCD1602_write_com(0x01); }
void LCD1602_ShowChar(unsigned char xpos,unsigned char ypos,char xsz) { ypos%=2; if(ypos==0) { LCD1602_write_com(0x80+xpos); } else { LCD1602_write_com(0x80+0x40+xpos); } LCD1602_write_data(xsz); }
void LCD1602_ShowLineStr(unsigned char xpos,unsigned char ypos,char *p){ unsigned char i=0; if(ypos>1 || xpos>=16)return; while(*p!='\0' && i<16 && xpos<16) { i++; LCD1602_ShowChar(xpos++,ypos,*p++); delay_us(500); } }
void LCD1602_ShowStr(unsigned char xpos,unsigned char ypos,char *p){ if(ypos>1)return; while(*p!='\0') { LCD1602_ShowChar(xpos++,ypos,*p++); if(*p=='\n')//當檢測到換行符時,進行換行檢測 { xpos=0; ypos++; p++; } } }
如果你覺得文章還不錯,記得"點贊關(guān)注"
關(guān)注我的微信公眾號【 加班猿 】可以獲取更多內(nèi)容
|