【单片机】16-LCD1602和12864显示器
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,EN=1 输出:bit0-bit7--》状态
void Read_Busy{ //忙检测函数,判断bit7是0:允许执行;1禁止unsigned char sta; LCD1602_DB=0xff;LCD1602_RS=0;LCD1602_RW=1;do{LCD1602_EN=1;//使能sta=LCD1602_DB;//读取8个bit位的状态LCD1602_EN=0;//如果sta&0x80==1,表示sta的bit7为1,则表示禁止状态,还要继续循环}while(sta & 0x80);
}
4.写指令时序分析
void Lcd1602_Write_Cmd(unsigned char cmd){Read_Busy();LCD1602_RS=0;LCD1602_RW=0;LCD1602_DB=cmd; //写入bit0-bit7LCD1602_EN=1;LCD1602_EN=0;
}
5.读数据时序分析
读数据实际上是读”显存“
但是实际上我们不需要
6.写数据的时序分析
void Lcd1602_Write_Data(unsigned char dat){ //写数据Read_Busy();LCD1602_RS=0;LCD1602_RW=0;LCD1602_DB=dat; //将数据写入LCD1602_EN=1;LCD1602_EN=0;
}
注意点:
写指令-->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.显示开/关及光标设置
//y=0是上面一行,y=1是下面一行
void LcdSetCursor(unsigned char x,unsigned char y){//坐标显示unsigned char addr;if(y==0)addr=0x00+x;elseaddr=0x40+x;Lcd1602_write_cmd(addr|0x80);
}
关闭显示: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.初始化过程
void lcd1602_init(void)
{lcd1602_write_cmd(0x28);//数据总线4位,显示2行,5*7点阵/字符lcd1602_write_cmd(0x08);//显示关闭【可以省略】lcd1602_write_cmd(0x01);//显示清屏【可以省略】lcd1602_write_cmd(0x0c);//显示功能开,无光标,光标闪烁lcd1602_write_cmd(0x06);//写入新数据后光标右移,显示屏不移动lcd1602_write_cmd(0x01);//清屏
}
4.显示字符
/*******************************************************************************
* 函 数 名 : lcd1602_show_string
* 函数功能 : LCD1602显示字符
* 输 入 : x,y:显示坐标,x=0~15,y=0~1;str:显示字符串
* 输 出 : 无
*******************************************************************************/
void lcd1602_show_string(u8 x,u8 y,u8 *str)
{u8 i=0;if(y>1||x>15)return;//行列参数不对则强制退出if(y<1) //第1行显示{ while(*str!='\0')//字符串是以'\0'结尾,只要前面有内容就显示{if(i<16-x)//如果字符长度超过第一行显示范围,则在第二行继续显示{lcd1602_write_cmd(0x80+i+x);//第一行显示地址设置 }else{lcd1602_write_cmd(0x40+0x80+i+x-16);//第二行显示地址设置 }lcd1602_write_data(*str);//显示内容str++;//指针递增i++; } }else //第2行显示{while(*str!='\0'){if(i<16-x) //如果字符长度超过第二行显示范围,则在第一行继续显示{lcd1602_write_cmd(0x80+0x40+i+x); }else{lcd1602_write_cmd(0x80+i+x-16); }lcd1602_write_data(*str);str++;i++; } }
}
5.代码实现
lcd1602.c
#include <reg51.h>// 对LCD1602的底层以及高层时序做封装// IO接口定义
#define LCD1602_DB P0 //data bus 数据总线
// 控制总线
sbit LCD1602_RS = P2^6;
sbit LCD1602_RW = P2^5;
sbit LCD1602_EN = P2^7; /************ 低层时序 ********************************/
void Read_Busy() //忙检测函数,判断bit7是0,允许执行;1禁止
{unsigned char sta; //LCD1602_DB = 0xff;LCD1602_RS = 0;LCD1602_RW = 1;do{LCD1602_EN = 1;sta = LCD1602_DB;LCD1602_EN = 0; //使能,用完就拉低,释放总线}while(sta & 0x80);
}void Lcd1602_Write_Cmd(unsigned char cmd) //写命令
{Read_Busy();LCD1602_RS = 0;LCD1602_RW = 0; LCD1602_DB = cmd;LCD1602_EN = 1;LCD1602_EN = 0;
}void Lcd1602_Write_Data(unsigned char dat) //写数据
{Read_Busy();LCD1602_RS = 1;LCD1602_RW = 0;LCD1602_DB = dat;LCD1602_EN = 1;LCD1602_EN = 0;
}/************* 高层时序 ******************************/
// 本函数用来设置当前光标位置,其实就是设置当前正在编辑的位置,
// 其实就是内部的数据地址指针,其实就是RAM显存的偏移量
// x范围是0-15,y=0表示上面一行,y=1表示下面一行
void LcdSetCursor(unsigned char x,unsigned char y) //坐标显示
{unsigned char addr;if(y == 0)addr = 0x00 + x;elseaddr = 0x40 + x;Lcd1602_Write_Cmd(addr|0x80);
}// 函数功能是:从坐标(x,y)开始显示字符串str
// 注意这个函数不能跨行显示,因为显存地址是不连续的
// 其实我们可以封装出一个能够折行显示的函数的
void LcdShowStr(unsigned char x,unsigned char y,unsigned char *str) //显示字符串
{LcdSetCursor(x,y); //当前字符的坐标while(*str != '\0'){Lcd1602_Write_Data(*str++);}
}// 初始化LCD,使之能够开始正常工作
void InitLcd1602() //1602初始化
{Lcd1602_Write_Cmd(0x38); //打开,5*8,8位数据//Lcd1602_Write_Cmd(0x0c); // 打开显示并且无光标Lcd1602_Write_Cmd(0x0f); // 打开显示并且光标闪烁Lcd1602_Write_Cmd(0x06);Lcd1602_Write_Cmd(0x01); //清屏
}
lcd1602.h
#ifndef __lcd1602__H__
#define __lcd1602__H__#include<reg51.h>#define u8 unsigned char //只需要声明高层时序即可,而底层时序是不需要声明
//因为我们在头文件中声明这个函数,目的是为了让别的文件去包含这个
//从而调用这个头文件中声明的函数,所以我们只需要声明1602.c中将来
//会被外部.c文件调用的哪些函数即可,而且1602.c中自己使用的内部函数将来也
//不会被外部.c文件调用,因此就不用声明了。void LcdSetCursor(unsigned char x,unsigned char y);
void LcdShowStr(unsigned char x,unsigned char y,unsigned char *str);
void lcd1602_show_string(u8 x,u8 y,u8 *str);
void InitLcd1602();#endif
main.c
#include"lcd1602.h"void main(){InitLcd1602();LcdShowStr(0, 0, "nihao,xiaolin");
}
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.写指令
void LcdSt7565_WriteCmd(cmd){LCD12864_CS=0; //chip select 打开片选LCD12864_RD=1; //disable read 读失能LCD12864_RS=0; //select command 悬着命令LCD12864_RW=0; //slect write 选择写模式_nop_();_nop_();DATA_PORT = cmd; //put command,放置命令_nop_();_nop_();LCD12864_RW = 1; //command writing ,写入命令
}
2.写数据
void LcdSt7565_WriteData(dat)
{ LCD12864_CS = 0; //chip select,打开片选LCD12864_RD = 1; //disable read,读失能 LCD12864_RS = 1; //select data,选择数据LCD12864_RW = 0; //select write,选择写模式_nop_();_nop_();DATA_PORT = dat; //put data,放置数据_nop_();_nop_();LCD12864_RW = 1; //data writing,写数据
}
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)】。
4.对照官方代码进行解析:初始化操作
初始化函数:
(1)第一类指令:时序需要
(2)第二类指令:硬件特性设置需要的(比如屏幕亮度,对比度之类)
(3)第三类指令:显示i参数相关的:A1/A0
/*******************************************************************************
* 函 数 名 : LCD12864_Init
* 函数功能 : 初始化12864
* 输 入 : 无
* 输 出 : 无
* 说 明 : LCD12864的命令指令可以查看例程文件夹下的《ST7565p数据手册》
* * 的第51页的位置。
*******************************************************************************/void Lcd12864_Init()
{uchar i;LCD12864_RSET = 0;//硬件复位for (i=0; i<100; i++);//让内部进行复位LCD12864_CS = 0;//打开片选,选中芯片LCD12864_RSET = 1;//关闭复位//----------------Start Initial Sequence(时序)-------////------程序初始化设置,具体命令可以看文件夹下---////--软件初始化--//LcdSt7565_WriteCmd(0xE2); //软件复位:resetfor (i=0; i<100; i++); //延时一下//--表格第8个命令,0xA0段(左右)方向选择正常方向(0xA1为反方向)--//// 0xA0对应0-127,0xA1对应4-131LcdSt7565_WriteCmd(0xA0); //ADC select segment direction //--表格第15个命令,0xC8普通(上下)方向选择选择反向,0xC0为正常方向--// LcdSt7565_WriteCmd(0xC8); //Common direction //--表格第9个命令,0xA6为设置字体为黑色,背景为白色---////--0xA7为设置字体为白色,背景为黑色---//LcdSt7565_WriteCmd(0xA6); //reverse display//--表格第10个命令,0xA4像素正常显示,0xA5像素全开--//LcdSt7565_WriteCmd(0xA4); //normal display//--表格第11个命令,0xA3偏压为1/7,0xA2偏压为1/9--//LcdSt7565_WriteCmd(0xA2); //bias set 1/9//--表格第19个命令,这个是个双字节的命令,0xF800选择增压为4X;--////--0xF801,选择增压为5X,其实效果差不多--// LcdSt7565_WriteCmd(0xF8); //Boost ratio setLcdSt7565_WriteCmd(0x01); //x4//--表格第18个命令,这个是个双字节命令,高字节为0X81,低字节可以--////--选择从0x00到0X3F。用来设置背景光对比度。---/LcdSt7565_WriteCmd(0x81); //V0 a setLcdSt7565_WriteCmd(0x23);//--表格第17个命令,选择调节电阻率--//LcdSt7565_WriteCmd(0x25); //Ra/Rb set//--表格第16个命令,电源设置。--//LcdSt7565_WriteCmd(0x2F);for (i=0; i<100; i++);//--表格第2个命令,设置显示开始位置--//LcdSt7565_WriteCmd(0x40); //start line//--表格第1个命令,开启显示--//LcdSt7565_WriteCmd(0xAF); // display onfor (i=0; i<100; i++);}
9.清屏操作
/*******************************************************************************
* 函 数 名 : LCD12864_ClearScreen
* 函数功能 : 清屏12864
* 输 入 : 无
* 输 出 : 无
*******************************************************************************/void Lcd12864_ClearScreen(void)
{uchar i, j;for(i=0; i<8; i++)//行--64行分为8页【8个bit位容易操作】{//--表格第3个命令,设置Y的坐标--////--Y轴有64个,一个坐标8位,也就是有8个坐标--////所以一般我们使用的也就是从0xB0到0x07【设置页地址0xB0+(0-7)】,就够了--// LcdSt7565_WriteCmd(0xB0+i); //--表格第4个命令,设置X坐标--////--当你的段初始化为0xA1时【4-131】,X坐标从0x10,0x04到0x18,0x04,一共128位--////--当你的段初始化为0xA0时【0-127】,X坐标从0x10,0x00到0x18,0x00,一共128位--////--在写入数据之后X坐标的坐标是会自动加1的,我们初始化使用0xA1所以--////--我们的X坐标从0x10,0x00开始---//LcdSt7565_WriteCmd(0x10); LcdSt7565_WriteCmd(0x00); //--X轴有128位,就一共刷128次,X坐标会自动加1,所以我们不用再设置坐标--//for(j=0; j<128; j++){LcdSt7565_WriteData(0x00); //如果设置背景为白色时,清屏选择0XFF}}
}
扩展
此时我们设置白背景,黑字
所以0x00显示白字,0xff显示黑字
下面我们设置0xf0【则在一页中,上面四行显示黑色,下面四行显示白色】
//--X轴有128位,就一共刷128次,X坐标会自动加1,所以我们不用再设置坐标--//for(j=0; j<128; j++){LcdSt7565_WriteData(0xf0); //如果设置背景为白色时,清屏选择0XFF}
10.LCD12864显示文字
1.文字显示的原理
(1)字模
(2)像素&显存的对应关系:一一对应
(3)显示函数:将字模丢到正确的显存中去
2.字模的获取
(1)芯片自带字库
(2)网上下载字库
(3)字模生成软件自助生成
3.代码实战显示6*8ASCII码
1.先弄初始化函数和清屏函数
main.c
#include"st7565.h"void main(){Lcd12864_Init();Lcd12864_ClearScreen();while(1);
}
st7565.c
#include "st7565p.h"/*******************************************************************************
* 函 数 名 : LCD12864_WriteCmd
* 函数功能 : 写入一个命令到12864
* 输 入 : cmd
* 输 出 : 无
*******************************************************************************/void LcdSt7565_WriteCmd(cmd)
{LCD12864_CS = 0; //chip select,打开片选LCD12864_RD = 1; //disable read,读失能 LCD12864_RS = 0; //select command,选择命令LCD12864_RW = 0; //select write,选择写模式_nop_();_nop_();DATA_PORT = cmd; //put command,放置命令_nop_();_nop_();LCD12864_RW = 1; //command writing ,写入命令
}/*******************************************************************************
* 函 数 名 : LcdSt7565_WriteData
* 函数功能 : 写入一个数据到12864
* 输 入 : dat
* 输 出 : 无
*******************************************************************************/void LcdSt7565_WriteData(dat)
{ LCD12864_CS = 0; //chip select,打开片选LCD12864_RD = 1; //disable read,读失能 LCD12864_RS = 1; //select data,选择数据LCD12864_RW = 0; //select write,选择写模式_nop_();_nop_();DATA_PORT = dat; //put data,放置数据_nop_();_nop_();LCD12864_RW = 1; //data writing,写数据
}
/*******************************************************************************
* 函 数 名 : LCD12864_Init
* 函数功能 : 初始化12864
* 输 入 : 无
* 输 出 : 无
* 说 明 : LCD12864的命令指令可以查看例程文件夹下的《ST7565p数据手册》
* * 的第51页的位置。
*******************************************************************************/void Lcd12864_Init()
{uchar i;LCD12864_RSET = 0;//硬件复位for (i=0; i<100; i++);//让内部进行复位LCD12864_CS = 0;//打开片选,选中芯片LCD12864_RSET = 1;//关闭复位//----------------Start Initial Sequence(时序)-------////------程序初始化设置,具体命令可以看文件夹下---////--软件初始化--//LcdSt7565_WriteCmd(0xE2); //软件复位:resetfor (i=0; i<100; i++); //延时一下//--表格第8个命令,0xA0段(左右)方向选择正常方向(0xA1为反方向)--//// 0xA0对应0-127,0xA1对应4-131LcdSt7565_WriteCmd(0xA0); //ADC select segment direction //--表格第15个命令,0xC8普通(上下)方向选择选择反向,0xC0为正常方向--// LcdSt7565_WriteCmd(0xC8); //Common direction //--表格第9个命令,0xA6为设置字体为黑色,背景为白色---////--0xA7为设置字体为白色,背景为黑色---//LcdSt7565_WriteCmd(0xA6); //reverse display//--表格第10个命令,0xA4像素正常显示,0xA5像素全开--//LcdSt7565_WriteCmd(0xA4); //normal display//--表格第11个命令,0xA3偏压为1/7,0xA2偏压为1/9--//LcdSt7565_WriteCmd(0xA2); //bias set 1/9//--表格第19个命令,这个是个双字节的命令,0xF800选择增压为4X;--////--0xF801,选择增压为5X,其实效果差不多--// LcdSt7565_WriteCmd(0xF8); //Boost ratio setLcdSt7565_WriteCmd(0x01); //x4//--表格第18个命令,这个是个双字节命令,高字节为0X81,低字节可以--////--选择从0x00到0X3F。用来设置背景光对比度。---/LcdSt7565_WriteCmd(0x81); //V0 a setLcdSt7565_WriteCmd(0x23);//--表格第17个命令,选择调节电阻率--//LcdSt7565_WriteCmd(0x25); //Ra/Rb set//--表格第16个命令,电源设置。--//LcdSt7565_WriteCmd(0x2F);for (i=0; i<100; i++);//--表格第2个命令,设置显示开始位置--//LcdSt7565_WriteCmd(0x40); //start line//--表格第1个命令,开启显示--//LcdSt7565_WriteCmd(0xAF); // display onfor (i=0; i<100; i++);}/*******************************************************************************
* 函 数 名 : LCD12864_ClearScreen
* 函数功能 : 清屏12864
* 输 入 : 无
* 输 出 : 无
*******************************************************************************/void Lcd12864_ClearScreen(void)
{uchar i, j;for(i=0; i<8; i++)//行--64行分为8页【8个bit位容易操作】{//--表格第3个命令,设置Y的坐标--////--Y轴有64个,一个坐标8位,也就是有8个坐标--////所以一般我们使用的也就是从0xB0到0x07【设置页地址0xB0+(0-7)】,就够了--// LcdSt7565_WriteCmd(0xB0+i); //--表格第4个命令,设置X坐标--////--当你的段初始化为0xA1时【4-131】,X坐标从0x10,0x04到0x18,0x04,一共128位--////--当你的段初始化为0xA0时【0-127】,X坐标从0x10,0x00到0x18,0x00,一共128位--////--在写入数据之后X坐标的坐标是会自动加1的,我们初始化使用0xA1所以--////--我们的X坐标从0x10,0x00开始---//LcdSt7565_WriteCmd(0x10); LcdSt7565_WriteCmd(0x00); //--X轴有128位,就一共刷128次,X坐标会自动加1,所以我们不用再设置坐标--//for(j=0; j<128; j++){LcdSt7565_WriteData(0x00); //如果设置背景为白色时,清屏选择0XFF}}
}
st7565.h
#ifndef __ST7565_H
#define __ST7565_H#include<reg51.h>
#include<intrins.h>//---重定义关键词---//
#ifndef uchar
#define uchar unsigned char
#endif#ifndef uint
#define uint unsigned int
#endif//--定时使用的IO口--//
#define DATA_PORT P0
sbit LCD12864_CS = P3^2;
sbit LCD12864_RSET = P3^3;
sbit LCD12864_RS = P2^6;
sbit LCD12864_RW = P2^7;
sbit LCD12864_RD = P2^5;//--定义全局函数--//
void LcdSt7565_WriteCmd(cmd);
void LcdSt7565_WriteData(dat);
void Lcd12864_Init();
void Lcd12864_ClearScreen(void);#endif
2.网上找到6*8ASCII码字库
nios ii 之5110液晶屏(6*8、8*16 ASCII字符,16*16 汉字,常用图标,图案,超全字库+函数代码)_6*8 ascii-CSDN博客
3.编写函数显示数值
我们在编写下面代码遇到的问题:
1)我们需要将模取高位和低位的时候需要分别使用一个变量组装起来
2)字库中对应的ASCII是十六进制,记得加上0x
3)当我们遇到问题的时候一个模块一个模块的检验
//在屏幕的(x,y)坐标处,显示c这个字符
//(x,y)表示像素点的坐标值,所以x范围是0-127,y的范围是0-63
//注意,因为显示文字是以整页为单位的,为了简单起见必须页对齐显示
//因此给的y值必须页首地址,就是0 8 16 24 等数值
void ascii_display(unsigned char x,unsigned char y,unsigned char c){unsigned char i=0;unsigned char x1,x2;//【第一步,设置显示的x和y坐标】//y坐标,其实就是page addressLcdst7565_WriteCmd(0xB0+y/8);//因为只能整页显示,所以我们要除8才能保证//x坐标,只要在范围内别超出就可以了x1=(x>>4) & 0x0f; //显示高4位x2=x& 0x0f; //显示低4位//因为我们要使用2次发送才可以将数据发出Lcdst5765_Write_Cmd(0x10+x1);Lcdst7565_Write_Cmd(0x00+x2);//【第二步,找到c对应的字模】//ASCII_6_8[x-20][0] 字模的第一个字节//【第三步,将字模丢到显存中去】for(i=0;i<6;i++){//因为我们字库是从“20”开始,所以要-20//注意点:我们是十六进制,所以是0x20Lcdst7565_Write_Cmd(ASCII_6_8[c-0x20][i]);}
遗留问题:
(1)初始化和字模不匹配,造成字是反的
(2)初始化不对,造成x坐标是从右往左的
4.解决遗留问题
1.修改初始化代码从左往右显示
(1)先修改初始化函数中的显示方向代码
//--表格第8个命令,0xA0段(左右)方向选择正常方向(0xA1为反方向)--//// 0xA0对应0-127,0xA1对应4-131LcdSt7565_WriteCmd(0xA0); //ADC select segment direction
(2)修改清屏函数
//--表格第4个命令,设置X坐标--////--当你的段初始化为0xA1时【4-131】,X坐标从0x10,0x04到0x18,0x04,一共128位--////--当你的段初始化为0xA0时【0-127】,X坐标从0x10,0x00到0x18,0x00,一共128位--////--在写入数据之后X坐标的坐标是会自动加1的,我们初始化使用0xA1所以--////--我们的X坐标从0x10,0x00开始---//LcdSt7565_WriteCmd(0x10); LcdSt7565_WriteCmd(0x00);
(3)修改显示数值的函数
4.显示跨页(16*16)
(1)超过8*8的字符如何显示
(2)常见汉字字模大小是16*16
zimo.h
#ifndef __ZIMO_H__
#define __ZIMO_H__unsigned char code zimo_zhu[] =
{0x80,0xA0,0x90,0x8E,0x88,0x88,0x88,0xFF,0x88,0x88,0x88,0x88,0x88,0x80,0x80,0x00,
0x20,0x20,0x10,0x08,0x04,0x02,0x01,0xFF,0x01,0x02,0x04,0x08,0x10,0x20,0x20,0x00,};unsigned char code zimo_you[] =
{0x04,0x04,0x04,0x84,0xE4,0x3C,0x27,0x24,0x24,0x24,0x24,0xE4,0x04,0x04,0x04,0x00,
0x04,0x02,0x01,0x00,0xFF,0x09,0x09,0x09,0x09,0x49,0x89,0x7F,0x00,0x00,0x00,0x00,};unsigned char code zimo_peng[] =
{0x00,0xFE,0x22,0xFE,0x00,0xFE,0x22,0xFE,0x00,0xFC,0x16,0x25,0x84,0xFC,0x00,0x00,
0x60,0x1F,0x22,0xBF,0x40,0x3F,0x82,0xFF,0x00,0x13,0x12,0x12,0x52,0x82,0x7E,0x00,};#endif
自定义数值输出
void hanzi_display(unsigned char x,unsigned char y,unsigned char zimo[]){unsigned char i=0;unsigned char x1,x2;//先显示上面一半Lcdst7565_WriteCmd(0xB0+y/8);//x坐标,只要在范围内别超出即可x1=(x>>4)&0x0f;x2=x&0x0f;Lcdst7565_Write(0x10+x1);Lcdst7565_Write(0x00+x2);for(i=0;i<16;i++){ //因为我们是16*16,此时是显示第一页的0-15列Lcdst7565_WriteData(zimo[i]);}//在显示下面一半Lcdst7565_WriteCmd(0xB0+y/8+1);//x坐标,只要在范围内别超出即可x1=(x>>4)&0x0f;x2=x&0x0f;Lcdst7565_Write(0x10+x1);Lcdst7565_Write(0x00+x2);for(i=16;i<32;i++){Lcdst7565_WriteData(zimo[i]);}
}
hanzi_display(0, 0, zimo_zhu);hanzi_display(16, 0, zimo_you);hanzi_display(32, 0, zimo_peng);
使用简单的方式
#ifndef __ZIMO_H__
#define __ZIMO_H__unsigned char code zimo_zhuyoupeng[3][32] =
{
// 朱
{0x80,0xA0,0x90,0x8E,0x88,0x88,0x88,0xFF,0x88,0x88,0x88,0x88,0x88,0x80,0x80,0x00,
0x20,0x20,0x10,0x08,0x04,0x02,0x01,0xFF,0x01,0x02,0x04,0x08,0x10,0x20,0x20,0x00,},
// 有
{0x04,0x04,0x04,0x84,0xE4,0x3C,0x27,0x24,0x24,0x24,0x24,0xE4,0x04,0x04,0x04,0x00,
0x04,0x02,0x01,0x00,0xFF,0x09,0x09,0x09,0x09,0x49,0x89,0x7F,0x00,0x00,0x00,0x00,},
// 鹏
{0x00,0xFE,0x22,0xFE,0x00,0xFE,0x22,0xFE,0x00,0xFC,0x16,0x25,0x84,0xFC,0x00,0x00,
0x60,0x1F,0x22,0xBF,0x40,0x3F,0x82,0xFF,0x00,0x13,0x12,0x12,0x52,0x82,0x7E,0x00,},
};#endif
hanzi_display(16*0, 16, zimo_zhuyoupeng[0]);hanzi_display(16*1, 16, zimo_zhuyoupeng[1]);hanzi_display(16*2, 16, zimo_zhuyoupeng[2]);
11.LCD12864显示图片
1.思路分析
通过取字模软件将图片翻译为一个十六进制的数组
2.图片数据获取
1)取模软件,转换为bmp
2)查看像素
3)调节分辨率---》画图工具
3.写显示函数
// 在屏幕上显示一个图片,从屏幕左上角开始显示
//因为是整个屏幕显示,所以跟清屏函数差不多
void pic_display(unsigned char pic[])
{uchar i, j;uint k = 0;//遍历数组,128*64/8=1024for(i=0; i<8; i++)//每一个page{ LcdSt7565_WriteCmd(0xB0+i); //y轴LcdSt7565_WriteCmd(0x10); //高4位LcdSt7565_WriteCmd(0x00);//低4位 //--X轴有128位,就一共刷128次,X坐标会自动加1,所以我们不用再设置坐标--//for(j=0; j<128; j++){LcdSt7565_WriteData(pic[k++]); //如果设置背景为白色时,清屏选择0XFF}}
}
4.调试
pic_display(pic);
相关文章:

【单片机】16-LCD1602和12864显示器
1.LCD显示器相关背景 1.LCD简介 (1)显示器,常见显示器:电视,电脑 (2)LCD(Liquid Crystal Display),液晶显示器,原理介绍 (3ÿ…...
AUTOSAR从入门到精通-基于 CAN 总线的汽车发电机智能调节器(下)
目录 4.4.3 CAN 通信软件实现 汽车发电机智能调节器试验与结果分析 5.1 试验方案设计...

Windows下Tensorflow docker python开发环境搭建
前置条件 windows10 更新到较新的版本,硬件支持Hyper-V。 参考:https://learn.microsoft.com/zh-cn/windows/wsl/install 启用WSL 在Powershell中输入如下指令: dism.exe /online /enable-feature /featurename:Microsoft-Windows-Subsys…...
idea常用快捷键 idea搜索快捷键
常用快捷键 IntelliJ IDEA 是一款流行的 Java 集成开发环境(IDE),有许多常用的快捷键可以帮助开发者提高效率。以下是一些常用的 IntelliJ IDEA 快捷键: CtrlSpace:基本代码补全,用于输入任何东西&#x…...
Redis Cluster Gossip Protocol: MEET
返回目录 CLUSTER MEET 过程说明 #mermaid-svg-dp95n6LRjBO1mCKE {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-dp95n6LRjBO1mCKE .error-icon{fill:#552222;}#mermaid-svg-dp95n6LRjBO1mCKE .error-text{fill:#…...
TcpConnection的读写操作【深度剖析】
文章目录 前言一、TcpConnection的读二、TcpConnection的写三、TcpConnection的关闭 前言 今天总结TcpConnection类的读写事件。 一、TcpConnection的读 当Poller检测到套接字的Channel处于可读状态时,会调用Channel的回调函数,回调函数中根据不同激活…...
k8s面试题
1 简述etcd及其特点 ETCD是高可用分布式的键值存储系统 特点 1)强一致性:即使部分节点故障,etcd仍能正常工作,并保持数据一致 (强一致性:分布式系统中,更新操作,所有节点读取的数据都是最新的,一致的) 2)高可用:etcd支持数据多副本复制,一个节点挂,其他节点接…...
OpenCV 4.x 版本的新特性都有哪些?
文章大纲 V 4. 0DNNV 4.0 - 4. 8cheatsheetvideo analysis参考文献与学习路径2016年的时候我快研究生毕业了,那时候OpenCV 2.4.x 版本非常的流行,当时3.x 的版本刚发布,很多人都没有用习惯。 我写过一遍笔记: OpenCV 3.0 3.1版本的改进家里还有一本书:《OpenCV 3 计算机视…...
Redisson—分布式集合
7.1. 映射(Map) 基于Redis的Redisson的分布式映射结构的RMap Java对象实现了java.util.concurrent.ConcurrentMap接口和java.util.Map接口。与HashMap不同的是,RMap保持了元素的插入顺序。该对象的最大容量受Redis限制,最大元素数…...

93、Redis 之 使用连接池管理Redis6.0以上的连接 及 消息的订阅与发布
★ 使用连接池管理Redis连接 从Redis 6.0开始,Redis可支持使用多线程来接收、处理客户端命令,因此应用程序可使用连接池来管理Redis连接。 上一章讲的是创建单个连接来操作redis数据库,这次使用连接池来操作redis数据库 Lettuce连接池 支持…...
doris动态分区开启历史分区
举例说明: CREATE TABLE tbl1 (k1 DATE,... ) PARTITION BY RANGE(k1) () DISTRIBUTED BY HASH(k1) PROPERTIES ("dynamic_partition.enable" "true","dynamic_partition.time_unit" "DAY","dynamic_partition.sta…...

Linux用户与权限(认知root用户、修改权限控制 - chmod、修改权限控制 - chown)
目录 1. 认知root用户 1.1 什么是root用户(超级管理员) 1.2 用户切换命令 1.3 sudo命令 1.3.1 为普通用户配置sudo认证 2. 用户、用户组管理 2.1 理解用户、用户组的概念 2.2 掌握用户、用户组管理的相关命令 2.2.1 用户组管理 2.2.2 …...

处理conda安装工具的动态库问题——解决记录 libssl.1.0.0 系统中所有openssl位置全览 whereis openssl
处理conda安装工具的动态库问题——解决记录 处理conda安装工具的动态库问题——解决记录 - 简书 解决libssl.so.1.0.0: cannot open shared object file: No such file or directory问题 - 简书 openssl 默认版本问题(Anaconda相关)_anaconda openssl-…...
如何在Go中格式化字符串
由于字符串通常由书面文本组成,在很多情况下,我们可能希望通过标点符号、换行和缩进来更好地控制字符串的外观,以使其更易于阅读。 在本教程中,我们将介绍一些处理go字符串的方法,以确保所有输出文本的格式正确。 字…...

C程序设计内容与例题讲解 -- 第四章--选择结构程序设计第二部分(第五版)谭浩强
前言:在前面我们学习了选择结构和条件判断,用if语句实现选择结构,关系运算符和关系表达式,逻辑运算符和逻辑表达式等知识。今天我们将接着上一篇未讲完的继续讲解。 鸡汤:种一棵树最好的时间是十年前,其次是现在!加油各…...

接雨水问题
接雨水问题 问题背景 LeetCode 42. 接雨水 接雨水问题是一个经典的计算雨水滞留量的问题,通常使用柱状图来表示不同高度的柱子。在下雨的情况下,柱子之间的凹陷部分能够存储雨水,问题的目标是计算这些柱子所能接收的雨水总量。 相关知识 …...

小谈设计模式(9)—工厂方法模式
小谈设计模式(9)—工厂方法模式 专栏介绍专栏地址专栏介绍 工厂方法模式角色分类抽象产品(Abstract Product)具体产品(Concrete Product)抽象工厂(Abstract Factory)具体工厂&#x…...

Android etc1tool之png图片转换pkm 和 zipalign简介
关于作者:CSDN内容合伙人、技术专家, 从零开始做日活千万级APP。 专注于分享各领域原创系列文章 ,擅长java后端、移动开发、商业变现、人工智能等,希望大家多多支持。 目录 一、导读二、etc1tool2.1、用法 三、zipalign3.1 使用 四…...
Spring Boot快速入门:构建简单的Web应用
SpringBoot Spring Boot是一个用于简化Spring应用程序开发的框架,它通过提供开箱即用的配置和一组常用的功能,使得构建高效、可维护的应用变得非常容易。在本篇博客中,我们将一步步地介绍如何快速入门Spring Boot,并构建一个简单的…...
JAVA 泛型、序列化和复制
泛型提供了编译时类型安全检测机制,该机制允许程序员在编译时检测到非法的类型。泛型的本质是参数化类型,也就是说所操作的数据类型被指定为一个参数。比如我们要写一个排序方法,能够对整型数组、字符串数组甚至其他任何类型的数组进行排序&a…...

IDEA运行Tomcat出现乱码问题解决汇总
最近正值期末周,有很多同学在写期末Java web作业时,运行tomcat出现乱码问题,经过多次解决与研究,我做了如下整理: 原因: IDEA本身编码与tomcat的编码与Windows编码不同导致,Windows 系统控制台…...
挑战杯推荐项目
“人工智能”创意赛 - 智能艺术创作助手:借助大模型技术,开发能根据用户输入的主题、风格等要求,生成绘画、音乐、文学作品等多种形式艺术创作灵感或初稿的应用,帮助艺术家和创意爱好者激发创意、提高创作效率。 - 个性化梦境…...
java_网络服务相关_gateway_nacos_feign区别联系
1. spring-cloud-starter-gateway 作用:作为微服务架构的网关,统一入口,处理所有外部请求。 核心能力: 路由转发(基于路径、服务名等)过滤器(鉴权、限流、日志、Header 处理)支持负…...

51c自动驾驶~合集58
我自己的原文哦~ https://blog.51cto.com/whaosoft/13967107 #CCA-Attention 全局池化局部保留,CCA-Attention为LLM长文本建模带来突破性进展 琶洲实验室、华南理工大学联合推出关键上下文感知注意力机制(CCA-Attention),…...
树莓派超全系列教程文档--(62)使用rpicam-app通过网络流式传输视频
使用rpicam-app通过网络流式传输视频 使用 rpicam-app 通过网络流式传输视频UDPTCPRTSPlibavGStreamerRTPlibcamerasrc GStreamer 元素 文章来源: http://raspberry.dns8844.cn/documentation 原文网址 使用 rpicam-app 通过网络流式传输视频 本节介绍来自 rpica…...

JavaScript 中的 ES|QL:利用 Apache Arrow 工具
作者:来自 Elastic Jeffrey Rengifo 学习如何将 ES|QL 与 JavaScript 的 Apache Arrow 客户端工具一起使用。 想获得 Elastic 认证吗?了解下一期 Elasticsearch Engineer 培训的时间吧! Elasticsearch 拥有众多新功能,助你为自己…...

SCAU期末笔记 - 数据分析与数据挖掘题库解析
这门怎么题库答案不全啊日 来简单学一下子来 一、选择题(可多选) 将原始数据进行集成、变换、维度规约、数值规约是在以下哪个步骤的任务?(C) A. 频繁模式挖掘 B.分类和预测 C.数据预处理 D.数据流挖掘 A. 频繁模式挖掘:专注于发现数据中…...
第25节 Node.js 断言测试
Node.js的assert模块主要用于编写程序的单元测试时使用,通过断言可以提早发现和排查出错误。 稳定性: 5 - 锁定 这个模块可用于应用的单元测试,通过 require(assert) 可以使用这个模块。 assert.fail(actual, expected, message, operator) 使用参数…...
linux 下常用变更-8
1、删除普通用户 查询用户初始UID和GIDls -l /home/ ###家目录中查看UID cat /etc/group ###此文件查看GID删除用户1.编辑文件 /etc/passwd 找到对应的行,YW343:x:0:0::/home/YW343:/bin/bash 2.将标红的位置修改为用户对应初始UID和GID: YW3…...

《基于Apache Flink的流处理》笔记
思维导图 1-3 章 4-7章 8-11 章 参考资料 源码: https://github.com/streaming-with-flink 博客 https://flink.apache.org/bloghttps://www.ververica.com/blog 聚会及会议 https://flink-forward.orghttps://www.meetup.com/topics/apache-flink https://n…...