1.硬件设计
1.1.LCD1602介绍
1.2.原理图
2.软件设计
2.1.控制原理
2.2.控制时序
2.3.指令集
2.4.程序设计
3.知识点
3.1.宏定义
3.2.指针和数组
3.3.for语句
1.硬件设计
1.1.LCD1602介绍
- LCD1602是由字符型液晶显示屏(LCD)、控制驱动主电路HD44780及其扩展驱动电路HD44100和少量电阻、电容元件和结构件组装在一起PCB板上而成。
- LCD1602主要用于显示数字、字母、图形和少量自定义字符。2行16个字符,16个引脚,其中8个数据总线D0-D7,和RS、R/W、EN工作电压为5V,并且有字符对比度调整V0和背光源AK
- 关于LCD介绍工作原理、结构堆叠等,可参考以下链接:https://lishiyi.blog.csdn.net/article/details/124106767?spm=1001.2014.3001.5502
1.2.原理图
2.软件设计
- 硬件分析:分析原理图,了解每个引脚的作用,并配置引脚;
- 控制原理:单片机如何控制显示,显示在哪里,显示什么内容?
- 时序分析:执行内容是数据还是指令;是读还是写..?
- 指令集:执行过程中会涉及哪些指令?
- 实现逻辑:初始化、数据控制...
2.1.控制原理
- 通过控制DDRAM通过控制数据显示的位置CGRAM控制数据显示的内容;例如,在第一行第一列显示一个"A"字,就要向DDRAM的00H地址写入“A”字的代码 41H ;
- 搜索地址意味着在哪里显示数据。控制器内部有一个数据地址指针,可以访问所有80个字节RAM(LCD1602的实际显示只有32个字节),需要在哪里显示,写入相应的字节RAM地址映射图如下:
- 在 LCD 字模存储器固化在模块上,即CGROM (HD44780 内置了192 常用字符的字模)和 CGRAM(另外还有 8 可自定义的字符生成RAM);因此,可以通过以下字模关系表选择需要显示的数据
2.2.控制时序(写)
- :RS=L,RW=L,E=H,D0~D7=指令(有效);
- RS=H,RW=L,E=H,D0~D7=数据(有效);代码如下:
//*写数据,Data为要写入的数据 void LCD_WriteData(unsigned char Data) { LCD_RS=1;//RS高电平代表写数据而不是指令 LCD_RW=0;//RW低电平代表写数据,而不是读数据 LCD_DataPort=Data;//P0口代表要写的数据内容 LCD_E=1;//使能,高电平有效 LCD_Delay(); LCD_E=0;///使能,低电平截止 LCD_Delay(); }
2.3.指令集
2.4.程序设计
#include <REGX52.H> //*引脚定义 sbit LCD_RS=P2^6; sbit LCD_RW=P2^5; sbit LCD_E=P2^7; #define LCD_DataPort P0 //宏定义,直接将数据接口替换成P0接口 //*延时函数 void LCD_Delay() { unsigned char i, j; i = 2; j = 239; do { while (--j); } while (--i); } //*写指令,Command要写的指令 void LCD_WriteCommand(unsigned char Command) { LCD_RS=0;//RS低电平代表写指令而不是数据 LCD_RW=0;//RW低电平代表写指令,而不是读指令 LCD_DataPort=Command; LCD_E=1;//使能,高电平有效 LCD_Delay()///高度电平的使能转换过快,因此需要延迟 LCD_E=0;///使能,低电平截止 LCD_Delay(); } //*写数据,Data要写的数据 void LCD_WriteData(unsigned char Data) { LCD_RS=1;//RS高电平代表写数据而不是指令 LCD_RW=0;//RW低电平代表写数据,而不是读数据 LCD_DataPort=Data;//P0口代表要写的数据内容 LCD_E=1;//使能,高电平有效 LCD_Delay()///高度电平的使能转换过快,因此需要延迟 LCD_E=0;//使能,低电平截止 LCD_Delay(); } //*初始化 //*显示模式设置:0x三八、八位数据接口,两行显示5*7点阵 //*显示开关及光标设置:0x0C,显示开关、光标关、闪烁关 //*输入设置:0x06.数据读写操作后,光标自动加一,画面不动 //*清屏设置:0x01,清屏 void LCD_Init(void) { LCD_WriteCommand(0x38);//八位数据接口,两行显示,5*7点阵 LCD_WriteCommand(0x0C);//显示开关,光标关,闪烁关 LCD_WriteCommand(0x06);//数据读写操作后,光标自动加一,画面不动 LCD_WriteCommand(0x01);//清屏 } //*光标位置 void LCD_SetCursor(unsigned char Line,unsigned char Column) { if(Line==1) { LCD_WriteCommand(0x80|Column-1);//第1行,第N列,第一行的起点是0x00 } else { LCD_WriteCommand(0x80|Column-1 0x40);//第二行,N列,0x40是第二行的起始位置 } } //*显示字符 void LCD_ShowChar(unsigned char Line,unsiged char Column,unsigned char Char) { LCD_SetCursor(Line,Column);//DDRAM地址设置 LCD_WriteData(Char);//设置要写入的字符数据 } //*显示字符串 //*这里有用到指针,*String等效于String[],指针指向该字符组的第一个地址,依次显示出来,直到'\0'(结束标志位)的出现 void LCD_ShowString(unsigned char Line,unsigned char Column,unsigned char *String) { unsigned char i; LCD_SetCursor(Line,Column);//光标位置 for(i=0;String[i]!=0;i++) { LCD_WriteData(String[i]); } } //*次方函数 //*Y=0,返回值Result=1,相当于任何数字的0次方等于1 //*Y=2,for循环执行两次,Result=X*X=X^2 int LCD_Pow(int X,int Y) { unsigned char i; int Result=1; for(i=0;i<Y;i++) { Result*=X; } return Result; } //*显示无符号数字 //*如要显示123,其显示逻辑如下 //*123/10^2%10=1 //*123/10^1%10=2 //*123/10^0%10=3 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('0'+Number/LCD_Pow(10,i-1)%10); //*'0'相当于0x30,在Number...前面加上'0',目的就是和ASCII码表对应,显示出要显示的数字 } } //*显示有符号数字 void LCD_ShowsignedNum(unsigned char Line,unsigned char Column,int Number,unsigned char Length) { unsigned char i; unsigned int Number1; LCD_SetCursor(Line,Column); if(Number>=0) { LCD_WriteData('+'); Number1=Number;//数字大于0的时候,显示Number } else { LCD_WriteData('-'); Number1=-Number;//数字小于0的时候,显示-Number } for(i=Length;i>0;i--) { LCD_WriteData('0'+Number1/LCD_Pow(10,i-1)%10); } } //*显示16进制 void LCD_ShowHexNum(unsigned char Line,unsigned char Column,unsigned int Number,unsigned char Length) { unsigned char i; unsigned char SingleNumber; LCD_SetCursor(Line,Column);//光标位置 for(i=Length;i>0;i--) { SingleNumber=Number/LCD_Pow(16,i-1)%16; if(SingleNumber<10) { LCD_WriteData('0'+SingleNumber);//小于10显示数字 } else { LCD_WriteData('A'+SingleNumber-10); //大于等于10显示字母 } } } //*显示二进制 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('0'+Number/LCD_Pow(2,i-1)%2); } }
#ifndef __LCD1602_H__ #define __LCD1602_H__ //*以下是.h头文件需要调用的命令 void LCD_WriteCommand(unsigned char Command);//写指令 void LCD_WriteData(unsigned char Data);//写数据 void LCD_Init(void);//初始化 void LCD_ShowChar(unsigned char Line,unsigned char Column,unsigned char Char);//显示字符 void LCD_ShowString(unsigned char Line,unsigned char Column,unsigned char *String);//显示字符串 void LCD_ShowNum(unsigned char Line,unsigned char Column,unsigned int Number,unsigned char Length);//显示无符号数字 void LCD_ShowsignedNum(unsigned char Line,unsigned char Column,int Number,unsigned char Length);//显示有符号数字 void LCD_ShowHexNum(unsigned char Line,unsigned char Column,unsigned int Number,unsigned char Length);//显示16进制 void LCD_ShowBinNum(unsigned char Line,unsigned char Column,unsigned int Number,unsigned char Length);//显示二进制 #endif
#include <REGX52.H> #include"LCD1602.h" #include"DELAY.h" void main() { LCD_Init();//初始化 LCD_ShowChar(1,1,'A');//显示字符A LCD_ShowString(1,3,"ABC");//显示字符串ABC LCD_ShowNum(1,7,123,3);//显示无符号数字123 LCD_ShowsignedNum(1,11,-123,3);//显示有符号数字-123 LCD_ShowHexNum(2,1,0xA1,2);//显示16进制A1 LCD_ShowBinNum(2,4,0xA1,8);//显示二进制0xA1(10100001) LCD_ShowChar(2,13,0xDF);//显示字符° LCD_ShowString(1,16,"ABCDEFGHIJKLMN");//显示字符串A~N,超过16位显示区 while(1) { LCD_WriteCommand(0x18);//光标向左平移一个字符,但光标不动,移屏(流动字幕效果) Delay(1000);//防止光标移动速度过快,增加延时 } }
3.知识点
3.1.宏定义
- 是C语言提供的三种预处理功能的其中一种,这三种预处理包括:宏定义、文件包含、条件编译。
- 宏定义是替换,不做计算,也不做表达式求解。宏定义又称为宏代换、宏替换,简称“宏”。在 C 语言中,宏是产生内嵌代码的唯一方法。对于嵌入式系统而言,为了能达到性能要求,宏是一种很好的代替函数的方法。
- #DEFINE 标识符 字符串
- 掌握"宏"概念的关键是“换”,一切以换为前提、做任何事情之前先要换,准确理解之前就要“换”,即在对相关命令或语句的含义和功能作具体分析之前就要换。
//*引脚定义 sbit LCD_RS=P2^6; sbit LCD_RW=P2^5; sbit LCD_E=P2^7; #define LCD_DataPort P0 //宏定义,直接将数据接口替换成P0接口
3.2.指针与数组
引用一个数组元素,可以用以下两种方法:
- ,如
a[i]
形式;- ,如
*(a+i)
或*(p+i)
。其中 a 是数组名,p是指向数组元素的指针变量,其初值为p=a
;//*显示字符串 //*这里有用到指针,*String等效于String[],指针指向该字符组的第一个地址,依次显示出来,直到'\0'(结束标志位)的出现 unsigned char i; void LCD_ShowString(unsigned char Line,unsigned char Column,unsigned char *String) { unsigned char i; LCD_SetCursor(Line,Column);//光标位置 for(i=0;String[i]!=0;i++) { LCD_WriteData(String[i]); }
3.3.for语句
- 表达式1:是初始化步骤,只执行一次
- 表达式2:是控制表达式,控制循环的终止
- 表达式3:在每次循环的最后被执行。
- 执行步骤:首先执行表达式1进行初始化,然后判断表达式2的值是否为真,若为真,则执行循环体,然后执行表达式3;随后再次对表达式2的值进行判断,若为真,则再次执行循环体和表达式3,依次循环直到表达式2的值为0为止。
//*次方函数 //*Y=0,返回值Result=1,相当于任何数字的0次方等于1 //*Y=2,for循环执行两次,Result=X*X=X^2 int LCD_Pow(int X,int Y) { unsigned char i; int Result=1; for(i=0;i<Y;i++) { Result*=X; } return Result; }