• 51单片机外设篇:点阵式LCD


    什么是LCD

    LCD(Liquid Crystal Display)俗称液晶。


    液晶是一种材料,液晶这种材料具有一种特点:可以在电信号的驱动下液晶分子进行旋转,旋转时会影响透光性,因此我们可以在整个液晶面板后面用白光照(称为背光),可以通过不同电信号让液晶分子进行选择性的透光,此时在液晶面板前面看到的就是亮和不亮的点,这就是LCD显示。

    被动发光和主动发光。

    有些显示器(譬如LED显示器、CRT显示器)自己本身会发光称为主动发光,有些(LCD)本身不会发光只会透光,需要背光的协助才能看起来是发光的,称为被动发光。
    液晶应用领域:电视机、电脑显示屏、手机显示屏、工业显示屏等····

    其他显示设备(LED、CRT、等离子、OLED)

    • CRT:阴极摄像管显示器。早期电视机的大屁股。寿命短,笨重;
    • 等离子显示:未成为主流;
    • OLED:目前未成为主流,但是很有市场潜力;
    • LED:(自发光)主要用在户外大屏幕;
    • LCD:目前是主流显示器(LCD易受光照影响,比如在亮处看不清屏幕)

    像素(pixel)
    像素就是组成图像的最基本元素,或者说显示中可以被控制的最小单位,整个图像就是由很多个像素组成的。
    像素可以被单独控制,控制其亮或不亮(单色屏)、或控制其亮度强弱(譬如亮50%,35%,这样叫灰度屏,以前的黑白电视机)、或控制其显示一定的颜色(这就是我们现在最常用的彩色显示屏)。
    总结:像素很重要,整个显示图像是由一个个的像素组成的。我们要在显示器上显示一个图像,就是把这个图像离散化成一个一个的点,然后把各个点的颜色对应在显示器的像素上。

    分辨率(resolution)
    整个屏幕的横向和纵向的像素个数就叫分辨率。
    屏幕尺寸和分辨率无关的。屏幕尺寸和分辨率和像素间距三者之间有关联。

    字模

    也就是字符、汉字或者图像所对应的亮灭信息的二进制数组,就和点阵中的显示源一致。

    字库

    所有字模的集合,就是字库。

    有些LCD带字库,有些不带字库。带字库的肯定比不带字库的要贵。

    驱动器&控制器&显存
    LCD实现功能一般需要以下几个模组:LCD面板+驱动器+控制器+显存。

    LCD面板是发光的实现;驱动器是提供足够的电压;控制器是控制哪些点亮哪些点不亮;显存是用来存放字模数据的,通过控制器,将显存中的数据通过亮或者不亮显示在液晶屏上。

    LCD控制器会自动从显存中读取像素数据传输给LCD驱动器。这个显示的过程不需要CPU的参与。我们只要把要显示的字符、汉字或者图像的像素数据丢到显存中,硬件就会自动响应,屏幕上就能自动看到显示的图像了。

    这里具体的过程自行百度,我们重点关注显存即可。

    LCD1602

    为什么叫1602?

    16x2,显示器显示2排,每排16个字符。

    能显示的字符数是32,但是像素数不是32,因为一个字符是由多个像素组成的。有可能一个字符是由5*7=35个像素组成的,也有可能是由6*8=48个像素组成的。但是我们不用去管,因为LCD1602内置了字库了。


    带ASCII码字库,不能显示中文。每个字符ASCLL对应一个字模,所有字模的集合就是字库。当我们想让LCD1602显示某个ASCII码字符时,只需要将这个字符对应的ASCII码发给LCD1602内部的控制器,控制器就会去查字库得到字模,然后将字模发给内部的驱动器去驱动LCD显示。

    内部结构如下:

    查看原理图

    引脚功能如下:

    引脚分为:数据接口(8)+控制接口(3)+VL(1)+电源地(4)


    LCD1602是并行接口,有8根数据线,所以一次同时传输8个bit位。

    地址映射:

    RAM地址范围(芯片范围是每行40个字符位,但是实际每行只用了15个)

    控制器接口

    基本读写时序:

    RS=1时,D0-D7上传输的是数据
    RS=0时,D0-D7上传输的是命令


    RW=1时,表示我们要读
    RW=0时,表示我们要写


    E=1时,表示使能        enable
    E=0时,表示禁止        disable

    读状态

    主要读STA7,以判断LCD1602当前是否处于忙状态。

    指令说明

    具体指令详见LCD1602的数据手册(注意1602的具体型号)

    列出重点指令:

    00001000    0x08    关闭显示
    00001100    0x0C    打开显示不显示光标
    00001111     0x0F    打开显示并且显示光标并且光标闪烁
    00000110    0x06    地址指针自动加1,整体屏幕不移动
    0x80+(0x00-0x0F)    第一行设置地址指针指令
    0x80+(0x40-0x4F)    第二行设置地址指针指令

    00000001     0x01    显示清屏
    00000010     0x02    回车

    初始化(复位)过程

    LCD读写没有什么时序要求,只需要使能相应的控制位,然后往对应的显存中放数据即可。

    代码实现

    1. #include
    2. // 对LCD1602的底层以及高层时序做封装
    3. // IO接口定义
    4. #define LCD1602_DB P0 //data bus 数据总线
    5. // 控制总线
    6. sbit LCD1602_RS = P2^6;
    7. sbit LCD1602_RW = P2^5;
    8. sbit LCD1602_EN = P2^7;
    9. /************ 低层时序 ********************************/
    10. void Read_Busy() //忙检测函数,判断bit7是0,允许执行;1禁止
    11. {
    12. unsigned char sta; //
    13. LCD1602_DB = 0xff;
    14. LCD1602_RS = 0;
    15. LCD1602_RW = 1;
    16. do
    17. {
    18. LCD1602_EN = 1;
    19. sta = LCD1602_DB;
    20. LCD1602_EN = 0; //使能,用完就拉低
    21. }while(sta & 0x80);
    22. }
    23. void Lcd1602_Write_Cmd(unsigned char cmd) //写命令
    24. {
    25. Read_Busy();
    26. LCD1602_RS = 0;
    27. LCD1602_RW = 0;
    28. LCD1602_DB = cmd;
    29. LCD1602_EN = 1;
    30. LCD1602_EN = 0;
    31. }
    32. void Lcd1602_Write_Data(unsigned char dat) //写数据
    33. {
    34. Read_Busy();
    35. LCD1602_RS = 1;
    36. LCD1602_RW = 0;
    37. LCD1602_DB = dat;
    38. LCD1602_EN = 1;
    39. LCD1602_EN = 0;
    40. }
    41. /************* 高层时序 ******************************/
    42. // 本函数用来设置当前光标位置,其实就是设置当前正在编辑的位置,
    43. // 其实就是内部的数据地址指针,其实就是RAM显存的偏移量
    44. // x范围是0-15,y=0表示上面一行,y=1表示下面一行
    45. void LcdSetCursor(unsigned char x,unsigned char y) //坐标显示
    46. {
    47. unsigned char addr;
    48. if(y == 0)
    49. addr = 0x00 + x;
    50. else
    51. addr = 0x40 + x;
    52. Lcd1602_Write_Cmd(addr|0x80);
    53. }
    54. // 函数功能是:从坐标(x,y)开始显示字符串str
    55. // 注意这个函数不能跨行显示,因为显存地址是不连续的
    56. // 其实我们可以封装出一个能够折行显示的函数的
    57. void LcdShowStr(unsigned char x,unsigned char y,unsigned char *str) //显示字符串
    58. {
    59. LcdSetCursor(x,y); //当前字符的坐标
    60. while(*str != '\0')
    61. {
    62. Lcd1602_Write_Data(*str++);
    63. }
    64. }
    65. // 初始化LCD,使之能够开始正常工作
    66. void InitLcd1602() //1602初始化
    67. {
    68. Lcd1602_Write_Cmd(0x38); //打开,5*8,8位数据
    69. //Lcd1602_Write_Cmd(0x0c); // 打开显示并且无光标
    70. Lcd1602_Write_Cmd(0x0f); // 打开显示并且光标闪烁
    71. Lcd1602_Write_Cmd(0x06);
    72. Lcd1602_Write_Cmd(0x01); //清屏
    73. }

    LCD12864(了解)

    128p*64p,注意不是字符而是pixel。

    没有内置字库,用户需要提供字模给LCD12864内部的控制器
    可以显示文字(英文、中文或其他文字)和图片(点阵图)

    查看原理图

    LCD12864共有20个引脚,其引脚具体功能如下表所示,由表可得LCD12864引脚组成为:

    • 8位数据传输端口(DB0-DB7);
    • 两个电源引脚(VCC,GND);
    • 两个电源背光引脚(BLK,BLA),控制LCD的背景亮度;
    • 一个VO引脚,外接一个上拉电阻(控制LCD12864的字符对比度,让字符更加的清晰可见);
    • RST复位引脚,低电平有效,此处直接接高电平;
    • 第16、17位空引脚,不用管;
    • 剩下的RS,RW,EN和PSB四个引脚则跟LCD12864的写入息息相关,通过PSB可以控制LCD12864跟单片机的通信方式,输入高电平,则LCD12864跟单片机的通信模式为并行通信,低电平则为串行通信。单片机对RS,RW,EN端口的写入控制,则可以控制LCD12864的数据传输模式,决定单片机写入LCD12864数据端口DB的是命令还是数据。写入命令可以控制LCD的模式和工作状态,然后写入数据,让LCD显示需要的界面。

    要控制12864,重点在熟悉其控制器,比如ST7565,具体内容自行查阅资料。

    ST7565是指令式交互系统,熟悉指令表是关键。

    通过发送对应的指令,让控制器做对应的事情。

    总体采用:控制总线+数据总线

    有些控制器不带字库,有些带字库。

    如果不带字库,那么,我们就需要将对应的字模写入LCD12864的控制器,以控制哪些点亮,哪些点不亮,从而显示字符、汉字以及各种各样的简单图案。

    注意:通常显示汉字都需要16*16的点阵屏,要不然看起来不像。

    LCD12864在竖向上被分为8个页,每个页在竖向是8个像素点,显示字符通常只需要1个页。

    但是显示汉字或者其他图案则需要两页甚至更多页,那么取模时就要注意取模的方式。要竖着8个点8个点地取。类似于多块8*8点阵拼在一起。

    具体的自行研究,不再赘述。关键要了解其原理。

  • 相关阅读:
    2022-11-03 C++并发编程( 三十九 )
    RecyclerView 数据更新方法 notifyItemChanged/notifyItemInsert/notifyIteRemoved
    20天深度复习JavaSE的详细笔记(十八)——网络编程
    使用 StringUtils.split 的坑
    【JAVA】-- 简易超市管理系统(一)(实现思路+每步代码)
    RHCE学习 --- 第八次作业(ansible)
    小迪安全33WEB 攻防-通用漏洞&文件上传&中间件解析漏洞&编辑器安全
    用acme.sh给网站域名,申请免费SSL永久证书(自动续期)
    Pytorch Advanced(三) Neural Style Transfer
    MFC案例:自制工具条(Toolbar)按钮的小程序
  • 原文地址:https://blog.csdn.net/qq_28576837/article/details/126098829