打印
[其他ST产品]

基于STM32(ARM)开发显示屏TFT-LCD经验分享

[复制链接]
1948|17
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
两只袜子|  楼主 | 2023-4-12 10:20 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
ARM, CD, LCD, ST, STM



一、常见显示器类型介绍

显示器属于输出设备,它是一种将特定电子信息输出到屏幕上再反射到人眼的显示工具。常见显示器有三类:CRT显示器、LCD液晶显示器和LED点阵显示器。

CRT显示器:CRT显示器是靠电子束激发屏幕内表面的荧光粉来显示图像的,由于荧光粉被点亮后很快会熄灭,所以电子枪必须循环地不断激发这些点。


LCD显示器:液晶显示器,简称 LCD(Liquid Crystal Display),相对于上一代 CRT显示器,LCD 显示器具有功耗低、体积小、承载的信息量大及不伤眼的优点,因而它成为了现在的主流电子显示设备,其中包括电视、电脑显示器、手机屏幕及各种嵌入式设备的显示器。


液晶是一种介于固体和液体之间的特殊物质,它是一种有机化合物,常态下呈液态,但是它的分子排列却和固体晶体一样非常规则,因此取名液晶。如果给液晶施加电场,会改变它的分子排列,从而改变光线的传播方向,配合偏振光片,它就具有控制光线透过率的作用,再配合彩色滤光片,改变加给液晶电压大小,就能改变某一颜色透光量的多少。利用这种原理,做出可控红、绿、蓝光输出强度的显示结构,把三种显示结构组成一个显示单位,通过控制红绿蓝的强度,可以使该单位混合输出不同的色彩,这样的一个显示单位被称为像素。注意: 液晶本身是不发光的,所以需要有一个背光灯提供光源。


LED显示器:LED点阵彩色显示器的单个像素点内包含红绿蓝三色LED灯,通过控制红绿蓝颜色的强度进行混色,实现全彩颜色输出,多个像素点构成一个屏幕。由于每个像素点都是LED灯自发光的,所以在户外白天也显示得非常清晰,但由于LED灯体积较大,导致屏幕的像素密度低,所以它一般只适合用于广场上的巨型显示器。相对来说,单色的LED点阵显示器应用得更广泛,如公交车上的信息展示牌、店广告牌等。


OLED显示器:新一代的OLED显示器与LED点阵彩色显示器的原理类似,但由于它采用的像素单元是“有机发光二极管”(Organic Light Emitting Diode),所以像素密度比普通LED点阵显示器高得多。OLED显示器具有不需要背光源、对比度高、轻薄、视角广及响应速度快等优点。待到生产工艺更加成熟时,必将取代现在液晶显示器的地位。


使用特权

评论回复
沙发
两只袜子|  楼主 | 2023-4-12 10:20 | 只看该作者
二、显示器的基本参数

像素:是组成图像的最基本单元要素,显示器的像素指它成像最小的点,即前面讲解液晶原理中提到的一个显示单元。

分辨率: 一些嵌入式设备的显示器常常以“行像素值x列像素值”表示屏幕的分辨率。如分辨率800x480表示该显示器的每一行有800个像素点,每一列有480个像素点,也可理解为有800列,480行。


色彩深度:指显示器的每个像素点能表示多少种颜色,一般用“位”(bit)来表示。如单色屏的每个像素点能表示亮或灭两种状态(即实际上能显示2种颜色),用1个数据位就可以表示像素点的所有状态,所以它的色彩深度为1bit,其它常见的显示屏色深为16bit、24bit。

显示器尺寸:显示器的大小一般以英寸表示,如5英寸、21英寸、24英寸等,这个长度是指屏幕对角线的长度,通过显示器的对角线长度及长宽比可确定显示器的实际长宽尺寸

显存:液晶屏中的每个像素点都是数据,在实际应用中需要把每个像素点的数据缓存起来,再传输给液晶屏,一般会使用 SRAM 或 SDRAM 性质的存储器,而这些专门用于存储显示数据的存储器,则被称为显存。显存一般至少要能存储液晶屏的一帧显示数据。

如分辨率为 800x480 的 液 晶 屏  使 用 RGB888 格 式 显 示 , 它 的 一 帧 显 示 数 据 大 小 为 :3(字节)x800x480=1152000 字 节 ;若 使 用 RGB565 格 式 显 示 , 一 帧 显 示 数 据 大 小 为 :2(字节)x800x480=768000 字节。

一般来说,外置的液晶控制器会自带显存,而像 STM32F429等集成液晶控制器的芯片可使用内部 SRAM或外扩 SDRAM用于显存空间

三、TFT-LCD控制框图

STM32F429 系列的芯片不需要额外的液晶控制器(可以理解为常规意义上的显卡),也就是说它把专用液晶控制器的功能集成到STM32F429芯片内部了,可以理解为电脑的CPU集成显卡。而 STM32F407 系列的芯片由于没有集成液晶控制器到芯片内部,所以它只能驱动自带控制器的屏幕,可以理解为电脑的外置显卡。

带有液晶控制器的显示面板工作时,STM32将数据写到LCD控制器的显存里,LCD控制器将显存中的数据渲染到显示面板上进行显示。而不带液晶控制器的面板,也就是MCU自集成了液晶控制器,MCU会在自己的内存中开辟一部分用作为液晶控制器的显存。


四、TFT-LCD控制原理

TFT-LCD结构:完整的显示屏由液晶显示面板、电容触摸面板以及 PCB底板构成

1.液晶显示面板:用于显示图像,文字的彩色显示设备

2.触摸面板:触摸面板带有触摸控制芯片,该芯片处理触摸信号并通过引出的信号线与外部器件通讯,触摸面板中间是透明的,它贴在液晶面板上面,一起构成屏幕的主体

3.PCB 底板:PCB 底板上可能会带有“液晶控制器芯片”因为控制液晶面板需要比较多的资源,所以大部分低级微控制器都不能直接控制液晶面板,需要额外配套一个专用液晶控制器来处理显示过程,外部微控制器只要把它希望显示的数据直接交给液晶控制器即可。而不带液晶控制器的PCB底板,只有小部分的电源管理电路,液晶面板的信号线与外部微控制器相连,直接控制。


五、RGB-LCD控制原理


RGB信号线:RGB信号线各有8根,分别用于表示液晶屏一个像素点的红、绿、蓝颜色分量。使用红绿蓝颜色分量来表示颜色是一种通用的做法,打开Windows系统自带的画板调色工具,可看到颜色的红绿蓝分量值,常见的颜色表示会在“RGB”后面附带各个颜色分量值的数据位数,如RGB565格式表示红绿蓝的数据线数分别为5、6、5根,一共为16个数据位,可表示216种颜色;如果液晶屏的种颜色分量的数据线有8根,那它表示RGB888格式,一共24位数据线,可表示的颜色为224种。


同步时钟信号CLK:液晶屏与外部使用同步通讯方式,以CLK信号作为同步时钟,在同步时钟的驱动下,每个时钟传输一个像素点数据。

水平同步信号HSYNC:水平同步信号HSYNC(Horizontal Sync)用于表示液晶屏一行像素数据的传输结束,每传输完成液晶屏的一行像素数据时,HSYNC会发生电平跳变,如分辨率为800x480的显示屏(800列,480行),传输一帧的图像HSYNC的电平会跳变480次。

垂直同步信号VSYNC:垂直同步信号VSYNC(Vertical Sync)用于表示液晶屏一帧像素数据的传输结束,每传输完成一帧像素数据时,VSYNC会发生电平跳变。其中“帧”是图像的单位,一幅图像称为一帧,在液晶屏中,一帧指一个完整屏液晶像素点。人们常常用“帧/秒”来表示液晶屏的刷新特性,即液晶屏每秒可以显示多少帧图像,如液晶屏以60帧/秒的速率运行时,VSYNC每秒钟电平会跳变60次。
数据使能信号DE:数据使能信号DE(Data Enable)用于表示数据的有效性,当DE信号线为高电平时,RGB信号线表示的数据有效。

LCD数据传输时序
一个VSYNC(即一帧)包含若干个HSYNC(即若干行),而一个HSYNC包含若干个像素点(一个24位数据)


液晶屏显示的图像可看作一个矩形,液晶屏有一个显示指针,它指向将要显示的像素。显示指针的扫描方向方向从左到右、从上到下,一个像素点一个像素点地描绘图形。这些像素点的数据通过RGB数据线传输至液晶屏,它们在同步时钟CLK的驱动下一个一个地传输到液晶屏中,交给显示指针,传输完成一行时,水平同步信号HSYNC电平跳变一次,而传输完一帧时VSYNC电平跳变一次。


液晶显示指针在行与行之间,帧与帧之间切换时需要延时,而且HSYNC及VSYNC信号本身也有宽度,这些时间参数说明见下表:


使用特权

评论回复
板凳
两只袜子|  楼主 | 2023-4-12 10:21 | 只看该作者
六、SSD1963液晶控制器

液晶驱动芯片或LCD驱动器,其内部有着较大的缓存空间可以存储文字、图像等数据,并能够将这些信息送入液晶模块进行显示,由于专用的芯片,因此速度往往比较快。
LCD驱动芯片的主要功能就是对主机发送过来的数据/命令,进行变换,变成每个像素的RGB数据,使之在屏幕上显示出来。常见的液晶驱动芯片有ILI932、ILI9328、SSD1963、HX8347、ILI9341、NT5510等。

SSD1963特性:内部包含1215KB frame buffer(显存)、支持分辨率为864*480的显示屏、支持像素位深为24bpp的显示模式(RGB888)。后面我们使用4.3寸TFT LCD真彩屏(分辨率480x272 )RGB565的方式进行实验。


8080传输效率比SPI传输效率更高,因此管脚足够的情况下采用8080时序

STM32与LCD电器连线图如下:


8080时序-写数据/命令

  • //用GPIO管脚模拟8080时序
  • void LCD_WR_Byte(uint8_t dat, uint8_t cmd)
  • {
  •   LCD_Data_Out(dat);        //放入数据
  • if(cmd)
  •       LCD_DC_Set();        //传命令
  • else
  •       LCD_DC_Clr();       //传数据
  • LCD_CS_Clr();           //拉低片选
  • LCD_WR_Clr();           //写使能
  • LCD_WR_Set();           //WR产生上升沿,数据锁存
  • LCD_CS_Set();           //取消片选
  • LCD_DC_Set();           //复位DC信号线
  • }

复制代码


注:STM32通过8080接口与SSD1963 芯片进行通讯,实现对液晶屏的控制。通讯的内容主要包括命令和显存数据,显存数据即各个像素点的RGB565内容;命令是指对SSD1963的控制指令,MCU 可通过8080接口发送命令编码控制 SSD1963的工作方式,例如复位指令、设置光标指令、睡眠。

FSMC模拟8080时序


重要的时序参数如下:时间相对长一点,也不能过大,否则屏幕刷新时间就会变成长,视觉上表现卡顿。



对于FSMC和8080接口,前四种信号线都是完全一样的,仅仅是FSMC的地址信号线A[25:0]与8080的数据/命令选择线D/C#有区别。为了模拟出8080时序,我们可以把FSMC的A0地址线(选择地址线的一条)与SSD1963芯片8080接口的D/C#信号线连接,那么当A0为高电平时(即D/C#为高电平),数据线D[15:0]的信号会被SSD1963理解为数据,若A0为低电平时(即D/C#为低电平),传输的信号则会被理解为命令。

关于如何让控制A0电平的高低,首先要清楚,LCD控制器的片选连入到FSMC的NE4管脚。所以当发出0x6C000000-0x6FFF FFFF之间的地址时NE4输出低电平,选中LCD控制器,那么A0作为原来地址线的最低位,要调整地址使得A0为0。


可以看到显示器在传输过程中并没有高低字节控制的选项(在读写SRAM的过程中,使用掩码信号LB#与UB#指示要访问目标地址的高、低字节部分),也就是说液晶控制器(显存)与MCU之间一次就要传输16位数据。

在实际控制时,以上地址计算方式还不完整,根据《STM32 参考手册》对 FSMC 访问NOR FLASH (LCD读写数据的方式与NOR FLASN几乎是一样的,都是16位,但是FSMC 访问NOR FLASH具有高低字节控制选项)的说明STM32 内部访问地址时使用的是内部 HADDR 总线, HADDR[25:0] 包含外部存储器地址。由于 HADDR 为字节地址(一次传输8位),而存储器按字寻址,所以根据存储器数据宽度不同,实际向存储器发送的地址也将有所不同,如下表所示。

因此发出一个地址后,只看第二低位。最低位表示一个字节的单位,而第二低位表示两个字节的单位。读者可类比10进制数取余,十进制数的读到最后一位表示几个1,而读到倒数第二位表示几个10,这样回到二进制,读到最后一位表示有几个字节,读到第二低位表示有多少个字(2字节,而又刚刚好对应二进制,没有余数)。

若读者当下理解困难可记住结论:发出一个地址后会自动对该地址左移1位,就是真正的地址,如果还想保持原来的地址,在发地址之前先把地址右移。

0x6C000000    低电平表示命令         
0x6C000002    高电平表示数据


LCD 测试
步骤:
1.配置RCC

2.配置FSMC



根据上图进行时序大小的设定,图中单位是ns,(读者需根据不同发开发设备进行调试,没有固定值)


使用特权

评论回复
地板
两只袜子|  楼主 | 2023-4-12 10:21 | 只看该作者
3.编程
  • //lcd.c
  • #include "lcd.h"
  • #include "font.h"
  • #include "stdlib.h"
  • #define MAX_HZ_POSX 480
  • #define MAX_HZ_POSY 227
  • #define LCD_RAM    *(__IO uint16_t *) (0x6C000002)    //数据寄存器
  • #define LCD_REG    *(__IO uint16_t *) (0x6C000000)//指令寄存器
  • #define rw_data_prepare()               write_cmd(34)
  • void write_cmd(unsigned short cmd);
  • unsigned short read_data(void);
  • unsigned short DeviceCode;
  • /*
  • *
  • */
  • void write_cmd(unsigned short cmd)
  • {
  • LCD_REG = cmd;
  • }
  • unsigned short read_data(void)
  • {
  • unsigned short temp;
  • temp = LCD_RAM;
  • temp = LCD_RAM;
  • return temp;
  • }
  • void write_data(unsigned short data_code )
  • {
  • LCD_RAM = data_code;
  • }
  • void write_reg(unsigned char reg_addr,unsigned short reg_val)
  • {
  • write_cmd(reg_addr);
  • write_data(reg_val);
  • }
  • unsigned short read_reg(unsigned char reg_addr)
  • {
  • unsigned short val=0;
  • write_cmd(reg_addr);
  • val = read_data();
  • return (val);
  • }
  • void lcd_SetCursor(unsigned int x,unsigned int y)
  • {
  • write_reg(0x004e,x);    /* 0-239 */
  • write_reg(0x004f,y);    /* 0-319 */
  • }
  • /*读取指定地址的GRAM */
  • static unsigned short lcd_read_gram(unsigned int x,unsigned int y)
  • {
  • unsigned short temp;
  • lcd_SetCursor(x,y);
  • rw_data_prepare();
  • /* dummy read */
  • temp = read_data();
  • temp = read_data();
  • return temp;
  • }
  • static void lcd_data_bus_test(void)
  • {
  • unsigned short temp1;
  • unsigned short temp2;
  • /* wirte */
  • lcd_SetCursor(0,0);
  • rw_data_prepare();
  • write_data(0x5555);
  • lcd_SetCursor(1,0);
  • rw_data_prepare();
  • write_data(0xAAAA);
  • /* read */
  • lcd_SetCursor(0,0);
  • temp1 = lcd_read_gram(0,0);
  • temp2 = lcd_read_gram(1,0);
  • if( (temp1 == 0x5555) && (temp2 == 0xAAAA) )
  • {
  • //printf(" data bus test pass!\r\n");
  • }
  • else
  • {
  • //printf(" data bus test error: %04X %04X\r\n",temp1,temp2);
  • }
  • }
  • void lcd_clear(unsigned short Color)
  • {
  •   unsigned int count;
  • write_cmd(0x002a); //发送列地址:起始-结束
  • write_data(0);
  • write_data(0);
  • write_data(HDP>>8);
  • write_data(HDP&0x00ff);
  •   write_cmd(0x002b); //发送行地址:起始-结束
  • write_data(0);
  • write_data(0);
  • write_data(VDP>>8);
  • write_data(VDP&0x00ff);
  • write_cmd(0x002c);//写frame buffer命令
  • for(count=0;count<130560;count++){
  • write_data(Color);
  • }
  • }
  • void lcd_init(void)
  • {
  • //GPIO_SetBits(GPIOF,GPIO_Pin_9);
  • HAL_Delay(50);
  • DeviceCode = read_reg(0x0000);
  •   write_cmd(0x002b);
  • write_data(0);
  • HAL_Delay(50); // delay 50 ms
  • write_cmd(0x00E2);//PLL multiplier, set PLL clock to 120M
  • write_data(0x001D);//N=0x36 for 6.5M, 0x23 for 10M crystal
  • write_data(0x0002);
  • write_data(0x0004);
  • write_cmd(0x00E0);//PLL enable
  • write_data(0x0001);
  • HAL_Delay(10);
  • write_cmd(0x00E0);
  • write_data(0x0003);
  • HAL_Delay(12);
  • write_cmd(0x0001);  //software reset
  • HAL_Delay(10);
  • write_cmd(0x00E6);//PLL setting for PCLK, depends on resolution
  • //LCD_WriteRAM(0x0001);
  • //LCD_WriteRAM(0x0033);
  • //LCD_WriteRAM(0x0032);
  • write_data(0x0000);
  • write_data(0x00D9);
  • write_data(0x0016);
  • write_cmd(0x00B0);//LCD SPECIFICATION
  • write_data(0x0020);
  • write_data(0x0000);
  • write_data((HDP>>8)&0X00FF);//Set HDP
  • write_data(HDP&0X00FF);
  •     write_data((VDP>>8)&0X00FF);//Set VDP
  • write_data(VDP&0X00FF);
  •     write_data(0x0000);
  • write_cmd(0x00B4);//HSYNC
  • write_data((HT>>8)&0X00FF); //Set HT
  • write_data(HT&0X00FF);
  • write_data((HPS>>8)&0X00FF);//Set HPS
  • write_data(HPS&0X00FF);
  • write_data(HPW);//Set HPW
  • write_data((LPS>>8)&0X00FF); //Set HPS
  • write_data(LPS&0X00FF);
  • write_data(0x0000);
  • write_cmd(0x00B6);//VSYNC
  • write_data((VT>>8)&0X00FF);   //Set VT
  • write_data(VT&0X00FF);
  • write_data((VPS>>8)&0X00FF); //Set VPS
  • write_data(VPS&0X00FF);
  • write_data(VPW);//Set VPW
  • write_data((FPS>>8)&0X00FF);//Set FPS
  • write_data(FPS&0X00FF);
  • //=============================================
  • //=============================================
  • write_cmd(0x00BA);
  • write_data(0x0005);           //0x000F);    //GPIO[3:0] out 1
  • write_cmd(0x00B8);
  • write_data(0x0007);    //GPIO3=input, GPIO[2:0]=output
  • write_data(0x0001);    //GPIO0 normal
  • write_cmd(0x0036); //rotation
  • write_data(0x0000);
  • HAL_Delay(50);
  • write_cmd(0x00BE); //set PWM for B/L
  • write_data(0x0006);
  • write_data(0x0080);
  • write_data(0x0001);
  • write_data(0x00f0);
  • write_data(0x0000);
  • write_data(0x0000);
  • write_cmd(0x00d0);//设置动态背光控制设置
  • write_data(0x000d);
  • write_cmd(0x00F0); //pixel data interface
  • write_data(0x0003);//03:16位 02:位»
  • write_cmd(0x0029); //display on
  • //lcd_data_bus_test();
  • lcd_clear(Yellow);//初始化全屏填充颜色
  • }
  • /*********************************************************************************************************
  • ** Functoin name:       LCD_SetCursor
  • ** Descriptions:        设置做标
  • ** input paraments:     Xpos、Ypos坐标
  • ** output paraments:    无
  • ** Returned values:     无
  • *********************************************************************************************************/
  • void LCD_SetCursor(uint16_t Xpos, uint16_t Ypos)
  • {
  • write_cmd(0x002A);
  • write_data(Xpos>>8);
  • write_data(Xpos&0x00ff);
  • write_data(479>>8);
  • write_data(479&0x00ff);
  •   write_cmd(0x002b);
  • write_data(Ypos>>8);
  • write_data(Ypos&0x00ff);
  • write_data(271>>8);
  • write_data(271&0x00ff);
  • }
  • /*********************************************************************************************************
  • ** Functoin name:       LCD_DrawPoint
  • ** Descriptions:        画点
  • ** input paraments:     x.y:画点的坐标
  • color:颜色
  • ** output paraments:    无
  • ** Returned values:     无
  • *********************************************************************************************************/
  • void LCD_DrawPoint(uint16_t xsta, uint16_t ysta, uint16_t color)
  • {
  • LCD_SetCursor(xsta, ysta);  /*设置光标位置 */
  • write_data_Prepare();          /*开始写入GRAM */
  • write_data(color);
  • }
  • /**
  • *名称:void WriteOneHz(uint16_t x0, uint16_t y0, uint8_t *pucMsk, uint16_t PenColor, uint16_t BackColor)
  • *参数:x0,y0起始坐标
  •    *pucMsk   指向
  •    PenColor  字符颜色
  •    BackColor 背景颜色
  • *功能:
  • *备注:此函数不能单独作为汉字字符显示
  • **/
  • void WriteOneHz(uint16_t x0, uint16_t y0, uint8_t *pucMsk, uint16_t PenColor, uint16_t BackColor)
  • {
  •     uint16_t i,j;
  •     uint16_t mod[16];                                      /* 当前字模 16*16 */
  •     uint8_t *pusMsk;                                       /* 当前字库地址  */
  •     uint16_t y;
  •     pusMsk = pucMsk;
  •     for(i=0; i<16; i++)                   /*保存当前汉字点阵字模式       */
  •     {
  •         mod = (*pusMsk << 8) | (*(pusMsk + 1));  /*取得当前字模,合并为半字对齐访问    */
  • pusMsk = pusMsk+2;
  •     }
  •     y = y0;
  •     for(i=0; i<16; i++)                                    /* 16行   */
  •     {
  •         for(j=0; j<16; j++)                                /* 16列   */
  •         {
  • if((mod << j) & 0x8000)       /* 显示第1行,共16个点*/
  • {
  • LCD_DrawPoint(x0+j, y0+i, PenColor);
  • }
  • else
  • {
  • LCD_DrawPoint(x0+j, y0+i, BackColor);
  • }
  •         }
  •         y++;
  •     }
  • }
  • /**
  • *名称: uint16_t findHzIndex(uint8_t *hz)
  • *参数:hz
  • *功能:索引汉字存储的内存地址
  • *备注
  • **/
  • uint16_t findHzIndex(uint8_t *hz)     /* 在自定义汉字库查找要显示的汉字的位置 */
  • {
  • uint16_t i=0;
  • FNT_GB16 *ptGb16 = (FNT_GB16 *)GBHZ_16;/*ptGb16指向BHZ_16*/
  • while(ptGb16.Index[0] > 0x80)
  • {
  • if ((*hz == ptGb16.Index[0]) && (*(hz+1) == ptGb16.Index[1]))
  •                 /*汉字用两位来表示地址码*/
  • {
  • return i;
  • }
  •     i++;
  •     if(i > (sizeof((FNT_GB16 *)GBHZ_16) / sizeof(FNT_GB16) - 1))  /*搜索下标约束*/
  •     {
  • break;
  •     }
  • }
  • return 0;
  • }
  • /**
  • *名称:void LCD_ShowHzString(uint16_t x0, uint16_t y0, uint8_t *pcStr, uint16_t PenColor, uint16_t BackColor)
  • *参数:x0,y0   起始坐标
  •    pcStr     指向
  •    PenColor  字体颜色
  •    BackColor 字体背景
  • *功能:显示汉字字符串
  • *备注:这个函数不能单独调用
  • **/
  • void LCD_ShowHzString(uint16_t x0, uint16_t y0, uint8_t *pcStr, uint16_t PenColor, uint16_t BackColor)
  • {
  • uint16_t usIndex;
  • uint8_t size = 16;
  • FNT_GB16 *ptGb16 = 0;
  •     ptGb16 = (FNT_GB16 *)GBHZ_16;
  • if(x0>MAX_HZ_POSX){x0=0;y0+=size;}/*超出x轴字体最小单位,换行*/
  •         if(y0>MAX_HZ_POSY){y0=x0=0;lcd_clear(White);}   /*超出r轴字体最小单位,回到原点,并且清屏*/
  •          usIndex = findHzIndex(pcStr);
  • WriteOneHz(x0, y0, (uint8_t *)&(ptGb16[usIndex].Msk[0]),  PenColor, BackColor); /* 显示字符*/
  • }
  • /**
  • *名称:void LCD_ShowChar(uint8_t x, uint16_t y, uint8_t num, uint8_t size, uint16_t PenColor, uint16_t BackColor)
  • *参数:x,y      起始坐标x:0~234 y:0~308£©
  •    num       字符AsCII码值
  •    size      字符大小,使用默认8*16
  •    PenColor  字体颜色
  •    BackColor 字体背景颜色
  • *功能:
  • *备注:注意屏幕大小
  • **/
  • void LCD_ShowChar(uint16_t x, uint16_t y, uint8_t num, uint8_t size, uint16_t PenColor, uint16_t BackColor)
  • {
  • #define MAX_CHAR_POSX (272-8)
  • #define MAX_CHAR_POSY (480-16)
  •     uint8_t temp;
  •     uint8_t pos,t;
  •     if(x>MAX_CHAR_POSX||y>MAX_CHAR_POSY)return;
  • num=num-' ';                         /*得到偏移后的值*/
  • for(pos=0;pos<size;pos++)
  • {
  • if(size==12)
  • temp=asc2_1206[num][pos];/*调用1206字体*/
  • else
  • temp=asc2_1608[num][pos];/*调用1608字体*/
  • for(t=0;t<size/2;t++)
  •     {
  •       if(temp&0x01) /*从低位开始*/
  •      {
  • LCD_DrawPoint(x+t, y+pos, PenColor);  /*画字体颜色,一个点*/
  •      }
  •     else
  • LCD_DrawPoint(x+t, y+pos, BackColor);/*画背景颜色,一个点*/
  • temp>>=1;
  •     }
  • }
  • }
  • /**
  • 名称:void LCD_ShowCharString(uint16_t x, uint16_t y, const uint8_t *p, uint16_t PenColor, uint16_t BackColor)
  • 参数:x,y      起始坐标
  •       p        指向字符串起始地址·
  •       PenColor  字符颜色
  •       BackColor 背景颜色
  • 功能:
  • 备注:用16字体,可以调节 此函数不能单独调用
  • **/
  • void LCD_ShowCharString(uint16_t x, uint16_t y, const uint8_t *p, uint16_t PenColor, uint16_t BackColor)
  • {
  • uint8_t size = 16;     /*---字符大小默认16*8---*/
  •     if(x>MAX_HZ_POSX){x=0;y+=size;}/*超出x轴字体最小单位,换行*/
  •     if(y>MAX_HZ_POSY){y=x=0;lcd_clear(White);} /*超出y轴字体最小单位,回到原点,并且清屏*/
  •     LCD_ShowChar(x, y, *p, size, PenColor, BackColor);/*0表示非叠加方式*/
  • }
  • /**
  • *名称:ºvoid LCD_ShowString(uint16_t x0, uint16_t y0, uint8_t *pcstr, uint16_t PenColor, uint16_t BackColor)
  • *参数:x,y      起始坐标
  •       pcstr    字符串指针
  •       PenColor  字符颜色
  •       BackColor 背景颜色
  • *功能:调用字符串和汉字显示函数,实现字符串显示
  • *备注
  • **/
  • void LCD_ShowString(uint16_t x0, uint16_t y0, uint8_t *pcStr, uint16_t PenColor, uint16_t BackColor)
  • {
  • while(*pcStr!='\0')
  • {
  • if(*pcStr>0x80) /*显示汉字*/
  • {
  • LCD_ShowHzString(x0, y0, pcStr, PenColor, BackColor);
  • pcStr += 2;
  • x0 += 16;
  • }
  • else           /*显示字符*/
  • {
  • LCD_ShowCharString(x0, y0, pcStr, PenColor, BackColor);
  • pcStr +=1;
  • x0+= 8;
  • }
  • }
  • }
  • //
  • ///*********************************************************************************************************
  • //** Functoin name:       write_data_Prepare
  • //** Descriptions:        写数据开始
  • //** input paraments:     无
  • //** output paraments:    无
  • //** Returned values:     无
  • //*********************************************************************************************************/
  • void write_data_Prepare(void)
  • {
  • write_cmd(0x002C);
  • }
  • /*********************************************************************************************************
  • ** Functoin name:       LCD_WindowMax
  • ** Descriptions:        设置窗口
  • ** input paraments:     窗口的位置
  • ** output paraments:    无
  • ** Returned values:     无
  • *********************************************************************************************************/
  • void LCD_WindowMax (unsigned int xsta,unsigned int xend, unsigned int ysta,unsigned int yend)
  • {
  • write_cmd(0X002A);
  • write_data(xsta>>8);
  • write_data(xsta&0X00FF);
  • write_data(xend>>8);
  • write_data(xend&0X00FF);
  • write_cmd(0X002B);
  • write_data(ysta>>8);
  • write_data(ysta&0X00FF);
  • write_data(yend>>8);
  • write_data(yend&0X00FF);
  • }
  • /*********************************************************************************************************
  • ** Functoin name:     LCD_Fill
  • ** Descriptions:      填充窗口
  • ** input paraments:   窗口的位置
  •   colour£:    颜色
  • ** output paraments:    无
  • ** Returned values:     无
  • *********************************************************************************************************/
  • void LCD_Fill(uint16_t xsta, uint16_t xend, uint16_t ysta,  uint16_t yend, uint16_t colour)
  • {
  •     uint32_t n;
  • /*设置窗口*/
  • LCD_WindowMax (xsta,  xend,  ysta, yend);
  • write_data_Prepare();         /*开始写入GRAM*/
  • n=(uint32_t)(yend-ysta+1)*(xend-xsta+1);
  • while(n--){write_data(colour);} /*显示所填充的颜色*/
  • }
  • /*********************************************************************************************************
  • ** Functoin name:       LCD_DrawLine
  • ** Descriptions:        指定坐标(两点)画线
  • ** input paraments:     xsta X起始坐标
  •                         ysta Y起始坐标
  •                         xend X终点坐标
  •                         yend Y终点坐标
  •                         colour颜色
  • ** output paraments:    无
  • ** Returned values:     无
  • *********************************************************************************************************/
  • void LCD_DrawLine(uint16_t xsta, uint16_t xend, uint16_t ysta,uint16_t yend, uint16_t color)
  • {
  •     uint16_t x, y, t;
  • if((xsta==xend)&&(ysta==yend))
  • LCD_DrawPoint(xsta, ysta, color);
  • else
  • if(abs(yend-ysta)>abs(xend-xsta))//斜率大于1
  • {
  • if(ysta>yend)
  • {
  • t=ysta;
  • ysta=yend;
  • yend=t;
  • t=xsta;
  • xsta=xend;
  • xend=t;
  • }
  • for(y=ysta;y<yend;y++)            /*以y轴为基准*/
  • {
  • x=(uint32_t)(y-ysta)*(xend-xsta)/(yend-ysta)+xsta;
  • LCD_DrawPoint(x, y, color);
  • }
  • }
  • else     /*斜率小于等于1*/
  • {
  • if(xsta>xend)
  • {
  • t=ysta;
  • ysta=yend;
  • yend=t;
  • t=xsta;
  • xsta=xend;
  • xend=t;
  • }
  • for(x=xsta;x<=xend;x++)  /*以x轴为基准/
  • {
  • y =(uint32_t)(x-xsta)*(yend-ysta)/(xend-xsta)+ysta;
  • LCD_DrawPoint(x, y, color);
  • }
  • }
  • }
  • /**
  • *名称:void Draw_Circle(uint16_t x0, uint16_t y0, uint8_t r)
  • *参数:x0 中心点横坐标
  •       y0 中心点纵坐标
  •       r  半径
  • *返回:无
  • *功能:在指定位置画一个指定大小的圆
  • *备注:加入颜色参数,是否填充等
  • **/
  • void Draw_Circle(uint16_t x0, uint16_t y0, uint8_t r, uint16_t color)
  • {
  • int a,b;
  • int di;
  • a=0;b=r;
  • di=3-(r<<1);             /*判断下个点位置标志*/
  • while(a<=b)
  • {
  • LCD_DrawPoint(x0-b, y0-a, color);             //3
  • LCD_DrawPoint(x0+b, y0-a, color);             //0
  • LCD_DrawPoint(x0-a, y0+b, color);             //1
  • LCD_DrawPoint(x0-b, y0-a, color);             //7
  • LCD_DrawPoint(x0-a, y0-b, color);             //2
  • LCD_DrawPoint(x0+b, y0+a, color);             //4
  • LCD_DrawPoint(x0+a, y0-b, color);             //5
  • LCD_DrawPoint(x0+a, y0+b, color);             //6
  • LCD_DrawPoint(x0-b, y0+a, color);
  • a++;
  • /*使用Bresenham算法画圆*/
  • if(di<0)di +=4*a+6;
  • else
  • {
  • di+=10+4*(a-b);
  • b--;
  • }
  • LCD_DrawPoint(x0+a, y0+b, color);
  • }
  • }
  • /**
  • *名称:void LCD_DrawRectangle(uint16_t xsta, uint16_t ysta, uint16_t xend, uint16_t yend)
  • *参数:xsta x起始坐标
  •       ysta Y起始坐标
  •       xend x结束坐标
  •       yend Y结束坐标
  • *返回:无
  • *功能:在指定区域画矩形
  • *备注:
  • **/
  • void LCD_DrawRectangle(uint16_t xsta, uint16_t xend, uint16_t ysta,uint16_t yend, uint16_t color)
  • {
  • LCD_DrawLine(xsta, xend, ysta, ysta, color);
  • LCD_DrawLine(xsta, xsta, ysta, yend, color);
  • LCD_DrawLine(xsta, xend, yend, yend, color);
  • LCD_DrawLine(xend, xend, ysta, yend, color);
  • }
  • /****************************************************************************
  • *名称:void LCD_DrawPicture(uint16_t StartX,uint16_t StartY,uint16_t EndX,uint16_t EndY,uint16_t *pic)
  • *功能:在指定座标范围显示一副图片
  • *入口参数:StartX     行起始坐标
  • *        EndX       行结束坐标
  • *        StartY     列起始坐标
  • *        EndY       列结束坐标
  •          pic        图片头指针
  • * 出口参数:无
  • * 说    明:图片取模格式为水平扫描,16位颜色模式
  • * 调用方法:ºLCD_DrawPicture(0,0,100,100,(uint16_t*)demo);
  • ****************************************************************************/
  • void LCD_DrawPicture(uint16_t StartX,uint16_t Xend,uint16_t StartY,uint16_t Yend,uint8_t *pic)
  • {
  • staticuint16_t i=0,j=0;
  • uint16_t *bitmap = (uint16_t *)pic;
  • for(j=0; j<Yend-StartY; j++)
  • {
  • for(i=0; i<Xend-StartX; i++)
  • LCD_DrawPoint(StartX+i, StartY+j, *bitmap++);
  • }
  • }

复制代码


使用特权

评论回复
5
想跳水的朱| | 2023-5-15 14:25 | 只看该作者
这里提的液晶屏控制器SSD1963的稳定性太差了!一点干扰就显示就乱,产品的可靠性测试一直通不过,后改用瑞佑的RA8889才搞掂,功能还多好多

使用特权

评论回复
6
mollylawrence| | 2023-6-7 21:16 | 只看该作者
TFT液晶屏,用stm32有几种驱动方式?

使用特权

评论回复
7
MessageRing| | 2023-6-7 22:51 | 只看该作者
mollylawrence 发表于 2023-6-7 21:16
TFT液晶屏,用stm32有几种驱动方式?

看不同的屏幕,有的是spi,有的是fsmc

使用特权

评论回复
8
geraldbetty| | 2023-6-8 14:03 | 只看该作者
为什么stm32中的,tftlcd显示实验验证出现白屏?

使用特权

评论回复
9
iyoum| | 2023-6-8 14:08 | 只看该作者
STM32f429通过RGB直接驱动TFT-LCD可以吗

使用特权

评论回复
10
yeates333| | 2023-6-8 15:17 | 只看该作者
TFT彩屏怎么实现区域性刷屏               

使用特权

评论回复
11
wwppd| | 2023-6-8 16:19 | 只看该作者
在设计显示内容时需要考虑用户界面设计、显示效果、字体大小、颜色搭配等,以达到好的用户体验。

使用特权

评论回复
12
jkl21| | 2023-6-14 11:38 | 只看该作者
stm32怎样连接tft lcd硬件设计

使用特权

评论回复
13
rosemoore| | 2023-6-14 11:59 | 只看该作者
用stm32单片机实现彩屏的显示好实现吗?

使用特权

评论回复
14
10299823| | 2023-6-14 15:32 | 只看该作者
如何点亮奋斗STM32配套4.3寸TFT显示屏

使用特权

评论回复
15
kmzuaz| | 2023-6-14 16:58 | 只看该作者
STM32驱动TFT液晶,刷屏慢, 怎么破

使用特权

评论回复
16
claretttt| | 2023-6-15 22:53 | 只看该作者
根据具体需求选择合适的显示控制器和驱动芯片,例如ILI9341、SSD1963等

使用特权

评论回复
17
macpherson| | 2023-6-19 08:59 | 只看该作者
在进行TFT-LCD显示屏开发时,还需要考虑其他一些因素,例如电源管理、触摸屏控制、扩展接口设计等。

使用特权

评论回复
18
cemaj| | 2023-6-19 11:50 | 只看该作者
需要进行正确的硬件连接和布局,包括数据线、时钟线、复位线等。另外,还需要注意信号线长度和阻抗匹配等问题。

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

2038

主题

7364

帖子

10

粉丝