LX12864P1屏幕使用介绍(ST7567驱动),显示横线、字符、图形
创始人
2024-02-02 16:01:13
0

LX12864P1屏幕显示(ST7567驱动)

可编辑12864液晶模组,也就是液晶显示屏是有128*64个点阵组成。12864是一种图形点阵液晶显示器,它主要采用动态驱动原理由行驱动—控制器和列驱动器两部分组成了128(列)×64(行)的全点阵液晶显示此显示器采用了COB的软封装方式,通过导电橡胶和压框连接LCD,使其寿命长,连接可靠。

产品特性编辑工作电压为+5V±10%,可自带驱动LCD所需的负电压,全屏幕点阵,点阵数为128(列)×64(行),可显示8(行)×4(行)个(16×16点阵)汉字,字符16(行)x8(行)个(8 .x 8)也可完成图形字符的显示,与CPU接口采用SPI通讯方式,驱动ST7567

LCD12864DDRAM示意图

在这里插入图片描述

驱动芯片ST7567 DDRAM示意图

ST7567芯片可写入的页有0 ~ 8 共9页,列有132列,但LCD12864只用到了8页和64列

在这里插入图片描述

写入数据的点阵显示效果

在这里插入图片描述

主控芯片与ST7567的通信方式

通信方式有并行的6800和8080,以及串行的4线方式,本次实验使用了4线串行通信,CSB为片选引脚,数据传输前拉低CSB,A0引脚说明传输的是数据还是指令,如果A0为0,说明是指令,如果为1,说明是数据,SCL为时钟线,SDA为数据/指令线,SCL为低电平时放数据或指令,SCL为高电平是ST7567读取SDA上的电平信号
在这里插入图片描述

LX12864官方手册(带参考代码):https://download.csdn.net/download/weixin_46251230/86731882

参考代码说明

1、LCD初始化函数中行扫描顺序的指令是0xC0,指令说明从上到下扫描,从屏幕上看则最下面是Page0,从下往上直到Page7

2、默认的g_ucComTable数组控制页的访问顺序,默认从Page3开始,若调用 LX12864_ShowChar(0,0,‘A’);函数显示一个字符时,因为字符A高16位,所以占两页,会在Page3开始显示,到Page2结束

3、若想Page0在屏幕的最上边,则初始化时行扫描顺序指令要改为0xC8

4、如果此时g_ucComTable数组不变,则也是从Page3开始显示,再往上显示到Page2,再调用LX12864_ShowChar(0,0,‘A’);则会显示倒着的A

5、如果把g_ucComTable数组改为{0,1,2,3,4,5,6,7},若调用LX12864_ShowChar(3,0,‘A’),则字符A也会倒着显示,并且字符A的上半部分倒着显示在Page3,下半部分倒着显示在Page4,不是想要的效果

6、重新用取模软件取模字符A,则会正常显示

对参考代码进行修改:

1、初始化函数中写入0xC8指令,控制Page0是在屏幕的最上面(根据屏幕实际摆放)

2、将g_ucComTable数组改为{0,1,2,3,4,5,6,7},或者后续可以把函数中的g_ucComTable操作去掉

3、把ASCII码全部重新取模一遍,因为参考代码的字模数组要用特定的数组来显示的,通用性不太好,自己进行修改

代码

GPIO要先初始化

在这里插入图片描述

/*** @name   gpio_Init* @brief  GPIO初始化* @param  None* @retval None*/	
void gpio_Init(void)
{GPIO_InitTypeDef        GPIO_InitStructure;/* GPIOB Periph clock enable */RCC_AHBPeriphClockCmd(CLK_GPIO, ENABLE);/*Configure GPIO_PIN*/GPIO_InitStructure.GPIO_Pin = BL|SI|SCL|A0|RS|CS;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;GPIO_Init(PORT, &GPIO_InitStructure);GPIO_SetBits(PORT,CS);GPIO_SetBits(PORT,SCL);GPIO_SetBits(PORT,SI);
}

BL:背光

SI(SDA):数据/指令线

SCL:时钟线

A0:说明是数据还是指令

RS:复位

CS:片选

写命令

/*** @name   LX12864_WrCmd* @brief  写命令串口模式下只能写不能读,也不能查忙,因此用户要控制好速度不要太快* @param  ucCmd:命令字节* @retval None*/	
void LX12864_WrCmd(uint8_t ucCmd)
{uint8_t i;GPIO_ResetBits(PORT,CS);                                            /* CS片选引脚输出低电平 */GPIO_ResetBits(PORT,A0);                                            /* A0引脚输出低电平,说明是指令 */for(i=0;i<8;i++){GPIO_ResetBits(PORT,SCL);if(ucCmd&0x80){GPIO_SetBits(PORT,SI);}else{GPIO_ResetBits(PORT,SI);}		GPIO_SetBits(PORT,SCL);delay_us(10);ucCmd=(ucCmd<<1);}GPIO_SetBits(PORT,CS);
}

写数据

/*** @name   LX12864_WrData* @brief  写数据* @param  ucData:数据字节* @retval None   */
void LX12864_WrData(uint8_t ucData)
{   uint8_t i;GPIO_ResetBits(PORT,CS);                                            /* CS片选引脚输出低电平 */GPIO_SetBits(PORT,A0);                                              /* A0引脚输出高电平,说明是数据 */for(i=0;i<8;i++){GPIO_ResetBits(PORT,SCL);if(ucData&0x80){GPIO_SetBits(PORT,SI);}else{GPIO_ResetBits(PORT,SI);}GPIO_SetBits(PORT,SCL);delay_us(10);ucData=(ucData<<1);}GPIO_SetBits(PORT,CS);
}

初始化

/*** @name   LX12864_Init* @brief  LX12864初始化* @param  None* @retval None   */
void LX12864_Init(void)
{GPIO_ResetBits(PORT,RS);                                            /* 硬复位 */delay_us(20);GPIO_SetBits(PORT,RS);delay_us(20);LX12864_WrCmd(0xE2);												/* 软复位 */delay_us(50);LX12864_WrCmd(0x2C);											    /* 升压步骤1 */delay_us(50);LX12864_WrCmd(0x2E);												/* 升压步骤2 */delay_us(50);LX12864_WrCmd(0x2F);												/* 升压步骤3 */delay_us(50);LX12864_WrCmd(0x24);												/* 调整对比度,设置范围0x20~0x27 */LX12864_WrCmd(0x81);												/* 微调对比度 */LX12864_WrCmd(0x1B);												/* 微调对比度的值 */LX12864_WrCmd(0xA3);	                                            /* 偏压比(bias),0xA2:1/9   0xA3:1=1/7  */LX12864_WrCmd(0xA6);	                                            /* 正常显示 */LX12864_WrCmd(0xA4);	                                            /* 全部点阵打开	*/LX12864_WrCmd(0xC8);	                                            /* 行扫描顺序:从上到下 */LX12864_WrCmd(0xA0);	                                            /* 列扫描顺序:从左到右 */LX12864_WrCmd(0x40);	                                            /* 起始行:第一行开始 */LX12864_WrCmd(0xAF);	                                            /* 开显示 */LX12864_Open_BL();                                                  /* 显示背光 */
}

LCD初始化指令

在这里插入图片描述

初始化命令中,设置对比度由两条指令组成,一定要先发送指令0x81,告诉ST7567接下来的一条指令是设置对比度的,再发送对比度的值,例如0x1B,由6位来控制;

设置行扫描顺序或者列扫描顺序时需要根据屏幕来设定,因为屏幕摆放的方向不同,则行列的显示也会不同

填充屏幕


/*** @name   LX12864_FillScreen* @brief  填充屏幕* @param  ucFillData:填充的数据* @retval None   */
void LX12864_FillScreen(uint8_t ucFillData)
{uint16_t i,j;for(i=0;i<8;i++){LX12864_WrCmd(0xB0|i);	                                        /* 设置页地址 */LX12864_WrCmd(0x10);	                                        /* 设置列地址的高位 */LX12864_WrCmd(0x00);	                                        /* 设置列地址的低位 */for(j=0;j<128;j++){LX12864_WrData(ucFillData);}}
}

填充一页

/*** @name   LX12864_FillPage* @brief  填充一页* @param  ucFillData:填充的数据* @retval None   */
void LX12864_FillPage(uint8_t ucPage,uint8_t ucFillData)
{uint16_t i;LX12864_WrCmd(0xB0|ucPage);	                                        /* 设置页地址 */LX12864_WrCmd(0x10);	                                            /* 设置列地址的高位 */LX12864_WrCmd(0x00);	                                            /* 设置列地址的低位 */for(i=0;i<128;i++){LX12864_WrData(ucFillData);}
}

显示一条横线

/*** @name   LX12864_ShowHorLine* @brief  显示一条横线* @param  ucPage:页地址 范围:0 ~ 7* @param  ucCol:列地址 范围:0 ~ 127* @param  ucLen:长度 范围:0 ~ 127* @param  ucData:数据* @retval None   */
void LX12864_ShowHorLine(uint8_t  ucPage,uint8_t  ucCol,uint8_t  ucLen,uint8_t  ucData)
{uint8_t i;LX12864_WrCmd((ucPage&0x07)|0xB0);	                                /* 设置页地址 */LX12864_WrCmd((ucCol>>4)|0x10);	                                    /* 设置列地址高位 */LX12864_WrCmd(ucCol&0x0F);                                          /* 设置列地址低位 */for(i=0;iLX12864_WrData(ucData);}
}

显示一条竖线

/*** @name   LX12864_ShowVerLine* @brief  显示一条竖线* @param  ucStartPage:起始页地址 范围:0 ~ 7* @param  ucCol:列地址* @param  ucEndPage:结束页地址 范围:0 ~ 7 注意:结束页地址要大于或等于起始页地址* @retval None   */
void LX12864_ShowVerLine(uint8_t  ucStartPage,uint8_t  ucCol,uint8_t  ucEndPage)
{uint8_t i,ucTemp;ucTemp = (ucEndPage - ucStartPage)+1;for(i=0;iLX12864_WrCmd((ucStartPage&0x07)|0xB0);	                        /* 设置页地址 */LX12864_WrCmd((ucCol>>4)|0x10);	                                /* 设置列地址高位 */LX12864_WrCmd(ucCol&0x0F);                                      /* 设置列地址低位 */LX12864_WrData(0xFF);ucStartPage++;}
}

显示字符

typedef enum
{g_enBigNumber,g_enSmallNumber,
}__ENCHARARRAY_T;/*** @name   LX12864_ShowChar* @brief  显示字符* @param  ucPage:页地址 范围:0 ~ 7* @param  ucCol:列地址 范围:0 ~ 127* @param  ucWidth:字体宽度* @param  ucHight:字体高度* @param  ucChar:字符* @param  ucCharArray:字模数组* @retval None   */
void LX12864_ShowChar(uint8_t ucPage, uint8_t ucCol, uint8_t ucWidth, uint8_t ucHight,uint8_t ucChar,__ENCHARARRAY_T ucCharArray)
{uint8_t i,j,ucNeedPage;uint16_t ucIndex = 0;ucNeedPage = ucHight / 8;if((ucHight%8) != 0){ucNeedPage = ucNeedPage+1;                                      /* 加上不够一页的部分 */}for(i=0;iLX12864_WrCmd((ucPage&0x07)|0xB0);	                            /* 设置页地址 */LX12864_WrCmd((ucCol>>4)|0x10);	                                /* 设置列地址高位 */LX12864_WrCmd(ucCol&0x0F);                                      /* 设置列地址低位 */for(j=0;jif(ucCharArray == g_enBigNumber){LX12864_WrData(g_ucBigNumber[ucChar][ucIndex]);         /* 大字体字模显示字符 */ucIndex++;}else if(ucCharArray == g_enSmallNumber){LX12864_WrData(g_ucSmallNumber[ucChar][ucIndex]);       /* 小字体字模显示字符 */ucIndex++;}}ucPage++;}
}

设置页地址时,参数ucPage为想要显示字符的页数,因为页被分为了0 ~ 7页, 一共8页,只用3位二进制位即可遍历8页,28 = 3,所以&0x07是为了取出ucPage的低3位,再或上0xB0,就设置了想要显示的页

/* 小字体的字模数组 */
unsigned char g_ucSmallNumber[][24]={
{0xC0,0xE0,0x70,0x30,0x30,0x70,0xE0,0xC0,0x3F,0x7F,0xE0,0xC0,0xC0,0xE0,0x7F,0x3F,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"0",0*/
/* (8 X 17 , Arial, 加粗 )*/
{0x00,0x80,0xC0,0x60,0xF0,0xF0,0x00,0x00,0x00,0x01,0x00,0x00,0xFF,0xFF,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"1",1*/
/* (8 X 17 , Arial, 加粗 )*/
{0xC0,0xE0,0x70,0x30,0x30,0x30,0xE0,0xC0,0xC0,0xE0,0xF0,0xD8,0xDC,0xCE,0xC7,0xC1,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"2",2*/
…………………………
};

用PCtoLCD2002取模软件取出想要显示的字符,本次实验用二维数组保存字模数据,根据参数ucChar作为下标去找到要显示的字符的一位数组,再遍历数组写入数据

显示有符号整型数

 /*** @name 	Pow* @brief 	求sBase的sPower次方* @param 	sBase:底数* @param 	sPower:次方数* @retval	返回次方后的结果*/
int16_t Pow(int16_t sBase,int16_t sPower)
{uint8_t i;int16_t sResult = 1;for(i = 0; i < sPower; i++){sResult *= sBase;}return sResult;
}/*** @name   LX12864_ShowVariableNum* @brief  显示有符号的整型数* @param  ucPage:页地址,范围:0 ~ 7* @param  ucCol:列地址,范围:0 ~ 127* @param  ucWidth:字符宽度* @param  ucHight:字符高度* @param  ucNumLen:待显示数字的位数* @param  sNum:待显示的数字* @param  ucCharArray:字模数组* @retval None   */
void LX12864_ShowSignedNum(uint8_t  ucPage,uint8_t  ucCol,uint8_t  ucWidth,uint8_t  ucHight,uint8_t  ucNumLen,int16_t  sNum,__ENCHARARRAY_T ucCharArray)
{uint8_t i;int16_t sNumTemp,sResult;if(sNum >= 0){LX12864_ShowChar(ucPage,ucCol-(ucWidth+2),ucWidth,ucHight,11,ucCharArray);           /* 11对应空白,如果是正数则去掉负号 */sNumTemp = sNum;}else{LX12864_ShowChar(ucPage,ucCol-(ucWidth+2),ucWidth,ucHight,10,ucCharArray);           /* 10对应字符'-',负数则在前面加上负号 */sNumTemp = -sNum;}for(i=ucNumLen;i>0;i--){sResult = sNumTemp/Pow(10,i-1)%10;                                        /* 从高位开始,取出数字的每一位 */LX12864_ShowChar(ucPage,ucCol+((ucWidth+2)*(ucNumLen-i)),ucWidth,ucHight,sResult,ucCharArray);/*显示数字 */}
}

其中Pow函数的用法参考了之前写的LCD1602代码,可以参考
http://t.csdn.cn/mMBIA

显示图形

图形需要用取模软件生成

/*** @name   LX12864_ShowBmp* @brief  显示图形* @param  ucPage:页地址 范围:0 ~ 7* @param  ucCol:列地址 范围:0 ~ 127* @param  ucWidth:图形宽度* @param  ucHight:图形高度* @param  pucBmp:图形字模数组指针* @retval None   */
void LX12864_ShowBmp(uint8_t ucPage, uint8_t ucCol, uint8_t ucWidth, uint8_t ucHight,uint8_t* pucBmp)
{uint8_t i,j,ucNeedPage;uint16_t ucIndex = 0;ucNeedPage = ucHight / 8;                                           /* 所需页数 */if((ucHight%8) != 0){ucNeedPage = ucNeedPage+1;                                      /* 加上不够一页的部分 */}for(i=0;iLX12864_WrCmd((ucPage&0x07)|0xB0);	                            /* 设置页地址 */LX12864_WrCmd((ucCol>>4)|0x10);	                                /* 设置列地址高位 */LX12864_WrCmd(ucCol&0x0F);                                      /* 设置列地址低位 */for(j=0;jLX12864_WrData(pucBmp[ucIndex]);                            /* 显示图形 */ucIndex++;}ucPage++;}
}

LCD实现显示亮一会,暗一会

实现亮一会,暗一会主要通过修改对比度来实现

在LCD_Init初始化函数中,有对比度的设置

LX12864_WrCmd(0x81);												/* 微调对比度 */
LX12864_WrCmd(0x1B);												/* 微调对比度的值 */

在这里插入图片描述

要先写入指令0x81,说明是后续的一个字节是修改对比度的

后续这个字节的是6位的,EV5和EV4的值会影响屏幕显示,有下面三种情况

0x1B:

正常显示(屏幕有点坏)

在这里插入图片描述

0x2B:

会显示填充整个128x64屏幕的黑点,“腾讯QQ”显示会比较暗,正面看看不清

在这里插入图片描述

如果从侧面看则可以看清

在这里插入图片描述

0x3B:

正面看看不到显示内容,屏幕全填充

在这里插入图片描述

侧面看也有黑点
在这里插入图片描述

所以调整对比度就只能设置EV3 ~ EV0这4位,高两位的EV4设置为1,EV5设置为0,才能正常显示

经过测试,0x1F对比度最高,显示内容很清晰,值越小则对比度越低,显示内容逐渐变暗,0x10时几乎看不见显示的内容

在主函数循环中,通过改变对比度的值,再加上适当的延时,就可以让显示内容亮一会,暗一会

/*
* @name   Run
* @brief  系统运行
* @param  None
* @retval None      
*/
void Run(void)
{LX12864_WrCmd(0x81);												/* 微调对比度 */LX12864_WrCmd(0x1B);						                		/* 亮 */LCD_ShowBmp(g_ucBmp1);delay_ms(2000);delay_ms(2000);LX12864_WrCmd(0x81);												/* 微调对比度 */LX12864_WrCmd(0x15);												/* 微亮 */LCD_ShowBmp(g_ucBmp1);delay_ms(2000);delay_ms(2000);
}

LCD12864最终显示界面

在这里插入图片描述

右上角的WiFi显示一会亮,一会灭

实现思路:因为改变对比度是对一整个屏幕而言的,没发现有对某一部分屏幕改变对比度的方法,所以对WiFi显示的字模数组全部改为0x00,则WiFi图形这一部分就显示空白,WiFi图形显示1秒后再写入全是0x00的字模数组,则可以对WiFi图形擦除,擦除1秒后再显示,则可以达到闪烁的目标

相关内容

热门资讯

有趣的事情作文 有趣的事情作文200字(精选20篇)  在学习、工作、生活中,大家或多或少都会接触过作文吧,借助作文...
云优秀作文 云优秀作文云优秀作文1  深秋那湛蓝湛蓝的天空上,团团白云像棉花一样在空中无忧无虑地漂浮着。  那牛...
企鹅作文 企鹅作文  企鹅是唯一不能飞的潜水性海鸟。共有17个品种,分布在南半球,南极数量极多。  企鹅的头、...
雨中即景作文 雨中即景作文(精选10篇)  无论是在学校还是在社会中,说到作文,大家肯定都不陌生吧,写作文是培养人...
描写秋晨的作文 描写秋晨的作文(通用36篇)  在我们平凡的日常里,大家都不可避免地会接触到作文吧,作文根据体裁的不...
柳暗花明作文700字 柳暗花明作文700字(通用49篇)  在学习、工作乃至生活中,许多人都写过作文吧,作文是由文字组成,...
威风的孟加拉虎作文 威风的孟加拉虎作文  10月1日 星期二 天气晴  威风的孟加拉虎  今天中午,我和妈妈一起来到动物...
兴趣作文600字 兴趣作文600字4篇  在学习、工作、生活中,大家都不可避免地会接触到作文吧,作文根据写作时限的不同...
2022启航作文 2022启航作文(精选12篇)  在平平淡淡的日常中,大家都尝试过写作文吧,作文是由文字组成,经过人...
成长作文600字 关于成长作文600字4篇  在我们平凡的日常里,大家都不可避免地会接触到作文吧,作文要求篇章结构完整...
成长标准的议论文 成长标准的议论文  在现实的学习、工作中,说到论文,大家肯定都不陌生吧,论文是对某些学术问题进行研究...
孤独记叙文 孤独记叙文  相信大家都尝试过写作文吧,特别是作文中不可忽视的记叙文,记叙文的样式有消息、通讯、游记...
校庆的800字作文 校庆的800字作文(精选8篇)  在日常生活或是工作学习中,大家总免不了要接触或使用作文吧,作文是通...
难忘的一堂课作文500字 难忘的一堂课作文500字(精选10篇)  在平平淡淡的日常中,大家都不可避免地会接触到作文吧,作文一...
猜猜她是谁300字作文 猜猜她是谁300字作文(通用31篇)  在生活、工作和学习中,大家都写过作文吧,作文一定要做到主题集...
行走在消逝中作文700字 行走在消逝中作文700字  消逝,是一个令人怅惘的词语,它可以标志着国家文明的消亡,也可以表达人离去...
以悔为题的作文 以悔为题的作文(精选35篇)  在现实生活或工作学习中,大家最不陌生的就是作文了吧,作文是人们把记忆...
杨梅树作文400字 杨梅树作文400字  无论在学习、工作或是生活中,大家一定都接触过作文吧,通过作文可以把我们那些零零...
桃花的作文450字 桃花的作文450字  无论在学习、工作或是生活中,大家都接触过作文吧,写作文可以锻炼我们的独处习惯,...
教训作文400字 教训作文400字(精选39篇)  在平时的学习、工作或生活中,大家都跟作文打过交道吧,写作文可以锻炼...