目錄
LCD1602顯示屏介紹
LCD1602(Liquid Crystal Display)液晶顯示屏是一種字符型液晶顯示模塊,可以顯示ASCII碼的標准字符和其它的一些內置特殊字符,還可以有8個自定義字符
顯示容量:16×2個字符,每個字符為5*7點陣
引腳介紹
內部結構框圖
存儲器
DDRAM儲存器地址
/**
* @brief LCD1602設置光標位置(將行,列轉換為地址)
* @param Line 行位置,范圍:1~2
* @param Column 列位置,范圍:1~16(Column-1)
* @retval 無
*/
//DB7置1進行DDRAM設置
void LCD_SetCursor(unsigned char Line,unsigned char Column)
{
if(Line==1)
{
LCD_WriteCommand(0x80|(Column-1));//00H,01H,,,27H
}
else if(Line==2)
{
LCD_WriteCommand(0x80|(Column-1+0x40));//40H,41H,,,67H
}
}
CGRAM與 CGROM的地址
時序介紹
賦值數據的時候直接將16進制數據賦值給P^0端口即可,不必和之前的I2C以及單線通信一樣,用“&”一位一位的移位賦值。
LCD1602快捷指令
常用的指令主要是,移屏,光標移動(常用的已經用紅色標識)
LCD1602指令操作流程:
初始化:
發送指令0x38 //八位數據接口,兩行顯示,5*7點陣
發送指令0x0C //顯示開,光標關,閃爍關
發送指令0x06 //數據讀寫操作后,光標自動加一,畫面不動
發送指令0x01 //清屏
#include <REGX52.H>
//引腳配置:
sbit LCD_RS=P2^6;
sbit LCD_RW=P2^5;
sbit LCD_EN=P2^7;
#define LCD_DataPort P0
//函數定義:
/**
* @brief LCD1602延時函數,12MHz調用可延時1ms
* @param 無
* @retval 無
*/
void LCD_Delay()
{
unsigned char i, j;
i = 2;
j = 239;
do
{
while (--j);
} while (--i);
}
/**
* @brief LCD1602初始化函數
* @param 無
* @retval 無
*/
void LCD_Init()
{
LCD_WriteCommand(0x38);//八位數據接口,兩行顯示,5*7點陣
LCD_WriteCommand(0x0c);//顯示開,光標關,閃爍關
LCD_WriteCommand(0x06);//數據讀寫操作后,光標自動加一,畫面不動
LCD_WriteCommand(0x01);//光標復位,清屏
}
顯示字符:
發送指令0x80|AC //設置光標位置
發送數據 //發送要顯示的字符數據
發送數據 //發送要顯示的字符數據
/**
* @brief LCD1602寫命令
* @param Command 要寫入的命令
* @retval 無
*/
void LCD_WriteCommand(unsigned char Command)
{
LCD_RS=0;
LCD_RW=0;
LCD_DataPort=Command;
LCD_EN=1;
LCD_Delay();
LCD_EN=0;
LCD_Delay();
}
/**
* @brief LCD1602寫數據
* @param Data 要寫入的數據
* @retval 無
*/
void LCD_WriteData(unsigned char Data)
{
LCD_RS=1;
LCD_RW=0;
LCD_DataPort=Data;
LCD_EN=1;
LCD_Delay();
LCD_EN=0;
LCD_Delay();
}
字符、字符串的顯示
字符:根據一定規則建立的數字到字符的映射(ASCII碼表)
例如:0x21=’!’,0x41=’A’,0x00=’\0’
定義方法:char x=‘A’;(等效於char x=0x41;)
字符數組:存儲字符變量的一個數組
定義方法:char y[]={’A’, ’B’, ’C’};
(等效於char y[]={0x41,0x42,0x43}; )
字符串:在字符數組后加一個字符串結束標志,本質上是字符數組
定義方法:char z[]=”ABC”;(等效於char z[]={’A’, ’B’, ’C’, ’\0’};)
從上面的解釋我們也發現了,在字符數組與字符串的區別在與兩者等價於帶有花括號的形式時,后者系統會自動補 ’\0’而前者不會。所以我們在設計顯示字符串的函數時就可以遍歷數組,最后以’\0’為標志停止循環即可
/**
* @brief 在LCD1602指定位置開始顯示所給字符串
* @param Line 起始行位置,范圍:1~2
* @param Column 起始列位置,范圍:1~16
* @param String 要顯示的字符串
* @retval 無
*/
void LCD_ShowString(unsigned char Line,unsigned char Column,char *String)
//用指針傳遞數組的首地址
{
unsigned char i;
LCD_SetCursor(Line,Column);
for(i=0; String[i]!='\0'; i++)//字符串在字符數組后面加上一個字符串結束的標志
{
LCD_WriteData(String[i]);//在模式設置的時候,光標會自動移動
}
}
但是對於一些特殊的符號,比如說單引號,在應用的時候,計算機可能不知道到底哪個單引號和哪個單引號是一對的,從而報錯。這時候就要用到轉譯符號
各種進制的數字顯示
在LCD1602上顯示十進制數字
通過之前字符顯示的學習,我們可以觸類旁通的聯想到:把一個多位數字的每一位拆分出來,然后轉化為字符的形式進行顯示(我們在CGRAM與 CGROM的地址中發現,相應的數字確實要加上‘0’才能顯示,也進一步驗證了我們的猜想)
/**
* @brief 返回值=X的Y次方
*/
int LCD_Pow(int X,int Y)
{
unsigned char i;
int Result=1;//解決Y=0的情況
for(i=0;i<Y;i++)
{
Result*=X;
}
return Result;
}
/**
* @brief 在LCD1602指定位置開始顯示所給數字
* @param Line 起始行位置,范圍:1~2
* @param Column 起始列位置,范圍:1~16
* @param Number 要顯示的數字,范圍:0~65535
* @param Length 要顯示數字的長度,范圍:1~5
* @retval 無
*/
void LCD_ShowNum(unsigned char Line,unsigned char Column,unsigned int Number,unsigned char Length)
{
unsigned char i;
LCD_SetCursor(Line,Column);
for(i=Length;i>0;i--)
{
LCD_WriteData(Number/LCD_Pow(10,i-1)%10+'0');
}//將數字表示為ASCLL表的形式,原因是(子模庫)中是以ASCLL表的形式對應
}
我們也看到了,這個Number只能最大顯示65535,那么如果我們想顯示更大的數呢:實現的思路和之前定時器高位低位賦值相同。設高位為Number1,低位為Number2他們共同構成Number
那么在第一個顯示函數上Number1=(Number/65535),在第二個顯示函數上Number2=(Number%65535)這樣就可以顯示大於65535的數。
在LCD1602上顯示十六進制數字
和顯示十進制數字的方法大致相同,只是十六進制的每一位要判斷是否大於10,大於10就用0~9的阿拉伯數字表示,大於10就用A,B,C,D,E,F來表示
/**
* @brief 在LCD1602指定位置開始以十六進制顯示所給數字
* @param Line 起始行位置,范圍:1~2
* @param Column 起始列位置,范圍:1~16
* @param Number 要顯示的數字,范圍:0~0xFFFF
* @param Length 要顯示數字的長度,范圍:1~4
* @retval 無
*/
void LCD_ShowHexNum(unsigned char Line,unsigned char Column,unsigned int Number,unsigned char Length)
{
unsigned char i,SingleNumber;
LCD_SetCursor(Line,Column);
for(i=Length;i>0;i--)
{
SingleNumber=Number/LCD_Pow(16,i-1)%16;//和10進制不一樣的是,16進制數除16求余16得到不同位
if(SingleNumber<10)
{
LCD_WriteData(SingleNumber+'0');
}
else//10以上顯示的是ABCDEF,所以要先減去10
{
LCD_WriteData(SingleNumber-10+'A');
}
}
}
在LCD1602上顯示二進制數字
和顯示十進制數字的方法大致相同,只是進制為每2進1
/**
* @brief 在LCD1602指定位置開始以二進制顯示所給數字
* @param Line 起始行位置,范圍:1~2
* @param Column 起始列位置,范圍:1~16
* @param Number 要顯示的數字,范圍:0~1111 1111 1111 1111(注意在c語言中不能直接寫2進制數據,所以寫16進制替換)
* @param Length 要顯示數字的長度,范圍:1~16
* @retval 無
*/
void LCD_ShowBinNum(unsigned char Line,unsigned char Column,unsigned int Number,unsigned char Length)
{
unsigned char i;
LCD_SetCursor(Line,Column);
for(i=Length;i>0;i--)
{
LCD_WriteData(Number/LCD_Pow(2,i-1)%2+'0');//和10進制不一樣的是,2進制數除2求余2得到不同位
}
}
綜合上述,將代碼整合在一起有:
#include <REGX52.H>
//引腳配置:
sbit LCD_RS=P2^6;
sbit LCD_RW=P2^5;
sbit LCD_EN=P2^7;
#define LCD_DataPort P0
//函數定義:
/**
* @brief LCD1602延時函數,12MHz調用可延時1ms
* @param 無
* @retval 無
*/
void LCD_Delay()
{
unsigned char i, j;
i = 2;
j = 239;
do
{
while (--j);
} while (--i);
}
/**
* @brief LCD1602寫命令
* @param Command 要寫入的命令
* @retval 無
*/
void LCD_WriteCommand(unsigned char Command)
{
LCD_RS=0;
LCD_RW=0;
LCD_DataPort=Command;
LCD_EN=1;
LCD_Delay();
LCD_EN=0;
LCD_Delay();
}
/**
* @brief LCD1602寫數據
* @param Data 要寫入的數據
* @retval 無
*/
void LCD_WriteData(unsigned char Data)
{
LCD_RS=1;
LCD_RW=0;
LCD_DataPort=Data;
LCD_EN=1;
LCD_Delay();
LCD_EN=0;
LCD_Delay();
}
/**
* @brief LCD1602設置光標位置
* @param Line 行位置,范圍:1~2
* @param Column 列位置,范圍:1~16
* @retval 無
*/
void LCD_SetCursor(unsigned char Line,unsigned char Column)
{
if(Line==1)
{
LCD_WriteCommand(0x80|(Column-1));
}
else if(Line==2)
{
LCD_WriteCommand(0x80|(Column-1+0x40));
}
}
/**
* @brief LCD1602初始化函數
* @param 無
* @retval 無
*/
void LCD_Init()
{
LCD_WriteCommand(0x38);//八位數據接口,兩行顯示,5*7點陣
LCD_WriteCommand(0x0c);//顯示開,光標關,閃爍關
LCD_WriteCommand(0x06);//數據讀寫操作后,光標自動加一,畫面不動
LCD_WriteCommand(0x01);//光標復位,清屏
}
/**
* @brief 在LCD1602指定位置上顯示一個字符
* @param Line 行位置,范圍:1~2
* @param Column 列位置,范圍:1~16
* @param Char 要顯示的字符
* @retval 無
*/
void LCD_ShowChar(unsigned char Line,unsigned char Column,char Char)
{
LCD_SetCursor(Line,Column);
LCD_WriteData(Char);
}
/**
* @brief 在LCD1602指定位置開始顯示所給字符串
* @param Line 起始行位置,范圍:1~2
* @param Column 起始列位置,范圍:1~16
* @param String 要顯示的字符串
* @retval 無
*/
void LCD_ShowString(unsigned char Line,unsigned char Column,char *String)
{
unsigned char i;
LCD_SetCursor(Line,Column);
for(i=0;String[i]!='\0';i++)
{
LCD_WriteData(String[i]);
}
}
/**
* @brief 返回值=X的Y次方
*/
int LCD_Pow(int X,int Y)
{
unsigned char i;
int Result=1;
for(i=0;i<Y;i++)
{
Result*=X;
}
return Result;
}
/**
* @brief 在LCD1602指定位置開始顯示所給數字
* @param Line 起始行位置,范圍:1~2
* @param Column 起始列位置,范圍:1~16
* @param Number 要顯示的數字,范圍:0~65535
* @param Length 要顯示數字的長度,范圍:1~5
* @retval 無
*/
void LCD_ShowNum(unsigned char Line,unsigned char Column,unsigned int Number,unsigned char Length)
{
unsigned char i;
LCD_SetCursor(Line,Column);
for(i=Length;i>0;i--)
{
LCD_WriteData(Number/LCD_Pow(10,i-1)%10+'0');
}
}
/**
* @brief 在LCD1602指定位置開始以有符號十進制顯示所給數字
* @param Line 起始行位置,范圍:1~2
* @param Column 起始列位置,范圍:1~16
* @param Number 要顯示的數字,范圍:-32768~32767
* @param Length 要顯示數字的長度,范圍:1~5(不包含符號的長度)
* @retval 無
*/
void LCD_ShowSignedNum(unsigned char Line,unsigned char Column,long Number,unsigned char Length)
{
unsigned char i;
unsigned int Number1;
LCD_SetCursor(Line,Column);
if(Number>=0)
{
LCD_WriteData('+');
Number1=Number;
}
else
{
LCD_WriteData('-');
Number1=-Number;
}
for(i=Length;i>0;i--)
{
LCD_WriteData(Number1/LCD_Pow(10,i-1)%10+'0');
}
}
/**
* @brief 在LCD1602指定位置開始以十六進制顯示所給數字
* @param Line 起始行位置,范圍:1~2
* @param Column 起始列位置,范圍:1~16
* @param Number 要顯示的數字,范圍:0~0xFFFF
* @param Length 要顯示數字的長度,范圍:1~4
* @retval 無
*/
void LCD_ShowHexNum(unsigned char Line,unsigned char Column,unsigned int Number,unsigned char Length)
{
unsigned char i,SingleNumber;
LCD_SetCursor(Line,Column);
for(i=Length;i>0;i--)
{
SingleNumber=Number/LCD_Pow(16,i-1)%16;
if(SingleNumber<10)
{
LCD_WriteData(SingleNumber+'0');
}
else
{
LCD_WriteData(SingleNumber-10+'A');
}
}
}
/**
* @brief 在LCD1602指定位置開始以二進制顯示所給數字
* @param Line 起始行位置,范圍:1~2
* @param Column 起始列位置,范圍:1~16
* @param Number 要顯示的數字,范圍:0~1111 1111 1111 1111
* @param Length 要顯示數字的長度,范圍:1~16
* @retval 無
*/
void LCD_ShowBinNum(unsigned char Line,unsigned char Column,unsigned int Number,unsigned char Length)
{
unsigned char i;
LCD_SetCursor(Line,Column);
for(i=Length;i>0;i--)
{
LCD_WriteData(Number/LCD_Pow(2,i-1)%2+'0');
}
}