STM32实战总结:HAL之FSMC控制TFT-LCD

news2024/11/26 20:26:44

什么是FSMC?

FSMC(Flexible Static Memory Controller,可变静态存储控制器)是STM32系列采用的一种新型的存储器扩展技术。在外部存储器扩展方面具有独特的优势,可根据系统的应用需要,方便地进行不同类型大容量静态存储器的扩展。

FSMC(Flexible Static Memory Controller,可变静态存储控制器)是STM32系列中内部集成256 KB以上FlaSh、后缀为xC、xD和xE的高存储密度微控制器特有的存储控制机制。之所以称为“可变”,是由于通过对特殊功能寄存器的设置,FSMC能够根据不同的外部存储器类型,发出相应的数据/地址/控制信号类型以匹配信号的速度,从而使得STM32系列微控制器不仅能够应用各种不同类型、不同速度的外部静态存储器,而且能够在不增加外部器件的情况下同时扩展多种不同类型的静态存储器,满足系统设计对存储容量、产品体积以及成本的综合要求。

FSMC技术优势

①支持多种静态存储器类型。STM32通过FSMC可以与SRAM、ROM、PSRAM、NOR Flash和NANDFlash存储器的引脚直接相连。

②支持丰富的存储操作方法。FSMC不仅支持多种数据宽度的异步读/写操作,而且支持对NOR/PSRAM/NAND存储器的同步突发访问方式。

③支持同时扩展多种存储器。FSMC的映射地址空间中,不同的BANK是独立的,可用于扩展不同类型的存储器。当系统中扩展和使用多个外部存储器时,FSMC会通过总线悬空延迟时间参数的设置,防止各存储器对总线的访问冲突。

④支持更为广泛的存储器型号。通过对FSMC的时间参数设置,扩大了系统中可用存储器的速度范围,为用户提供了灵活的存储芯片选择空间。

⑤支持代码从FSMC扩展的外部存储器中直接运行,而不需要首先调入内部SRAM。

FSMC内部结构

STM32微控制器之所以能够支持NOR Flash和NAND Flash这两类访问方式完全不同的存储器扩展,是因为FSMC内部实际包括NOR Flash和NAND/PC Card两个控制器,分别支持两种截然不同的存储器访问方式。在STM32内部,FSMC的一端通过内部高速总线AHB连接到内核Cortex-M3,另一端则是面向扩展存储器的外部总线。内核对外部存储器的访问信号发送到AHB总线后,经过FSMC转换为符合外部存储器通信规约的信号,送到外部存储器的相应引脚,实现内核与外部存储器之间的数据交互。FSMC起到桥梁作用,既能够进行信号类型的转换,又能够进行信号宽度和时序的调整,屏蔽掉不同存储类型的差异,使之对内核而言没有区别。

FSMC映射地址空间

FSMC管理1 GB的映射地址空间。该空间划分为4个大小为256 MB的BANK,每个BANK又划分为4个64 MB的子BANK,如表1所列。FSMC的2个控制器管理的映射地址空间不同。NOR Flash控制器管理第1个BANK,NAND/PC Card控制器管理第2~4个BANK。由于两个控制器管理的存储器类型不同,扩展时应根据选用的存储设备类型确定其映射位置。其中,BANK1的4个子BANK拥有独立的片选线和控制寄存器,可分别扩展一个独立的存储设备,而BANK2~BANK4只有一组控制寄存器。

什么是PC卡?

PC卡,又称PCMCIA卡,被笔记本电脑广泛用作存储媒体。

一般来说较耗电,但成本较低。

PCMCIA插槽是笔记本电脑上最重要的设备扩展接口,可以用来插入传真卡/网卡/存储卡/声霸卡等等,一些专业杂志甚至预测PCMCIA会成为今后台式电脑、汽车以及家用电器上的标准接口。PCMCIA的主要优势是可以带电插拔,配合适当软件后可以实现即插即用。

除了笔记型计算机可使用 PCMCIA 规格的卡片外,还有 PDA、数字相机、数字电视、机顶盒 ( set-top boxes )…等等也都有对应的产品可以使用PCMCIA规格的卡片。

LCD

什么是LCD?

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


被动发光和主动发光。

有些显示器(譬如LED显示器、CRT显示器)自己本身会发光称为主动发光,有些(LCD)本身不会发光只会透光,需要背光的协助才能看起来是发光的,称为被动发光。


 

液晶应用领域:电视机、电脑显示屏、手机显示屏、工业显示屏等····

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

LCD的显示原理和特点(液晶分子透光+背光)

LCD屏幕的工作原理是怎样的?_哔哩哔哩_bilibili
 

LCD的发展史和种类(TN/STN/TFT)
(1) TN最早。坏处是响应性不够好,有拖尾现象。
(2) STN是TN的升级版。有效解决拖尾现象,显示更清晰。
(3) TFT的最大特点就是超薄。
(4) TFT技术之上发展出来很多更新的技术。


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

扫描
(1)扫描是一个动作而不是一个名字,扫描就是依次将颜色数值放入屏幕中所有的像素的这个过程。
(2)扫描这个词是由最早的CRT显示器遗留下来的,到LCD显示器的年代本来已经失去意义了,但是我们还是延续着这么叫。
(3)显示器的扫描显示原理依赖于人眼的视觉暂留。只要显示器扫描频率大于人眼的发现频率,人眼看到的图像就是恒定的。如果扫描频率偏小人眼就会看到闪动。(扫描频率的概念就叫做刷新率)

驱动器&控制器
LCD驱动器一般和LCD显示面板集成在一起(本来是分开的,做面板的是只做面板的,譬如说三星、LG、台湾的友达、奇美都是做面板的;驱动器也由专门的IC厂商生产;集成厂商买来面板和驱动器后集成在一起做成LCD屏幕),面板只负责里面的液晶分子旋转透光,面板需要一定的模拟电信号来控制液晶分子;LCD驱动器芯片负责给面板提供控制液晶分子的模拟电信号,驱动器的控制信号(数字信号)来自于自己的数字接口,这个接口就是LCD屏幕的外部接口
LCD控制器一般集成在单片机端,他负责通过数字接口向远端的LCD驱动器提供控制像素显示的数字信号。LCD控制器的关键在于时序,它必须按照一定的时序和LCD驱动器通信;LCD控制器受单片机控制,单片机会从内存中拿像素数据给LCD控制器并最终传给LCD驱动器。有的会直接将控制器和驱动器都集成到LCD中。具体要看产品设计。

显示内存(简称:显存)
(1) SoC在内存中挑选一段内存,然后通过配置将LCD控制器和这一段内存(以后称为显存)连接起来构成一个映射关系。一旦这个关系建立之后,LCD控制器就会自动从显存中读取像素数据传输给LCD驱动器。这个显示的过程不需要CPU的参与。
(2) 显示体系建立起来后,CPU就不用再管LCD控制器、驱动器、面板这些东西了;以后CPU就只关心显存了,因为我只要把要显示的图像的像素数据丢到显存中,硬件就会自动响应(屏幕上就能自动看到显示的图像了)。

总结:LCD显示是分为2个阶段的:第一个阶段就是建立显示体系的过程,目的就是CPU初始化LCD控制器使其和显存联系起来构成映射;第二个阶段就是映射建立之后,此阶段主要任务是将要显示的图像丢到显存中去。


LCD显示单位:帧(frame)
(1) 显示器上一整个画面的内容成为一个帧(frame),整个显示器工作时是一帧一帧的在显示。
(2) 电影实际就是以每秒种24帧的速度在播放图片。
(3) 帧内数据:一帧分为多行,一行分为多像素,因此一帧图像其实就是多个像素组成的矩阵。
(4) 帧外数据:整个视频由很多个帧构成,最终播放视频时逐个播放各个图像帧即可。

LCD显示一帧图像的过程
(1)首先把帧分为行,然后再把行分为像素,然后逐个像素去显示。(显示像素:其实就是LCD驱动器按照接收到的LCD控制器给的显示数据,驱动一个像素的液晶分子旋转,让这个像素显示出相应的颜色值的过程)
(2)关键点:LCD控制器和驱动器之间一次只能传一个像素点的显示数据。所以一帧图像在屏幕上其实是串行的依次被显示上去的,不是同一时间显示出来的。

LCD显示的主要相关概念

像素(pixel)
(1)整个图像是由一个个的像素组成的,像素就是一个显示点。

像素间距(pitch)
(1)pitch是连续2个像素的像素中心的距离。一般的像素是方形的,所以横向pitch和纵向的pitch一样的。但是也有不一样的。
(2)像素间距会影响屏幕的最佳观看距离。像素间距大的适合远距离看,像素间距小的适合近距离看。

分辨率(resolution)
(1)整个屏幕的横向和纵向的像素个数就叫分辨率,譬如X210开发板用的屏幕是800×480.
(2)屏幕尺寸和分辨率无关的,像开发板的屏幕尺寸是7寸的(纯屏幕对角线尺寸是7英寸)。
(3)屏幕尺寸和分辨率和像素间距三者之间有关联。

清晰度
(1)清晰度是一个主观概念,是人眼对显示效果的一个主观判断。说白了就是人看起来感觉清晰不清晰。
(2)客观来讲,清晰度由分辨率和像素间距共同决定。一般的,屏幕尺寸固定时分辨率越高越清晰,分辨率越低就越不清晰;分辨率固定下,屏幕尺寸越小越清晰,越大越不清晰。
(3)清晰度还由其他很多因素共同决定。

像素深度(bits per pixel,简称bpp)
(1)一个像素在计算机中由多少个字节数据来描述。
(2)计算机中用二进制位来表示一个像素的数据,用来表示一个像素的数据位越多,则这个像素的颜色值更加丰富、分的更细,颜色深度就更深。
(3)一般来说像素深度有这么几种:1位、8位、16位、24位、32位。

颜色在计算机中的表示
颜色的本质
(1) 颜色是主观存在,颜色其实是自然光在人的眼睛中和大脑中产生的一种映像。
(2) 颜色的本质决定于光的波长。

自然光的颜色是连续的
光的波长是连续的,导致颜色也是连续的。理论上,只要你的眼睛分辨能力足够好,可以在自然界中发现无数种颜色。

计算机中的颜色是离散的
(1)计算机中不可能存储无数种颜色,所以必须将颜色有限化,所以就用有限种颜色来代表自然界中的无限种颜色。这个理论非常类似于之前学过的AD转换。
(2)这种离散化表达颜色的缺点是不够真实,漏掉了很多种颜色。因此计算机中所能表达的颜色没有自然界中丰富(计算机屏幕上显示的图像和真实图像有差别)
(3)计算机所能表达的颜色种类个数,这个参数叫:像素深度bpp。

常见像素深度:1位、8位、16位、24位、32位
1位:用1个二进制位来表示颜色,这种就叫单色显示。示例就是小饭店、理发店门口的LED屏。
8位:用8个二进制位来表示颜色,此时能表示256种颜色。这种叫灰度显示。这时候是黑白的,没有彩色,我们把纯白到纯黑分别对应255到0,中间的数值对应不同的灰。示例就是以前的黑白电视机。
16位:用16个二进制位表示颜色,此时能表示65536种颜色。这时候就可以彩色显示了,一般是RGB565的颜色分布(用5位二进制表示红色、用6位二进制表示绿色、用5位二进制表示蓝色)。这种红绿蓝都有的颜色表示法就是一种模拟自然界中所有颜色的表示方式。但是因为RGB的颜色表达本身二进制位数不够多(导致红绿蓝三种颜色本身分的都不够细致),所以这样显示的彩色失真比较重,人眼能明显看到显示的不真实。
24位:用24个二进制位来表示颜色,此时能表示16777216种颜色。这种表示方式和16位色原理是一样的,只是RGB三种颜色各自的精度都更高了(RGB各8位),叫RGB888。此时颜色比RGB565更加真实细腻,虽然说比自然界无数种颜色还是少了很多,不过由于人眼的不理想性所以人眼几乎不能区分1677万种颜色和无数种颜色的差别了。于是乎就把这种RGB888的表示方法叫做真彩色。(RGB565就是假彩色)
32位:总共用32位二进制来表示颜色,其中24位表示红绿蓝三元色(还是RGB888分布),剩下8位表示透明度。这种显色方式就叫ARGB(A是阿尔法,表示透明度),现在PC机中一般都用ARGB表示颜色。

补充:颜色的组成,三元色(三基色)是RGB,也就是说所有的颜色都可以由红绿蓝三种颜色组成。

TFT-LCD

TFT(Thin Film Transistor)是薄膜晶体管的缩写。

TFT式显示屏是各类笔记本电脑和台式机上的主流显示设备,该类显示屏上的每个液晶像素点都是由集成在像素点后面的薄膜晶体管来驱动,从而可以做到高速度高亮度高对比度显示屏幕信息。TFT式显示器是最好的LCD彩色显示器之一,具有高响应度、高亮度、高对比度等优点。是多数液晶显示器的一种。

同时,TFT式屏幕也普遍应用于中高端彩屏手机中,分65536 色、16 万色,1600万色三种,其显示效果非常出色。

随着九十年代初TFT技术的成熟,彩色液晶平板显示器迅速发展,不到10年的时间,TFT-LCD迅速成长为主流显示器,这与它具有的优点是分不开的。主要特点是:

使用特性好

低压应用,低驱动电压,固体化使用安全性和可靠性提高;平板化,又轻薄,节省了大量原材料和使用空间;低功耗,它的功耗约为CRT显示器的十分之一,反射式TFT-LCD甚至只有CRT的百分之一左右,节省了大量的能源;TFT-LCD产品还有规格型号、尺寸系列化,品种多样,使用方便灵活、维修、更新、升级容易,使用寿命长等许多特点。显示范围覆盖了从1英寸至40英寸范围内的所有显示器的应用范围以及投影大平面,是全尺寸显示终端;显示质量从最简单的单色字符图形到高分辨率,高彩色保真度,高亮度,高对比度,高响应速度的各种规格型号的视频显示器;显示方式有直视型,投影型,透视式,也有反射式。

环保特性好

无辐射、无闪烁,对使用者的健康无损害。特别是TFT-LCD电子书刊的出现,将把人类带入无纸办公、无纸印刷时代,引发人类学习、传播和记栽文明方式的革命。

适用范围宽

从-20℃到+50℃的温度范围内都可以正常使用,经过温度加固处理的TFT-LCD低温工作温度可达到零下80℃。既可作为移动终端显示,台式终端显示,又可以作大屏幕投影电视,是性能优良的全尺寸视频显示终端。

自动化程度

大规模工业化生产特性好。TFT-LCD产业技术成熟,大规模生产的成品率达到90%以上。TFT-LCD易于集成化。是大规模半导体集成电路技术和光源技术的完美结合,继续发展潜力很大。有非晶、多晶和单晶硅TFT-LCD,将来会有其它材料的TFT,既有玻璃基板的又有塑料基板。

FSMC控制TFT-LCD

我们使用FSMC的块1来控制TFT

新出现的存储器PSRAM(pseudo SRAM),称之为伪静态随机存取器。

它具有SRAM的接口协议:给出地址、读写指令,就可以实现数据的存取;相比DRAM的实现,它不需要复杂的memory controller来控制内存单元去定期刷新数据。

为什么FSMC可以控制LCD?因为非复用信号的PSRAM的接口功能和8080接口基本吻合。

其实,只要引脚数量足够,手动模拟时序来读取也可以。

这里是因为刚好FSMC的信号和时序都能匹配得上8080接口,所以直接使用能大大提升效率。

硬件接口

这里的LCD显示采用的是8080接口。用到的LCD驱动器是ILI9341。

ILI9341内部结构如下:

左上角一块为控制器接口,和单片机相连。右侧接口则和LCD相连接。

单片机控制LCD显示,实际上就是和LCD的驱动器进行通信。

LCD常用接口参考:LCD常见接口总结_路溪非溪的博客-CSDN博客

MX配置FSMC

模式选择选项中,就是FSMC的存储块选择。

前四个选项对应块1的四个分区;

NAND Flash1对应块2;

NAND Flash2对应块3;

Compact Flash对应块4。

我们这里选择NOR Flash/PSRAM/SRAM/ROM/LCD1即可(也可以选另外三个分区)

Chip Select

Memory type

LCD的数据/命令选择端口

可以选择任意一根地址线,但是要看实际的硬件到底是连到了哪个引脚。

数据位宽

选完后,下方默认即可。

这里的2、5、0也保持默认,影响的是FSMC的时序周期。

另外,背光是单独控制的,配置其连接的引脚即可。

驱动程序

要想LCD显示,先要调通驱动控制。

/* Includes ------------------------------------------------------------------*/
#include "MyApplication.h"

/* Private define-------------------------------------------------------------*/

/* Private variables----------------------------------------------------------*/
static void LCD_Init(void);                                                 //LCD屏幕初始化
static void LCD_FillColor(uint16_t,uint16_t,uint16_t,uint16_t,LCD_Color_t); //LCD屏幕填充颜色

/* Public variables-----------------------------------------------------------*/
TFT_LCD_t TFT_LCD = 
{
	0,
	
	LCD_Init,
	LCD_FillColor
};

/* Private function prototypes------------------------------------------------*/
static uint32_t LCD_ReadID(void);                                //LCD读取ID
static void LCD_Disp_Direction(void);                            //LCD显示方向
static void LCD_SetWindows(uint16_t,uint16_t,uint16_t,uint16_t); //设置LCD显示窗口

/*
	* @name   LCD_ReadID
	* @brief  LCD读取ID
	* @param  None
	* @retval LCD_ID -> 返回LCD屏幕ID    
*/
static uint32_t LCD_ReadID(void)
{
	uint32_t LCD_ID = 0;
	uint32_t buf[4];
	
	LCD_Write_CMD(0xD3);
	buf[0] = LCD_Read_DATA();        // 第一个读取数据无效
	buf[1] = LCD_Read_DATA()&0x00FF; // 只有低8位数据有效
	buf[2] = LCD_Read_DATA()&0x00FF; // 只有低8位数据有效
	buf[3] = LCD_Read_DATA()&0x00FF; // 只有低8位数据有效
	
	LCD_ID = (buf[1] << 16) + (buf[2] << 8) + buf[3];
	return LCD_ID;
}

/*
	* @name   LCD_Init
	* @brief  LCD屏幕初始化
	* @param  None
	* @retval None      
*/
static void LCD_Init(void)
{
	//读取LCD屏幕ID
	TFT_LCD.ID = LCD_ReadID();
	printf("The ID of TFT LCD is 0x%.6X\r\n",TFT_LCD.ID);
	
	//2.8inch ILI9341初始化
	LCD_Write_CMD(0xCF);  
	LCD_Write_DATA(0x00); 
	LCD_Write_DATA(0xC9);   //C1 
	LCD_Write_DATA(0x30); 
	LCD_Write_CMD(0xED);  
	LCD_Write_DATA(0x64); 
	LCD_Write_DATA(0x03); 
	LCD_Write_DATA(0X12); 
	LCD_Write_DATA(0X81); 
	LCD_Write_CMD(0xE8);  
	LCD_Write_DATA(0x85); 
	LCD_Write_DATA(0x10); 
	LCD_Write_DATA(0x7A); 
	LCD_Write_CMD(0xCB);  
	LCD_Write_DATA(0x39); 
	LCD_Write_DATA(0x2C); 
	LCD_Write_DATA(0x00); 
	LCD_Write_DATA(0x34); 
	LCD_Write_DATA(0x02); 
	LCD_Write_CMD(0xF7);  
	LCD_Write_DATA(0x20); 
	LCD_Write_CMD(0xEA);  
	LCD_Write_DATA(0x00); 
	LCD_Write_DATA(0x00); 
	LCD_Write_CMD(0xC0);    //Power control 
	LCD_Write_DATA(0x1B);   //VRH[5:0] 
	LCD_Write_CMD(0xC1);    //Power control 
	LCD_Write_DATA(0x00);   //SAP[2:0];BT[3:0] 01 
	LCD_Write_CMD(0xC5);    //VCM control 
	LCD_Write_DATA(0x30); 	//3F
	LCD_Write_DATA(0x30); 	//3C
	LCD_Write_CMD(0xC7);    //VCM control2 
	LCD_Write_DATA(0XB7); 
	//LCD_Write_CMD(0x36);    // Memory Access Control 
	//LCD_Write_DATA(0x08); 
	LCD_Disp_Direction();   //设置LCD显示方向
	LCD_Write_CMD(0x3A);   
	LCD_Write_DATA(0x55); 
	LCD_Write_CMD(0xB1);   
	LCD_Write_DATA(0x00);   
	LCD_Write_DATA(0x1A); 
	LCD_Write_CMD(0xB6);    // Display Function Control 
	LCD_Write_DATA(0x0A); 
	LCD_Write_DATA(0xA2); 
	LCD_Write_CMD(0xF2);    // 3Gamma Function Disable 
	LCD_Write_DATA(0x00); 
	LCD_Write_CMD(0x26);    //Gamma curve selected 
	LCD_Write_DATA(0x01); 
	LCD_Write_CMD(0xE0);    //Set Gamma 
	LCD_Write_DATA(0x0F); 
	LCD_Write_DATA(0x2A); 
	LCD_Write_DATA(0x28); 
	LCD_Write_DATA(0x08); 
	LCD_Write_DATA(0x0E); 
	LCD_Write_DATA(0x08); 
	LCD_Write_DATA(0x54); 
	LCD_Write_DATA(0XA9); 
	LCD_Write_DATA(0x43); 
	LCD_Write_DATA(0x0A); 
	LCD_Write_DATA(0x0F); 
	LCD_Write_DATA(0x00); 
	LCD_Write_DATA(0x00); 
	LCD_Write_DATA(0x00); 
	LCD_Write_DATA(0x00); 		 
	LCD_Write_CMD(0XE1);    //Set Gamma 
	LCD_Write_DATA(0x00); 
	LCD_Write_DATA(0x15); 
	LCD_Write_DATA(0x17); 
	LCD_Write_DATA(0x07); 
	LCD_Write_DATA(0x11); 
	LCD_Write_DATA(0x06); 
	LCD_Write_DATA(0x2B); 
	LCD_Write_DATA(0x56); 
	LCD_Write_DATA(0x3C); 
	LCD_Write_DATA(0x05); 
	LCD_Write_DATA(0x10); 
	LCD_Write_DATA(0x0F); 
	LCD_Write_DATA(0x3F); 
	LCD_Write_DATA(0x3F); 
	LCD_Write_DATA(0x0F); 
	LCD_Write_CMD(0x2B); 
	LCD_Write_DATA(0x00);
	LCD_Write_DATA(0x00);
	LCD_Write_DATA(0x01);
	LCD_Write_DATA(0x3f);
	LCD_Write_CMD(0x2A); 
	LCD_Write_DATA(0x00);
	LCD_Write_DATA(0x00);
	LCD_Write_DATA(0x00);
	LCD_Write_DATA(0xef);	 
	LCD_Write_CMD(0x11); //Exit Sleep
	HAL_Delay(120);
	LCD_Write_CMD(0x29); //display on		
  
	TFT_LCD_BL_ON; //打开背光	 
}

/*
	* @name   LCD_Disp_Directio
	* @brief  LCD显示方向
	* @param  None
	* @retval None      
*/
static void LCD_Disp_Direction()
{
	switch(LCD_DIRECTION)
	{
		case 1:	LCD_Write_CMD(0x36); LCD_Write_DATA(1<<3); break;
		case 2: LCD_Write_CMD(0x36); LCD_Write_DATA((1<<3)|(1<<5)|(1<<6)); break;
		case 3: LCD_Write_CMD(0x36); LCD_Write_DATA((1<<3)|(1<<7)|(1<<4)|(1<<6)); break;
		case 4: LCD_Write_CMD(0x36); LCD_Write_DATA((1<<3)|(1<<7)|(1<<5)|(1<<4)); break;
		default:LCD_Write_CMD(0x36); LCD_Write_DATA(1<<3); break;			
	}
}

/*
	* @name   LCD_SetWindows
	* @brief  设置LCD显示窗口
	* @param  xStar  ->窗口的起点X坐标
						yStar  ->窗口的起点Y坐标
						xWidth ->窗口的宽度
						yHeight->窗口的高度
	* @retval None      
*/
static void LCD_SetWindows(uint16_t xStar, uint16_t yStar,uint16_t xWidth,uint16_t yHeight)
{	
	LCD_Write_CMD(LCD_CMD_SETxOrgin);	
	LCD_Write_DATA(xStar>>8);
	LCD_Write_DATA(0x00FF&xStar);		
	LCD_Write_DATA((xStar+xWidth-1)>>8);
	LCD_Write_DATA((xStar+xWidth-1)&0xFF);

	LCD_Write_CMD(LCD_CMD_SETyOrgin);
	LCD_Write_DATA(yStar>>8);
	LCD_Write_DATA(0x00FF&yStar);		
	LCD_Write_DATA((yStar+yHeight-1)>>8);
	LCD_Write_DATA((yStar+yHeight-1)&0xFF);

	LCD_Write_CMD(LCD_CMD_WRgram); //开始写入GRAM		
}	

/*
	* @name   LCD_FillColor
	* @brief  LCD屏幕填充颜色
	* @param  xStar  ->窗口的起点X坐标
						yStar  ->窗口的起点Y坐标
						xWidth ->窗口的宽度
						yHeight->窗口的高度 
						FillColor -> 填充色
	* @retval None      
*/
static void LCD_FillColor(uint16_t xStar, uint16_t yStar,uint16_t xWidth,uint16_t yHeight,LCD_Color_t FillColor)
{
	uint16_t i,j;
	//uint16_t k;
	
	//设置窗口
	LCD_SetWindows(xStar,yStar,xWidth,yHeight);
	//填充颜色
	for(i=xStar;i<(xStar+xWidth);i++)
	{
		for(j=0;j<(yStar+yHeight);j++)
		{
			LCD_Write_DATA(FillColor);
			//动态观看屏幕显示过程
			//for(k=0;k<100;k++);
		}
	}
}
/********************************************************
  End Of File
********************************************************/

LCD显示的关键是写入各种字符或者图片的“模”,将对应的数据码传输给驱动器。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/50130.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

计算机网络 HTTP

概念 Web 基础 HTTP &#xff08;HyperText Transfer Protocol&#xff0c;超文本传输协议&#xff09;。WWW &#xff08;World Wide Web&#xff09;的三种技术&#xff1a;HTML、HTTP、URL。RFC&#xff08;Request for Comments&#xff0c;征求意见书&#xff09;&#…

HTTP DDOS攻击有什么类型和特点?

一、攻击类型 1、 HTTP floods 该攻击类型分为HTTP GET request floods和HTTP POST request floods两种形式&#xff0c;第一种攻击者通过构造HTTP GET请求报文&#xff0c;向目标服务器发送针对特定资源的大量请求&#xff1b;一条HTTP请求的成本很低&#xff0c;但是目标服…

力扣(LeetCode)124. 二叉树中的最大路径和(C++)

深度优先遍历 自底向上的递归。 对于二叉树&#xff0c;我们令每个结点作为 LCALCALCA (最近公共祖先)&#xff0c; 结点 uuu 作为 LCALCALCA &#xff0c; 经过它的最大路径 往左子树的最大路径 往右子树的最大路径 它自己的路径 。 有 ansmax(ans,vulrans max(ans,v_ul…

MobPush 厂商通道SDK集成指南

开发工具&#xff1a;Android Studio 集成方式&#xff1a;Gradle在线集成 安卓版本支持&#xff1a;minSdkVersion 19 集成准备 MobPush快速集成 在使用厂商通道之前&#xff0c;请确保您已申请MobTech开发者账号并已按照MobPush快速集成文档进行集成&#xff0c;本篇文档将…

POI实现Excel导入和导出(源码测试)

因为实际开发中很多需求都需要实现Excel批量导入和导出&#xff0c;所以今天就来写一个后端demo实现Excel的导入和导出。 需求&#xff1a; Excel的导入 1对文件路径为D:\Users\Mixi\IdeaProjects\javapoi-anli\product-test.xlsx 的Excel文件导入到数据库&#xff1b; Excel的…

SAP 采购订单免费标识自动勾选的判断依据

SAP采购订单的免费标识没有专门的字段存储,是根据发票收据和项目类别计算出来的 写程序的时候折磨判断呢? 1.EKPO-REPOS <> ‘X’ AND EKPO-PSTYP <> ‘2’ AND EKPO-PSTYP <> ‘7’ &#xff0c;则系统会自动勾选上这个免费项目 2.如果要求不是很精密&…

机器学习之MATLAB代码--LSTM-SVRNN(五)

机器学习之MATLAB代码--LSTM-SVRNN&#xff08;五&#xff09;代码数据结果代码 1、cdmnn.m文件 %% 组合模型 %% %% 数据导入 clc;clear;warning off; data xlsread(nndata.xlsx, sheet1, A2:G350); load LSTMoutput load SVMoutput %% nwholelength(data); %计算数据长度…

Vue笔记_transition组件(过渡样式)

目录transition组件作用过渡时机语法1语法2使用-animation侦动画使用-过渡动画总结transition组件 作用 transition组件的作用是 给 单个 元素/组件 添加过渡效果&#xff1b; transition-group组件的作用是给 多个 元素/组件 添加过渡效果&#xff1b; 过渡时机 vue只有在…

【pen200-lab】10.11.1.13

pen200-lab 学习笔记 【pen200-lab】10.11.1.13 &#x1f525;系列专栏&#xff1a;pen200-lab &#x1f389;欢迎关注&#x1f50e;点赞&#x1f44d;收藏⭐️留言&#x1f4dd; &#x1f4c6;首发时间&#xff1a;&#x1f334;2022年11月30日&#x1f334; &#x1f36d;作…

turtlebot2利用turtlebot_exploration_3d进行自主建图

安装octomap_ros和rviz插件 sudo apt-get install ros-indigo-octomap*源码安装&#xff1a;turtlebot_exploration_3d(本机为Ubuntu16对应的ros版本为kinetic&#xff0c;但是无对应的版本&#xff0c;用的是ubuntu14的indigo&#xff0c;版本向前兼容&#xff0c;故可以运行&…

AXWWriter兼容的Word处理元素

AXWWriter兼容的Word处理元素 AXWWriter是一个与MS Word兼容的Word处理元素。该部件不需要设置任何其他库或软件。 AXWWriter使用DOCXReadWrite一起工作,DOCXReadWriter也包含在内。有关其他属性,请查看DOCXReadWrite。AXWWriter不难使用。如果您了解DOCXReadWrite,那么您已…

岩藻多糖-聚已内酯 Fucoidan-PCL 聚已内酯-PEG-岩藻多糖

岩藻多糖-聚已内酯 Fucoidan-PCL 聚已内酯-PEG-岩藻多糖 中文名称&#xff1a;岩藻多糖-聚已内酯 英文名称&#xff1a;Fucoidan-PCL 别称&#xff1a;PCL修饰岩藻多糖&#xff0c;PCL-岩藻多糖 聚己内酯&#xff08;Polycaprolactone&#xff0c;PCL&#xff0c;CAS号…

第4部分 RIP

动态路由协议包括距离向量路由协议和链路状态路由协议。RIP&#xff08;Routing Information Protocol&#xff0c;路由信息协议&#xff09;是使用最广泛的距离微向量路由协议。RIP 是为小型网络环境设计的&#xff0c;国为这类协议是路由学习及路由更新将产生较大的流量&…

一文看懂MySQL的行锁

MySQL的全局锁和表锁可以看这篇文章&#xff1a;MySQL的全局锁和表锁 进入正文 行锁 行锁是由各个存储引擎自己实现的&#xff0c;并不是所有的引擎都支持行锁。 MyISAM引擎就不支持行锁&#xff0c;同一时刻一张表只能有一个更新在执行。 现在说InnoDB的行锁&#xff0c;行…

[附源码]计算机毕业设计springboot家庭医生签约服务管理系统

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis Maven Vue 等等组成&#xff0c;B/S模式 M…

你在终端启动的进程,最后都是什么下场?(上)

你在终端启动的进程&#xff0c;最后都是什么下场&#xff1f;&#xff08;上&#xff09; 前言 在本篇文章当中&#xff0c;主要给大家介绍我们在终端启动的进程都是怎么结束的&#xff0c;在我们登录终端和退出终端都发生了什么&#xff1f; 基本介绍 首先我们需要了解的…

从Android系统启动→app启动→activity启动和渲染的整个流程

引言 本文讲解从开机到app显示画面的流程&#xff0c;但不分析源码&#xff0c;如果想阅读源码请到参考文章中查阅。 本文把这段流程分为三部分&#xff1a; 从开机到显示应用列表从点击应用图标到Activity创建成功从Activity创建成功到显示画面 从开机到显示应用列表 先看…

Java-CC

漏洞原理 TransformedMap这个类的decorate函数可以将一个普通的Map转换为一个TransformedMap&#xff0c;其第2、3参数分别对应当key改变和value改变时需要做的操作。所以此时如果修改其中的任意key或value&#xff0c;就会触发我们预先定义好的某些操作来对Map进行处理&#…

pytorch初学笔记(十四):损失函数

目录 一、损失函数 1.1 L1损失函数 1.1.1 简介 1.1.2 参数设定 1.1.3 代码实现 1.2 MSE损失函数&#xff08;平方和&#xff09; 1.2.1 简介 1.2.2 参数介绍 1.2.3 代码实现 1.3 损失函数的作用 二、在神经网络中使用loss function 2.1 使用交叉熵损失函数 2.2 …

【软件测试】资深测试聊一聊,测试架构师是怎么样的,做一名成功的测试工程师......

目录&#xff1a;导读前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结&#xff08;尾部小惊喜&#xff09;前言 测试架构师 测试架…