追求以通俗的语言让小白可以更容易上手学单片机,在此同时巩固知识(很多图片来自江科大和普中,作者也是学这个来的,只是通过自己的语言想把它复述出来)。
玩单片机几天了,想要玩一下显示屏,但不知道叫什么,怎么操作?
LCD1602介绍
有同学在问,学了几个单片机设计了,什么时候有那种显示屏显示东西的来玩玩(毕竟兴趣是最好的老师)。本期就来介绍一个简单的显示屏设计--LCD1602
如图为LCD显示屏,那为什么叫1602?--是因为其显示容量为16X2(16列2行)个字符,因此称为LCD1602,
而由于这个模块的字符点阵容量及其他原因限制,不能显示汉字和其他复杂的表情符号,只能显示数字,英文及一些标点符号
LCD1602硬件内部
引脚图
其引脚图如下
简单介绍一下这些引脚,
VO:是一个旋钮,外接的是电位器(相当于滑动变阻器),可以控制LCD的对比度,太低的话显示文字会很不明显,一般控制在一半。
RS:1为选择数据,即所显示的数据,可以写入,读取等;0为指令操作,可以控制清屏,光标位置
RW:1为读,即把LCD显示的数据读取,不过一般显示的数据,都是自己已有的,所以不会用到读;0为写入数据,即把数据显示在LCD上,一般都置0
E:使能,这里可以说是时序概念的初用。E相当于时钟线CLK,当为高电平,则八个引脚所储存的数据有效,可以用(显示),当下降沿时,数据则无效,可以执行其他命令操作。
其他的见字可懂。
VO如上图,当逆时针旋转时,对比度会下降,当顺时针旋转时,对比度会上升
使能为上图
内部结构图
PS:我们可以看到该模块有16列2行显示数据,但是实际有40列2行,其他24行没有在这外表中,但是可以用移动的方式,将其他24列的数据展示出来,后面有机会会将这个功能实现出来。
如何利用LCD1602实现我想要的显示?
封装
注意这个点阵5X7--说明了显示屏上的字符跟数码管一样,都是好几个引脚以高低电平形式构成的(也就是说,想显示一个字符,必须经过一定的处理才能实现);但是,如果我每次想存一个字符,就得0x??地去设置,效率会很低的,因此设计者在设计这个模块时就附了一个字模库,基本上能实现的字符在里面都有,都封装好了的,在里面调用即可,省去开发者很多设置的时间精力。
封装思路
读者:我也知道要封装,那从哪开始,怎么弄嘞?
回答:
1.明确要干嘛:我们要实现封装函数使得LCD能显示某种类型的数据(数字,字符等)
2.我们要利用引脚的功能,尤其是使能端(时序)来控制初始化、数据的获取,数据的显示及其他功能
3.查该芯片的中文文档,查什么功能,对应什么操作(这个芯片最重要的是操作RS,RW,E三个端)
比如写功能
封装代码
主配置
#include <REGX52.H>
//引脚配置:
sbit LCD_RS=P2^6;
sbit LCD_RW=P2^5;
sbit LCD_EN=P2^7;
#define LCD_DataPort P0//将八个引脚数据输入端同时控制
1.写数据
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();//必须最好给个延时函数,避免数据的收发有延迟
}
2.写指令
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();//必须最好给个延时函数,避免数据的收发有延迟
}
比如这个指令
如果你在做项目,下面这个指令图表一定是你有利的助手!
单单这些不够吧?来个案例试试!
小案例
封装LCD1602并实现输入数据,就显示数据 1.初始化
通常什么用什么模块,都会有初始化函数,配置一些通用的高低电平设定
想一想,这里的初始化应该 发送什么指令?
1.功能设定,数据接口,两行显示有效,5*7点阵
2.显示开,关掉开关和闪烁
3.数据读完操作后,光标自动加一,画面不动
4.清屏(清除遗留)
代码如下
void LCD_Init()
{
LCD_WriteCommand(0x38);//八位数据接口,两行显示,5*7点阵
LCD_WriteCommand(0x0c);//显示开,光标关,闪烁关
LCD_WriteCommand(0x06);//数据读写操作后,光标自动加一,画面不动
LCD_WriteCommand(0x01);//光标复位,清屏
}
2.显示字符 显示字符=写入数据(第几行第几列,字符只有一个,所以不用控制长度,传一次就可以)
void LCD_ShowChar(unsigned char Line,unsigned char Column,char Char)
{
LCD_SetCursor(Line,Column);
LCD_WriteData(Char);
}
主函数调用
LCD_ShowChar(2,1,'A');或者A 可以换成其阿斯康码--0x41(其他的自行百度)
3.显示字符串
void LCD_ShowString(unsigned char Line,unsigned char Column,char *String)//因为c
中只能传指针或者数组的首地址,所以你必须用循环一个一个遍历输入
{
unsigned char i;
LCD_SetCursor(Line,Column);
for(i=0;String[i]!='\0';i++)
{
LCD_WriteData(String[i]);
}
}
4.显示数字 显示数字=写入数据+执行显示(第几行,第几列,长度) 重点:数字怎么一个一个取到并写入呢
显示数字
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');
}
}
获得动态除数
int LCD_Pow(int X,int Y)
{
unsigned char i;
int Result=1;
for(i=0;i<Y;i++)
{
Result*=X;
}
return Result;
}
其他的网上查吧哈哈,功能性不强
主函数
#include <REGX52.H>
#include "LCD1602.h"
int a;int b;int c;
void main(){
LCD_Init();
LCD_ShowChar(1,1,'A');
while(1){
LCD_ShowString(1,3,"KK");
LCD_ShowSignedNum(2,5,-55,2);
LCD_ShowBinNum(1,5,0x7f,4);
LCD_ShowHexNum(2,9,0x06,4);
a=1;
b=2;
c=a+b;
LCD_ShowNum(2,1,c,3);
}
}
注意:初始化或者写死不变的数据可以在while外,动态的比如按键啊其他的可以放在while里! 写的貌似很多,不过有一定含量的搬运,但自己也巩固了一些知识。 期待与各位的交流!