• 【单片机】16-LCD1602和12864和LCD9648显示器


    1.LCD显示器相关背景

    1.LCD简介

    (1)显示器,常见显示器:电视,电脑

    (2)LCD(Liquid Crystal Display),液晶显示器,原理介绍

    (3)LCD应用领域:手机,电脑

    (4)将来取代LCD:LED,OLED【全面屏---软性】

    2.电子显示器的原理

    1.像素(分辨率)

    显示单元【液晶分子】

    但是实际上:像素!=分辨率

    比如:出厂时电脑的像素已经确定,就是最大的显示【比如是1920*1080】,所以最大的分辨率是1920*1080,但是不能超过1920*1080,却可以小于1920*1080

    2.显存

    用来做显示的内存【电子显示效果跟内存有关】

    找一块空间来存储像素和内存的对应关系。【将要显示的内容丢到显存中---存储的是要显示的内容与液晶分子的一一对应关系

    3.字模

    字的模型。表示将这个字如何对应到显示器中。【将“A“放入相同的分辨率的显示器上,会产生不同的字模】

    4.字库

    字模形成的库。

    5.控制器(关键)和驱动器

    LCD显示器中的2个器件

    控制器:方向盘,挂挡---跟CPU对接---靠近软件

    驱动器:马达,发动器---将要显示的东西打到液晶显示器上---靠近硬件

    6.软件+硬件实现功能

    2.LCD1602

    1.简介

    1.为什么叫1602

    16*2--》显示器可以显示的字符【显示器可以显示2排,每排16个

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

    2.带ASCII码字库,不能显示中文

    当我们想要让LCD1602显示某一个ASCII码字符时候,只需要将这个字符对应的ASCII码发给LCD1602内部的控制器,控制器就会去查字库就得到字模,如何将字模发给内部的驱动器去驱动LCD做显示。

    2.原理图和接线引脚

    1.引脚分为:数据接口+控制接口

    16根线:2根VCC,2根GND,1根VO(调节屏幕亮度),RS+RW+E(控制信号线),DB0-DB7(数据线)

    2.并行接口

    串行:就是数据线只有1根(I2C中的SDA),同时只能传输1个bit位,如果要传送多个bit位必须分时传输。

    并行:就是数据线有很多根,每一根可以传输1个bit位,所以同时可以传输多个bit位。

    如LCD1602有8根数据线,所以一次同时传输8bit位

    3.背光调节

    1根VO(调节屏幕亮度)

    4.接线确认

    3.数据手册

    LCD1602数据手册速览 - 电子组培训文档

    https://www.dfrobot.com.cn/image/data/DFR0063/CN/HD44780.pdf

    1.LCM和LCD

    LCM:就是lcd module(LCD模组)

    2.主要技术参数解析

    3.引脚定义(结合原理图来对照分析)

    4.控制器接口说明(主要控制器型号)

    RS=1时候,D0-D7上传输的是数据

    RS=0时候,D0-D7上传输的是命令

    RW=1时候,表示我们要读

    RW=0时候,表示我们要写

    E=1时候,表示使能        enable

    E=0时候,表示禁止(禁能) disable

    3.LCD1602控制器的底层时序

    1.关键点

    (1)时序走控制接口引脚

    (2)指令码,状态字,数据,这三个走数据接口

    (3)注意是并行的

    2.控制器接口

    3.读状态时序分析(判断是否在忙)

    判断当前LCD是否有在显示数据

    对控制器每一次进行读写操作之前,都必须进行读写检测,确保bit7==0

    状态字的解析方法

    读状态:RS=0;RW=1;RE=1;

    读取状态字的bit7位,如果此时bit7=1--》表示此时还在显示东西,此时不可以进入

                                                    bit7=0---》表示此时没有显示东西,可以开始显示

    1. //基本操作时序:读状态:输入RS=0,RW=1,EN=1 输出:bit0-bit7--》状态
    2. void Read_Busy{ //忙检测函数,判断bit7是0:允许执行;1禁止
    3. unsigned char sta;
    4. LCD1602_DB=0xff;
    5. LCD1602_RS=0;
    6. LCD1602_RW=1;
    7. do{
    8. LCD1602_EN=1;//使能
    9. sta=LCD1602_DB;//读取8个bit位的状态
    10. LCD1602_EN=0;
    11. //如果sta&0x80==1,表示sta的bit7为1,则表示禁止状态,还要继续循环
    12. }while(sta & 0x80);
    13. }

    4.写指令时序分析

    1. void Lcd1602_Write_Cmd(unsigned char cmd){
    2. Read_Busy();
    3. LCD1602_RS=0;
    4. LCD1602_RW=0;
    5. LCD1602_DB=cmd; //写入bit0-bit7
    6. LCD1602_EN=1;
    7. LCD1602_EN=0;
    8. }

    5.读数据时序分析

    读数据实际上是读”显存“

    但是实际上我们不需要

    6.写数据的时序分析

    1. void Lcd1602_Write_Data(unsigned char dat){ //写数据
    2. Read_Busy();
    3. LCD1602_RS=0;
    4. LCD1602_RW=0;
    5. LCD1602_DB=dat; //将数据写入
    6. LCD1602_EN=1;
    7. LCD1602_EN=0;
    8. }

    注意点:

    写指令-->RS=0

    写数据-->RS=1

    7.RAM地址映射图

    芯片范围是0-39每行,但是实际只用了0-15每行

    将”A“给00这个空间,这个00会自动查找该位

    4.指令说明

    1.显示模式设置

    lcd1602_write_cmd(0x38);//设置16*2显示,数据总线8位,5*7点阵/字符

    2.显示开/关及光标设置

    1. // 本函数用来设置当前光标位置,其实就是设置当前正在编辑的位置,
    2. // 其实就是内部的数据地址指针,其实就是RAM显存的偏移量
    3. // x范围是0-15,y=0表示上面一行,y=1表示下面一行
    4. void lcd1602_set_cursor(unsigned char x,unsigned char y){//显示坐标位置
    5. unsigned char addr;//鼠标所在位置
    6. if(y==0){//第一行
    7. addr=0x00+x;
    8. }else{//第二行
    9. //LCD1602是一行只能显示16个,但是实际上一行有40
    10. addr=0x40+x;
    11. }
    12. lcd1602_write_cmd(addr|0x80);
    13. }

    关闭显示:0000 1000   0x08

    打开显示不显示光比 : 0000 1100   0x0c

    打开显示并且显示光标且光标闪烁: 0000 1111   0x0f

    地址指针自动+1,整体屏幕不移动 :0000 0110   0x06

    3.数据控制

    控制器内部设有一个数据地址指针,用户可以通过它们来访问内部的全部80字节RAM

    1.数据指针设置

    0x80+(0x00-0x0f)   第一行设置地址指针指令

    0x80+(0x40-0x4f)   第二行设置地址指针指令

    2.读数据

    3.写数据

    4.其他设置

    0x01  显示清屏

    0x02  显示回车

    5.初始化过程

    1. void lcd1602_init(void)
    2. {
    3. lcd1602_write_cmd(0x28);//数据总线4位,显示2行,5*7点阵/字符
    4. lcd1602_write_cmd(0x08);//显示关闭【可以省略】
    5. lcd1602_write_cmd(0x01);//显示清屏【可以省略】
    6. lcd1602_write_cmd(0x0c);//显示功能开,无光标,光标闪烁
    7. lcd1602_write_cmd(0x06);//写入新数据后光标右移,显示屏不移动
    8. lcd1602_write_cmd(0x01);//清屏
    9. }

    4.显示字符

    可以进行换行的

    1. /*******************************************************************************
    2. * 函 数 名 : lcd1602_show_string
    3. * 函数功能 : LCD1602显示字符
    4. * 输 入 : x,y:显示坐标,x=0~15,y=0~1;
    5. str:显示字符串
    6. * 输 出 : 无
    7. *******************************************************************************/
    8. void lcd1602_show_string(u8 x,u8 y,u8 *str)
    9. {
    10. u8 i=0;
    11. if(y>1||x>15)return;//行列参数不对则强制退出
    12. if(y<1) //第1行显示
    13. {
    14. while(*str!='\0')//字符串是以'\0'结尾,只要前面有内容就显示
    15. {
    16. if(i<16-x)//如果字符长度超过第一行显示范围,则在第二行继续显示
    17. {
    18. lcd1602_write_cmd(0x80+i+x);//第一行显示地址设置
    19. }
    20. else
    21. {
    22. lcd1602_write_cmd(0x40+0x80+i+x-16);//第二行显示地址设置
    23. }
    24. lcd1602_write_data(*str);//显示内容
    25. str++;//指针递增
    26. i++;
    27. }
    28. }
    29. else //第2行显示
    30. {
    31. while(*str!='\0')
    32. {
    33. if(i<16-x) //如果字符长度超过第二行显示范围,则在第一行继续显示
    34. {
    35. lcd1602_write_cmd(0x80+0x40+i+x);
    36. }
    37. else
    38. {
    39. lcd1602_write_cmd(0x80+i+x-16);
    40. }
    41. lcd1602_write_data(*str);
    42. str++;
    43. i++;
    44. }
    45. }
    46. }

    不可以自动换行的

    1. static void Lcd1602_Write_Data(unsigned char dat) //写数据
    2. {
    3. Read_Busy();
    4. LCD1602_RS = 1;
    5. LCD1602_RW = 0;
    6. LCD1602_DB = dat;
    7. LCD1602_EN = 1;
    8. LCD1602_EN = 0;
    9. }
    10. /************* 高层时序 ******************************/
    11. // 本函数用来设置当前光标位置,其实就是设置当前正在编辑的位置,
    12. // 其实就是内部的数据地址指针,其实就是RAM显存的偏移量
    13. // x范围是0-15,y=0表示上面一行,y=1表示下面一行
    14. void LcdSetCursor(unsigned char x,unsigned char y) //坐标显示
    15. {
    16. unsigned char addr;
    17. if(y == 0)
    18. addr = 0x00 + x;
    19. else
    20. addr = 0x40 + x;
    21. Lcd1602_Write_Cmd(addr|0x80);
    22. }
    23. // 函数功能是:从坐标(x,y)开始显示字符串str
    24. // 注意这个函数不能跨行显示,因为显存地址是不连续的
    25. // 其实我们可以封装出一个能够折行显示的函数的
    26. void LcdShowStr(unsigned char x,unsigned char y,unsigned char *str) //显示字符串
    27. {
    28. LcdSetCursor(x,y); //当前字符的坐标
    29. while(*str != '\0')
    30. {
    31. Lcd1602_Write_Data(*str++);
    32. }
    33. }

    5.代码实现

    lcd1602.c

    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. }

    lcd1602.h

    1. #ifndef __lcd1602__H__
    2. #define __lcd1602__H__
    3. #include
    4. #define u8 unsigned char
    5. //只需要声明高层时序即可,而底层时序是不需要声明
    6. //因为我们在头文件中声明这个函数,目的是为了让别的文件去包含这个
    7. //从而调用这个头文件中声明的函数,所以我们只需要声明1602.c中将来
    8. //会被外部.c文件调用的哪些函数即可,而且1602.c中自己使用的内部函数将来也
    9. //不会被外部.c文件调用,因此就不用声明了。
    10. void LcdSetCursor(unsigned char x,unsigned char y);
    11. void LcdShowStr(unsigned char x,unsigned char y,unsigned char *str);
    12. void lcd1602_show_string(u8 x,u8 y,u8 *str);
    13. void InitLcd1602();
    14. #endif

    main.c

    1. #include"lcd1602.h"
    2. void main(){
    3. InitLcd1602();
    4. LcdShowStr(0, 0, "nihao,xiaolin");
    5. }

    6.LCD12864

    1.什么是LCD12864

    (1)128p*64p,注意不是字符而是pixel【像素】

    (2)没有内置字库,用户需要提供字模给LCD12864内部的控制器

    (3)常见外观有2种

    (4)可以显示文字(英文,中文或者其他文字),可以显示图片(点阵图)

    2.原理图和数据手册和接线

    1.接线确认

    2.原理图(开发板底板,屏幕转接板)

    3.数据手册(LCD12894,ST7565【内部控制器】)

    https://www.dfrobot.com.cn/image/data/FIT0021/CN/LCD12864%20chinese%20char.pdf


     

    http://pdf-html.ic37.com/pdf_file_A/20200531/pdf_pdf/pdf4/SITRONIX/ST756_datasheet_832636/135203/ST756_datasheet.pdf

    7.LCD12864低层时序分析

    1.学习方法

    (1)找准数据手册中关键信息点,用来查而不是挨个看

    (2)数据手册对照官方示例代码来参照对比

    (3)要结合各部分原理图,各部分数据手册,实例代码来综合分析

    (4)必要时做笔记

    2.ST7565低层时序分析

    由于我们找不到时序图所以只能通过引脚描述来进行分析

    1.写指令

    1. void LcdSt7565_WriteCmd(cmd){
    2. LCD12864_CS=0; //chip select 打开片选
    3. LCD12864_RD=1; //disable read 读失能
    4. LCD12864_RS=0; //select command 悬着命令
    5. LCD12864_RW=0; //slect write 选择写模式
    6. _nop_();
    7. _nop_();
    8. DATA_PORT = cmd; //put command,放置命令
    9. _nop_();
    10. _nop_();
    11. LCD12864_RW = 1; //command writing ,写入命令
    12. }

    2.写数据

    1. void LcdSt7565_WriteData(dat)
    2. {
    3. LCD12864_CS = 0; //chip select,打开片选
    4. LCD12864_RD = 1; //disable read,读失能
    5. LCD12864_RS = 1; //select data,选择数据
    6. LCD12864_RW = 0; //select write,选择写模式
    7. _nop_();
    8. _nop_();
    9. DATA_PORT = dat; //put data,放置数据
    10. _nop_();
    11. _nop_();
    12. LCD12864_RW = 1; //data writing,写数据
    13. }

    8.ST7565的指令集

    1.高层时序分析

    1.指令式交互系统

    实际上我们是给CPU编程,控制ST7565

    2.指令表是关键

    操作手册

    2.指令系统学习方法

    (1)沿着数据手册顺序分析

    (2)沿着示例代码按需分析

    3.逐个分析

    对应上面的P32页

    1. 打开开关:Display ON/OFF

    Display ON/OFF

                            1010 1111                0xaf    on

                            1010 1110                0xae    off

    2.一行显示:Display Start Line Set

    显示行号设置

            0x 0100 0000+(0-63)

            0x40+(0-63)                表示要将内容显示在第0-63行

    实际上ST7565是65*132【多了一行没有显示】

    3.页地址设置:Page Address Set

    设置page address   

            1011 0000+(0-7)

            0xB0+(0-7)    表示设置page address

    4.列地址设置Column Address Set

    设置column address     

            一个完整指令是分为2条相连的指令合起来的。必须连发2个

            指令1:0001 0000+高4位        0x10+高4位

            指令2:0000 0000+低4位        0x00+低4位

    5.设置从哪一个方向开始显示:ADC Select

    设置ADC

            0xA0        normal                columu address 从左往后的

            0xa1         reverse               columu address 从右往左的

    6.设置相反的显示:Display Normal/Reverse

    该命令可以反转点亮和熄灭的显示,而不覆盖显示数据 RAM 的内容。 完成此操作后
    显示数据 RAM 内容被保留。

    7.软件复位:Reset

    在初始化的时候,应该先硬件复位【LCD12864_RSET = 0】,在软件复位【LcdSt7565_WriteCmd(0xE2)】。

    8.设置背景光对比度:Electronic volume

    1000 0001   ---->0x81

    4.对照官方代码进行解析:初始化操作

    初始化函数:

    (1)第一类指令:时序需要

    (2)第二类指令:硬件特性设置需要的(比如屏幕亮度,对比度之类)
    (3)第三类指令:显示i参数相关的:A1/A0

    1. /*******************************************************************************
    2. * 函 数 名 : LCD12864_Init
    3. * 函数功能 : 初始化12864
    4. * 输 入 : 无
    5. * 输 出 : 无
    6. * 说 明 : LCD12864的命令指令可以查看例程文件夹下的《ST7565p数据手册》
    7. * * 的第51页的位置。
    8. *******************************************************************************/
    9. void Lcd12864_Init()
    10. {
    11. uchar i;
    12. LCD12864_RSET = 0;//硬件复位
    13. for (i=0; i<100; i++);//让内部进行复位
    14. LCD12864_CS = 0;//打开片选,选中芯片
    15. LCD12864_RSET = 1;//关闭复位
    16. //----------------Start Initial Sequence(时序)-------//
    17. //------程序初始化设置,具体命令可以看文件夹下---//
    18. //--软件初始化--//
    19. LcdSt7565_WriteCmd(0xE2); //软件复位:reset
    20. for (i=0; i<100; i++); //延时一下
    21. //--表格第8个命令,0xA0段(左右)方向选择正常方向(0xA1为反方向)--//
    22. // 0xA0对应0-127,0xA1对应4-131
    23. LcdSt7565_WriteCmd(0xA0); //ADC select segment direction
    24. //--表格第15个命令,0xC8普通(上下)方向选择选择反向,0xC0为正常方向--//
    25. LcdSt7565_WriteCmd(0xC8); //Common direction
    26. //--表格第9个命令,0xA6为设置字体为黑色,背景为白色---//
    27. //--0xA7为设置字体为白色,背景为黑色---//
    28. LcdSt7565_WriteCmd(0xA6); //reverse display
    29. //--表格第10个命令,0xA4像素正常显示,0xA5像素全开--//
    30. LcdSt7565_WriteCmd(0xA4); //normal display
    31. //--表格第11个命令,0xA3偏压为1/7,0xA2偏压为1/9--//
    32. LcdSt7565_WriteCmd(0xA2); //bias set 1/9
    33. //--表格第19个命令,这个是个双字节的命令,0xF800选择增压为4X;--//
    34. //--0xF801,选择增压为5X,其实效果差不多--//
    35. LcdSt7565_WriteCmd(0xF8); //Boost ratio set
    36. LcdSt7565_WriteCmd(0x01); //x4
    37. //--表格第18个命令,这个是个双字节命令,高字节为0X81,低字节可以--//
    38. //--选择从0x00到0X3F。用来设置背景光对比度。---/
    39. LcdSt7565_WriteCmd(0x81); //V0 a set
    40. LcdSt7565_WriteCmd(0x23);
    41. //--表格第17个命令,选择调节电阻率--//
    42. LcdSt7565_WriteCmd(0x25); //Ra/Rb set
    43. //--表格第16个命令,电源设置。--//
    44. LcdSt7565_WriteCmd(0x2F);
    45. for (i=0; i<100; i++);
    46. //--表格第2个命令,设置显示开始位置--//
    47. LcdSt7565_WriteCmd(0x40); //start line
    48. //--表格第1个命令,开启显示--//
    49. LcdSt7565_WriteCmd(0xAF); // display on
    50. for (i=0; i<100; i++);
    51. }

    9.清屏操作

    1. /*******************************************************************************
    2. * 函 数 名 : LCD12864_ClearScreen
    3. * 函数功能 : 清屏12864
    4. * 输 入 : 无
    5. * 输 出 : 无
    6. *******************************************************************************/
    7. void Lcd12864_ClearScreen(void)
    8. {
    9. uchar i, j;
    10. for(i=0; i<8; i++)//行--64行分为8页【8个bit位容易操作】
    11. {
    12. //--表格第3个命令,设置Y的坐标--//
    13. //--Y轴有64个,一个坐标8位,也就是有8个坐标--//
    14. //所以一般我们使用的也就是从0xB0到0x07【设置页地址0xB0+(0-7)】,就够了--//
    15. LcdSt7565_WriteCmd(0xB0+i);
    16. //--表格第4个命令,设置X坐标--//
    17. //--当你的段初始化为0xA1时【4-131】,X坐标从0x10,0x04到0x18,0x04,一共128位--//
    18. //--当你的段初始化为0xA0时【0-127】,X坐标从0x10,0x00到0x18,0x00,一共128位--//
    19. //--在写入数据之后X坐标的坐标是会自动加1的,我们初始化使用0xA1所以--//
    20. //--我们的X坐标从0x10,0x00开始---//
    21. LcdSt7565_WriteCmd(0x10);
    22. LcdSt7565_WriteCmd(0x00);
    23. //--X轴有128位,就一共刷128次,X坐标会自动加1,所以我们不用再设置坐标--//
    24. for(j=0; j<128; j++)
    25. {
    26. LcdSt7565_WriteData(0x00); //如果设置背景为白色时,清屏选择0XFF
    27. }
    28. }
    29. }

    扩展

    此时我们设置白背景,黑字

    所以0x00显示白字,0xff显示黑字

    下面我们设置0xf0【则在一页中,上面四行显示黑色,下面四行显示白色】

    1. //--X轴有128位,就一共刷128次,X坐标会自动加1,所以我们不用再设置坐标--//
    2. for(j=0; j<128; j++)
    3. {
    4. LcdSt7565_WriteData(0xf0); //如果设置背景为白色时,清屏选择0XFF
    5. }

    10.LCD12864显示文字

    1.文字显示的原理

    (1)字模

    (2)像素&显存的对应关系:一一对应

    (3)显示函数:将字模丢到正确的显存中去

    2.字模的获取

    (1)芯片自带字库

    (2)网上下载字库

    (3)字模生成软件自助生成

    3.代码实战显示6*8ASCII码

    1.先弄初始化函数和清屏函数

    main.c
    1. #include"st7565.h"
    2. void main(){
    3. Lcd12864_Init();
    4. Lcd12864_ClearScreen();
    5. while(1);
    6. }
    st7565.c
    1. #include "st7565p.h"
    2. /*******************************************************************************
    3. * 函 数 名 : LCD12864_WriteCmd
    4. * 函数功能 : 写入一个命令到12864
    5. * 输 入 : cmd
    6. * 输 出 : 无
    7. *******************************************************************************/
    8. void LcdSt7565_WriteCmd(cmd)
    9. {
    10. LCD12864_CS = 0; //chip select,打开片选
    11. LCD12864_RD = 1; //disable read,读失能
    12. LCD12864_RS = 0; //select command,选择命令
    13. LCD12864_RW = 0; //select write,选择写模式
    14. _nop_();
    15. _nop_();
    16. DATA_PORT = cmd; //put command,放置命令
    17. _nop_();
    18. _nop_();
    19. LCD12864_RW = 1; //command writing ,写入命令
    20. }
    21. /*******************************************************************************
    22. * 函 数 名 : LcdSt7565_WriteData
    23. * 函数功能 : 写入一个数据到12864
    24. * 输 入 : dat
    25. * 输 出 : 无
    26. *******************************************************************************/
    27. void LcdSt7565_WriteData(dat)
    28. {
    29. LCD12864_CS = 0; //chip select,打开片选
    30. LCD12864_RD = 1; //disable read,读失能
    31. LCD12864_RS = 1; //select data,选择数据
    32. LCD12864_RW = 0; //select write,选择写模式
    33. _nop_();
    34. _nop_();
    35. DATA_PORT = dat; //put data,放置数据
    36. _nop_();
    37. _nop_();
    38. LCD12864_RW = 1; //data writing,写数据
    39. }
    40. /*******************************************************************************
    41. * 函 数 名 : LCD12864_Init
    42. * 函数功能 : 初始化12864
    43. * 输 入 : 无
    44. * 输 出 : 无
    45. * 说 明 : LCD12864的命令指令可以查看例程文件夹下的《ST7565p数据手册》
    46. * * 的第51页的位置。
    47. *******************************************************************************/
    48. void Lcd12864_Init()
    49. {
    50. uchar i;
    51. LCD12864_RSET = 0;//硬件复位
    52. for (i=0; i<100; i++);//让内部进行复位
    53. LCD12864_CS = 0;//打开片选,选中芯片
    54. LCD12864_RSET = 1;//关闭复位
    55. //----------------Start Initial Sequence(时序)-------//
    56. //------程序初始化设置,具体命令可以看文件夹下---//
    57. //--软件初始化--//
    58. LcdSt7565_WriteCmd(0xE2); //软件复位:reset
    59. for (i=0; i<100; i++); //延时一下
    60. //--表格第8个命令,0xA0段(左右)方向选择正常方向(0xA1为反方向)--//
    61. // 0xA0对应0-127,0xA1对应4-131
    62. LcdSt7565_WriteCmd(0xA0); //ADC select segment direction
    63. //--表格第15个命令,0xC8普通(上下)方向选择选择反向,0xC0为正常方向--//
    64. LcdSt7565_WriteCmd(0xC8); //Common direction
    65. //--表格第9个命令,0xA6为设置字体为黑色,背景为白色---//
    66. //--0xA7为设置字体为白色,背景为黑色---//
    67. LcdSt7565_WriteCmd(0xA6); //reverse display
    68. //--表格第10个命令,0xA4像素正常显示,0xA5像素全开--//
    69. LcdSt7565_WriteCmd(0xA4); //normal display
    70. //--表格第11个命令,0xA3偏压为1/7,0xA2偏压为1/9--//
    71. LcdSt7565_WriteCmd(0xA2); //bias set 1/9
    72. //--表格第19个命令,这个是个双字节的命令,0xF800选择增压为4X;--//
    73. //--0xF801,选择增压为5X,其实效果差不多--//
    74. LcdSt7565_WriteCmd(0xF8); //Boost ratio set
    75. LcdSt7565_WriteCmd(0x01); //x4
    76. //--表格第18个命令,这个是个双字节命令,高字节为0X81,低字节可以--//
    77. //--选择从0x00到0X3F。用来设置背景光对比度。---/
    78. LcdSt7565_WriteCmd(0x81); //V0 a set
    79. LcdSt7565_WriteCmd(0x23);
    80. //--表格第17个命令,选择调节电阻率--//
    81. LcdSt7565_WriteCmd(0x25); //Ra/Rb set
    82. //--表格第16个命令,电源设置。--//
    83. LcdSt7565_WriteCmd(0x2F);
    84. for (i=0; i<100; i++);
    85. //--表格第2个命令,设置显示开始位置--//
    86. LcdSt7565_WriteCmd(0x40); //start line
    87. //--表格第1个命令,开启显示--//
    88. LcdSt7565_WriteCmd(0xAF); // display on
    89. for (i=0; i<100; i++);
    90. }
    91. /*******************************************************************************
    92. * 函 数 名 : LCD12864_ClearScreen
    93. * 函数功能 : 清屏12864
    94. * 输 入 : 无
    95. * 输 出 : 无
    96. *******************************************************************************/
    97. void Lcd12864_ClearScreen(void)
    98. {
    99. uchar i, j;
    100. for(i=0; i<8; i++)//行--64行分为8页【8个bit位容易操作】
    101. {
    102. //--表格第3个命令,设置Y的坐标--//
    103. //--Y轴有64个,一个坐标8位,也就是有8个坐标--//
    104. //所以一般我们使用的也就是从0xB0到0x07【设置页地址0xB0+(0-7)】,就够了--//
    105. LcdSt7565_WriteCmd(0xB0+i);
    106. //--表格第4个命令,设置X坐标--//
    107. //--当你的段初始化为0xA1时【4-131】,X坐标从0x10,0x04到0x18,0x04,一共128位--//
    108. //--当你的段初始化为0xA0时【0-127】,X坐标从0x10,0x00到0x18,0x00,一共128位--//
    109. //--在写入数据之后X坐标的坐标是会自动加1的,我们初始化使用0xA1所以--//
    110. //--我们的X坐标从0x10,0x00开始---//
    111. LcdSt7565_WriteCmd(0x10);
    112. LcdSt7565_WriteCmd(0x00);
    113. //--X轴有128位,就一共刷128次,X坐标会自动加1,所以我们不用再设置坐标--//
    114. for(j=0; j<128; j++)
    115. {
    116. LcdSt7565_WriteData(0x00); //如果设置背景为白色时,清屏选择0XFF
    117. }
    118. }
    119. }
    st7565.h
    1. #ifndef __ST7565_H
    2. #define __ST7565_H
    3. #include
    4. #include
    5. //---重定义关键词---//
    6. #ifndef uchar
    7. #define uchar unsigned char
    8. #endif
    9. #ifndef uint
    10. #define uint unsigned int
    11. #endif
    12. //--定时使用的IO口--//
    13. #define DATA_PORT P0
    14. sbit LCD12864_CS = P3^2;
    15. sbit LCD12864_RSET = P3^3;
    16. sbit LCD12864_RS = P2^6;
    17. sbit LCD12864_RW = P2^7;
    18. sbit LCD12864_RD = P2^5;
    19. //--定义全局函数--//
    20. void LcdSt7565_WriteCmd(cmd);
    21. void LcdSt7565_WriteData(dat);
    22. void Lcd12864_Init();
    23. void Lcd12864_ClearScreen(void);
    24. #endif

    2.网上找到6*8ASCII码字库

    nios ii 之5110液晶屏(6*8、8*16 ASCII字符,16*16 汉字,常用图标,图案,超全字库+函数代码)_6*8 ascii-CSDN博客

    3.编写函数显示数值

    我们在编写下面代码遇到的问题:

    1)我们需要将模取高位和低位的时候需要分别使用一个变量组装起来

    2)字库中对应的ASCII是十六进制,记得加上0x

    3)当我们遇到问题的时候一个模块一个模块的检验

    1. //在屏幕的(x,y)坐标处,显示c这个字符
    2. //(x,y)表示像素点的坐标值,所以x范围是0-127,y的范围是0-63
    3. //注意,因为显示文字是以整页为单位的,为了简单起见必须页对齐显示
    4. //因此给的y值必须页首地址,就是0 8 16 24 等数值
    5. void ascii_display(unsigned char x,unsigned char y,unsigned char c){
    6. unsigned char i=0;
    7. unsigned char x1,x2;
    8. //【第一步,设置显示的x和y坐标】
    9. //y坐标,其实就是page address
    10. Lcdst7565_WriteCmd(0xB0+y/8);//因为只能整页显示,所以我们要除8才能保证
    11. //x坐标,只要在范围内别超出就可以了
    12. x1=(x>>4) & 0x0f; //显示高4位
    13. x2=x& 0x0f; //显示低4位
    14. //因为我们要使用2次发送才可以将数据发出
    15. Lcdst5765_Write_Cmd(0x10+x1);
    16. Lcdst7565_Write_Cmd(0x00+x2);
    17. //【第二步,找到c对应的字模】
    18. //ASCII_6_8[x-20][0] 字模的第一个字节
    19. //【第三步,将字模丢到显存中去】
    20. for(i=0;i<6;i++){
    21. //因为我们字库是从“20”开始,所以要-20
    22. //注意点:我们是十六进制,所以是0x20
    23. Lcdst7565_Write_Cmd(ASCII_6_8[c-0x20][i]);
    24. }
    遗留问题:

    (1)初始化和字模不匹配,造成字是反的

    (2)初始化不对,造成x坐标是从右往左的

    4.解决遗留问题

    1.修改初始化代码从左往右显示

    (1)先修改初始化函数中的显示方向代码

    1. //--表格第8个命令,0xA0段(左右)方向选择正常方向(0xA1为反方向)--//
    2. // 0xA0对应0-127,0xA1对应4-131
    3. LcdSt7565_WriteCmd(0xA0); //ADC select segment direction

    (2)修改清屏函数

    1. //--表格第4个命令,设置X坐标--//
    2. //--当你的段初始化为0xA1时【4-131】,X坐标从0x10,0x04到0x18,0x04,一共128位--//
    3. //--当你的段初始化为0xA0时【0-127】,X坐标从0x10,0x00到0x18,0x00,一共128位--//
    4. //--在写入数据之后X坐标的坐标是会自动加1的,我们初始化使用0xA1所以--//
    5. //--我们的X坐标从0x10,0x00开始---//
    6. LcdSt7565_WriteCmd(0x10);
    7. LcdSt7565_WriteCmd(0x00);

    (3)修改显示数值的函数

    4.显示跨页(16*16)

    (1)超过8*8的字符如何显示

    (2)常见汉字字模大小是16*16

    zimo.h

    1. #ifndef __ZIMO_H__
    2. #define __ZIMO_H__
    3. unsigned char code zimo_zhu[] =
    4. {0x80,0xA0,0x90,0x8E,0x88,0x88,0x88,0xFF,0x88,0x88,0x88,0x88,0x88,0x80,0x80,0x00,
    5. 0x20,0x20,0x10,0x08,0x04,0x02,0x01,0xFF,0x01,0x02,0x04,0x08,0x10,0x20,0x20,0x00,};
    6. unsigned char code zimo_you[] =
    7. {0x04,0x04,0x04,0x84,0xE4,0x3C,0x27,0x24,0x24,0x24,0x24,0xE4,0x04,0x04,0x04,0x00,
    8. 0x04,0x02,0x01,0x00,0xFF,0x09,0x09,0x09,0x09,0x49,0x89,0x7F,0x00,0x00,0x00,0x00,};
    9. unsigned char code zimo_peng[] =
    10. {0x00,0xFE,0x22,0xFE,0x00,0xFE,0x22,0xFE,0x00,0xFC,0x16,0x25,0x84,0xFC,0x00,0x00,
    11. 0x60,0x1F,0x22,0xBF,0x40,0x3F,0x82,0xFF,0x00,0x13,0x12,0x12,0x52,0x82,0x7E,0x00,};
    12. #endif

    自定义数值输出

    1. void hanzi_display(unsigned char x,unsigned char y,unsigned char zimo[]){
    2. unsigned char i=0;
    3. unsigned char x1,x2;
    4. //先显示上面一半
    5. Lcdst7565_WriteCmd(0xB0+y/8);
    6. //x坐标,只要在范围内别超出即可
    7. x1=(x>>4)&0x0f;
    8. x2=x&0x0f;
    9. Lcdst7565_Write(0x10+x1);
    10. Lcdst7565_Write(0x00+x2);
    11. for(i=0;i<16;i++){ //因为我们是16*16,此时是显示第一页的0-15列
    12. Lcdst7565_WriteData(zimo[i]);
    13. }
    14. //在显示下面一半
    15. Lcdst7565_WriteCmd(0xB0+y/8+1);
    16. //x坐标,只要在范围内别超出即可
    17. x1=(x>>4)&0x0f;
    18. x2=x&0x0f;
    19. Lcdst7565_Write(0x10+x1);
    20. Lcdst7565_Write(0x00+x2);
    21. for(i=16;i<32;i++){
    22. Lcdst7565_WriteData(zimo[i]);
    23. }
    24. }
    1. hanzi_display(0, 0, zimo_zhu);
    2. hanzi_display(16, 0, zimo_you);
    3. hanzi_display(32, 0, zimo_peng);

    使用简单的方式

    1. #ifndef __ZIMO_H__
    2. #define __ZIMO_H__
    3. unsigned char code zimo_zhuyoupeng[3][32] =
    4. {
    5. // 朱
    6. {0x80,0xA0,0x90,0x8E,0x88,0x88,0x88,0xFF,0x88,0x88,0x88,0x88,0x88,0x80,0x80,0x00,
    7. 0x20,0x20,0x10,0x08,0x04,0x02,0x01,0xFF,0x01,0x02,0x04,0x08,0x10,0x20,0x20,0x00,},
    8. // 有
    9. {0x04,0x04,0x04,0x84,0xE4,0x3C,0x27,0x24,0x24,0x24,0x24,0xE4,0x04,0x04,0x04,0x00,
    10. 0x04,0x02,0x01,0x00,0xFF,0x09,0x09,0x09,0x09,0x49,0x89,0x7F,0x00,0x00,0x00,0x00,},
    11. // 鹏
    12. {0x00,0xFE,0x22,0xFE,0x00,0xFE,0x22,0xFE,0x00,0xFC,0x16,0x25,0x84,0xFC,0x00,0x00,
    13. 0x60,0x1F,0x22,0xBF,0x40,0x3F,0x82,0xFF,0x00,0x13,0x12,0x12,0x52,0x82,0x7E,0x00,},
    14. };
    15. #endif
    1. hanzi_display(16*0, 16, zimo_zhuyoupeng[0]);
    2. hanzi_display(16*1, 16, zimo_zhuyoupeng[1]);
    3. hanzi_display(16*2, 16, zimo_zhuyoupeng[2]);

    11.LCD12864显示图片

    1.思路分析

    通过取字模软件将图片翻译为一个十六进制的数组

    2.图片数据获取

    1)取模软件,转换为bmp

    2)查看像素

    3)调节分辨率---》画图工具

    3.写显示函数

    1. // 在屏幕上显示一个图片,从屏幕左上角开始显示
    2. //因为是整个屏幕显示,所以跟清屏函数差不多
    3. void pic_display(unsigned char pic[])
    4. {
    5. uchar i, j;
    6. uint k = 0;//遍历数组,128*64/8=1024
    7. for(i=0; i<8; i++)//每一个page
    8. {
    9. LcdSt7565_WriteCmd(0xB0+i); //y轴
    10. LcdSt7565_WriteCmd(0x10); //高4位
    11. LcdSt7565_WriteCmd(0x00);//低4位
    12. //--X轴有128位,就一共刷128次,X坐标会自动加1,所以我们不用再设置坐标--//
    13. for(j=0; j<128; j++)
    14. {
    15. LcdSt7565_WriteData(pic[k++]); //如果设置背景为白色时,清屏选择0XFF
    16. }
    17. }
    18. }

    4.调试

    pic_display(pic);

    12.LCD9648

    1.SPI传输数据

    1. /*******************************************************************************
    2. * 函 数 名 : lcd9648_spi_write_byte
    3. * 函数功能 : LCD9648 SPI传输数据
    4. * 输 入 : dat:数据
    5. * 输 出 : 无
    6. *******************************************************************************/
    7. void lcd9648_spi_write_byte(u8 dat)
    8. {
    9. u8 i=0;
    10. for(i=0;i<8;i++)//循环8次将一个字节传输
    11. {
    12. if((dat&0x80)!=0)
    13. SDA = 1;
    14. else
    15. SDA = 0;
    16. dat<<= 1;//先写高位再写低位
    17. SCL = 0;
    18. SCL = 1;//时钟上升沿写入数据
    19. }
    20. }

    2.写

    1.写数据

    1. /*******************************************************************************
    2. * 函 数 名 : lcd9648_write_dat
    3. * 函数功能 : LCD9648写数据
    4. * 输 入 : dat:数据
    5. * 输 出 : 无
    6. *******************************************************************************/
    7. void lcd9648_write_dat(u8 dat)
    8. {
    9. CS0 = 0;//使能
    10. RS = 1;//选择数据
    11. lcd9648_spi_write_byte(dat);//发送数据
    12. CS0 = 1;//失能
    13. }

    2.写指令

    1. /*******************************************************************************
    2. * 函 数 名 : lcd9648_write_cmd
    3. * 函数功能 : LCD9648写命令
    4. * 输 入 : cmd:命令
    5. * 输 出 : 无
    6. *******************************************************************************/
    7. void lcd9648_write_cmd(u8 cmd)
    8. {
    9. CS0 = 0;//使能
    10. RS = 0;//选择命令
    11. lcd9648_spi_write_byte(cmd);//发送命令
    12. CS0 = 1;//失能
    13. }

    3.指令集

    1.第1条指令:将数据字节写入内存

    2.第二条指令:从内存中读取数据字节

    根据页地址 (PA) 寄存器和列地址 (CA) 寄存器写入/读取数据字节(命令 1,2)访问显示数据 RAM。 PA 和 CA 也可以通过发出设置页地址和设置列地址命令直接编程。

    3.第三条指令:获取当前显示器的状态

    BZ:BZ=1的时候,此时处于忙状态。BZ=0时候,表示可以接收命令

    MX:

    DE:显示使能标志。当表示可以使能DE=1,DE=0的时候表示不能使能

    RST:复位标志。RST=1的时候表示正在复位,RST=0的时候表示复位结束。

    4.第四条指令:设置列地址

    5.第五条指令:设置电源消耗设置

    6.第六条指令:设置滚动一行命令

    设置滚动行数。范围:0~63 滚动行设置将显示的图像向上滚动 SL 行。图标输出 CIC 不会受到“设置滚动线”命令的影响。

    7.第七条指令:设置页地址

    地址是0-7(所以使用4位数进行标识)

    8.第八条指令:设置 VLCD 电阻比

    9.第9条指令:设置光对比度

    10.第11条指令:将所有像素设置为开启

    11.第12条指令:设置显示启用

    该命令用于对寄存器 DC[2] 进行编程。当DC[2]设置为1时,UC1701x将首先退出睡眠模式,恢复电源,然后打开COM驱动程序和SEG驱动程序。

    12.第13条指令:设置显示x方向

    MX=0:表示按照默认方向显示---》0xa0

    MX=1:表示按照相反的方向显示--->0xa1

    13.第14条指令:设置显示y方向

    D0-D2:用来显示要设置的页数(y轴方向)-----》0-7

    MY=1:按照相反的方向显示

    MY=0:按照默认的方向显示

    14.第15条指令:系统重置

    该命令将激活系统重置。控制寄存器值将重置为其默认值。 RAM 中的数据存储不会受到影响。

    15.第16条指令:设置不进行操作

    16.第17条指令:设置屏幕的显示亮度(bias ratio:偏置比)

    17.第18条指令:设置光标更新模式

    此命令用于设置光标更新模式功能。当光标更新模式设置时,UC1701x 将使用寄存器 CA 的值更新寄存器 CR。列地址 CA 将随着写入 RAM 数据操作而增加,但无论 WA 设置是什么,地址环绕都将挂起。但是,列地址在读取 RAM 数据操作中不会递增。设置光标更新模式可用于实现“读后写RAM”功能。重置游标更新模式时,列地址 (CA) 将恢复为设置游标更新模式命令之前的值。此对命令及其功能的目的是支持游标实现的“读后写”功能。

    18.第19条指令:重置光标位置

    19.第20/21号指令:设置静态指示器关闭/打开

    20.第22条指令:设置助推器比率

    21.第23条指令:设置省电

    22.第24条指令:设置高级程序控制 0

    23.第25条指令:设置高级程序控制1

     

  • 相关阅读:
    六十七、Vue-CLI
    Unity背包系统
    SQL 优化有哪些技巧?
    Unity Raycast开启了新的性能时代
    数据结构——考研笔记(二)线性表的定义和线性表之顺序表
    高级FPGA设计结构实现和优化_(六)静态时序分析
    Windows11 OneDrive 安装后无法打开的解决办法
    Multiplexer and Demultiplexer(多路复用器和解复用器)
    Deep Dual-resolution Network 原理与代码解析
    Google Chrome的新“IP保护”功能将隐藏用户的IP地址
  • 原文地址:https://blog.csdn.net/m0_63077733/article/details/133499038