这些小活动你都参加了吗?快来围观一下吧!>>
电子产品世界 » 论坛首页 » 活动中心 » 板卡试用 » 【换取逻辑分析仪】STM32G4从入门到大师之二:驱动TFT显示屏

共7条 1/1 1 跳转至

【换取逻辑分析仪】STM32G4从入门到大师之二:驱动TFT显示屏

高工
2025-03-31 11:44:21   被打赏 23 分(兑奖)     打赏

   先从网上找个TFT显示屏,ILI9328驱动的 240*320 。ILI9328是一款由Ilitek公司开发的TFT-LCD驱动控制器,广泛应用于各类嵌入式显示系统中。

主要特点

1 高分辨率支持:ILI9328支持高达240x320像素的屏幕分辨率,适用于多种尺寸的液晶显示屏,如2.5英寸和2.8英寸的TFT显示屏。

   该控制器支持16位和18位真彩色模式,能够显示262,144种颜色(即262K色),提供高质量的彩色显示效果。

2 接口灵活:ILI9328支持多种接口模式,包括并行总线接口(如8位、9位、16位和18位)和串行接口(如SPI),便于与不同类型的微控制器或处理器连接。内置视频RAM缓冲区:控制器内置视频RAM(GRAM),用于存储图像数据,减少了外部存储器的需求,简化了系统设计。

3 低功耗:ILI9328采用先进的低功耗设计,适用于便携式设备,如手持GPS、MP3播放器、智能仪表等。








开发一个PCB转接板,先要源文件可以私信我。

S6.png

下面进行软件编写:

使用普通I/O口模拟SPI接口时,需要连接以下信号线:

SCK(Serial Clock):时钟信号线,由STM32G4提供,用于同步数据传输。

MOSI(Master Out Slave In):主设备输出/从设备输入引脚,用于STM32G4向TFT显示屏发送数据。

CS(Chip Select):片选信号线,用于选中TFT显示屏进行通信。

DC(Data/Command):数据/命令选择信号线,用于区分传输的是数据还是命令。

RST(Reset):复位信号线,用于复位TFT显示屏。其他信号线:如背光控制信号线等,根据实际需求进行连接。

宏定义:

#define LCD_RS         	RS_Pin	//PE3Á¬½ÓÖÁTFT --DC RS
#define LCD_CS        	CS_Pin 	//PE4Á¬½ÓÖÁTFT --CS
#define LCD_RST     	RST_Pin	//PE1Á¬½ÓÖÁTFT --RST
#define LCD_SCL        	CLK_Pin	//PE2Á¬½ÓÖÁTFT --CLK
#define LCD_SDA        	SDA_Pin	//PE6Á¬½ÓÖÁTFT - SDI
#define LCD_SDO        	SDO_Pin	//PE5Á¬½ÓÖÁTFT - SDO

#define SPI_CS(a)	\
						if (a)	\
						GPIOE->BSRR=LCD_CS;	\
						else		\
						GPIOE->BRR=LCD_CS ;
#define SPI_DCLK(a)	\
						if (a)	\
						GPIOE->BSRR=LCD_SCL;	\
						else		\
						GPIOE->BRR=LCD_SCL;
#define SPI_SDA(a)	\
						if (a)	\
						GPIOE->BSRR=LCD_SDA;	\
						else		\
						GPIOE->BRR=LCD_SDA;
#define lcd_RS(a)	\
						if (a)	\
						GPIOE->BSRR=LCD_RS;\
						else		\
						GPIOE->BRR=LCD_RS;
						
#define	LCD_RST_SET  	 GPIOE->BSRR=LCD_RST
#define	LCD_RST_CLR  	 GPIOE->BRR=LCD_RST						

功能函数编写:

void Lcd_Reset(void)
{
	LCD_RST_CLR;
	HAL_Delay(100);
	LCD_RST_SET;
	HAL_Delay(50);
}

void LCD_delay(int time)  //¼òµ¥Èí¼þ ÑÓʱº¯Êý
{
	unsigned short i,j;
	for(i=0;i<time;i++)
		for(j=0;j<1000;j++)	;
}
void LCD_WriteByteSPI(unsigned char byte) //SPIÄ£Ä⺯Êý£¬Ð´Ò»¸ö8bitµÄÊý¾Ý
{
	  unsigned char buf;
    unsigned char i;
    for(i=0;i<8;i++) 
    {
        buf=(byte>>(7-i))&0x1;
				SPI_DCLK(0);
        SPI_SDA(buf);
        SPI_DCLK(1);
    }	
		
}
void LCD_WriteRegIndex(unsigned char Index) //дÃüÁîµÄ²ÎÊý
{
	SPI_CS(0);
	LCD_WriteByteSPI(0X70);
	LCD_WriteByteSPI(0);
	LCD_WriteByteSPI(Index);
	SPI_CS(1);
}
void LCD_WriteData(unsigned short dat) //дÊý¾Ý
{
	SPI_CS(0);
	LCD_WriteByteSPI(0X72);
  LCD_WriteByteSPI(dat>>8);		//	start byte RS=1,RW=0----Write a GRAM data
  LCD_WriteByteSPI(dat);
	SPI_CS(1);
}

void LCD_WR_REG(unsigned int Index,unsigned int CongfigTemp)
{
	LCD_WriteRegIndex(Index);
	LCD_WriteData(CongfigTemp);
}

void Lcd_SetCursor(unsigned short x,unsigned short y)
{ 
  LCD_WriteRegIndex(0x20);
  LCD_WriteData(x);//ˮƽ×ø±ê
  LCD_WriteRegIndex(0x21);
  LCD_WriteData(y);//´¹Ö±×ø±ê 
} 

void BlockWrite(unsigned int Xstart,unsigned int Xend,unsigned int Ystart,unsigned int Yend) 
{
	//ILI9328
	
	LCD_WR_REG(0x0050,Xstart);//ˮƽGRAMÆðʼλÖÃ
	LCD_WR_REG(0x0051,Xend); //ˮƽGRAMÖÕֹλÖÃ
	LCD_WR_REG(0x0052,Ystart);//´¹Ö± GRAMÆðʼλÖÃ
	LCD_WR_REG(0x0053,Yend); //´¹Ö±GRAMÖÕֹλÖÃ
	
	Lcd_SetCursor(Xstart, Ystart);
	
  LCD_WriteRegIndex(0x022);

}

void Lcd_ColorBox(unsigned int xStart,unsigned int yStart,unsigned int xLong,unsigned int yLong,unsigned int Color)
{
		unsigned int temp;

	BlockWrite(xStart,xStart+xLong-1,yStart,yStart+yLong-1);
	SPI_CS(0);
	LCD_WriteByteSPI(0X72);
	for (temp=0; temp<xLong*yLong; temp++)
	{
		LCD_WriteByteSPI(Color>>8);		//	start byte RS=1,RW=0----Write a GRAM data
		LCD_WriteByteSPI(Color);
	}
	SPI_CS(1);
}
void LCD_Initial(void) //LCD³õʼ»¯º¯Êý
{
Lcd_Reset();
//************* Start Initial Sequence **********//
LCD_WR_REG(0x0001, 0x0000); // set SS and SM bit
LCD_WR_REG(0x0002, 0x0700); // set 1 line inversion
LCD_WR_REG(0x0003, 0x1030); // set GRAM write direction and BGR=1.  0001 0000 0011 0000
LCD_WR_REG(0x0004, 0x0000); // Resize register
LCD_WR_REG(0x0008, 0x0202); // set the back porch and front porch
LCD_WR_REG(0x0009, 0x0000); // set non-display area refresh cycle ISC[3:0]
LCD_WR_REG(0x000A, 0x0000); // FMARK function
LCD_WR_REG(0x000C, 0x0000); // RGB interface setting
LCD_WR_REG(0x000D, 0x0000); // Frame marker Position
LCD_WR_REG(0x000F, 0x0000); // RGB interface polarity
//*************Power On sequence ****************//
LCD_WR_REG(0x0010, 0x0000); // SAP, BT[3:0], AP, DSTB, SLP, STB
LCD_WR_REG(0x0011, 0x0007); // DC1[2:0], DC0[2:0], VC[2:0]
LCD_WR_REG(0x0012, 0x0000); // VREG1OUT voltage
LCD_WR_REG(0x0013, 0x0000); // VDV[4:0] for VCOM amplitude
LCD_WR_REG(0x0007, 0x0001);
HAL_Delay(200); // Dis-charge capacitor power voltage
LCD_WR_REG(0x0010, 0x1690); // SAP, BT[3:0], AP, DSTB, SLP, STB
LCD_WR_REG(0x0011, 0x0227); // Set DC1[2:0], DC0[2:0], VC[2:0]
HAL_Delay(50); // Delay 50ms
LCD_WR_REG(0x0012, 0x009D); // External reference voltage= Vci;
HAL_Delay(50); // Delay 50ms
LCD_WR_REG(0x0013, 0x1A00); // VDV[4:0] for VCOM amplitude
LCD_WR_REG(0x0029, 0x001D); // VCM[5:0] for VCOMH
LCD_WR_REG(0x002B, 0x000D); // Set Frame Rate
HAL_Delay(50); // Delay 50ms
LCD_WR_REG(0x0020, 0x0000); // GRAM horizontal Address
LCD_WR_REG(0x0021, 0x0000); // GRAM Vertical Address
// ----------- Adjust the Gamma Curve ----------//
LCD_WR_REG(0x0030, 0x0000);
LCD_WR_REG(0x0031, 0x0607);
LCD_WR_REG(0x0032, 0x0305);
LCD_WR_REG(0x0035, 0x0000);
LCD_WR_REG(0x0036, 0x1604);
LCD_WR_REG(0x0037, 0x0204);
LCD_WR_REG(0x0038, 0x0001);
LCD_WR_REG(0x0039, 0x0707);
LCD_WR_REG(0x003C, 0x0000);
LCD_WR_REG(0x003D, 0x000F);
//------------------ Set GRAM area ---------------//
LCD_WR_REG(0x0050, 0x0000); // Horizontal GRAM Start Address
LCD_WR_REG(0x0051, 0x00EF); // Horizontal GRAM End Address
LCD_WR_REG(0x0052, 0x0000); // Vertical GRAM Start Address
LCD_WR_REG(0x0053, 0x013F); // Vertical GRAM Start Address
LCD_WR_REG(0x0060, 0x2700); // Gate Scan Line  
LCD_WR_REG(0x0061, 0x0001); // NDL,VLE, REV

LCD_WR_REG(0x006A, 0x0000); // set scrolling line
//-------------- Partial Display Control ---------//
LCD_WR_REG(0x0080, 0x0000);
LCD_WR_REG(0x0081, 0x0000);
LCD_WR_REG(0x0082, 0x0000);
LCD_WR_REG(0x0083, 0x0000);
LCD_WR_REG(0x0084, 0x0000);
LCD_WR_REG(0x0085, 0x0000);
//-------------- Panel Control -------------------//
LCD_WR_REG(0x0090, 0x0010);
LCD_WR_REG(0x0092, 0x0600);
LCD_WR_REG(0x0007, 0x0133); // 262K color and display ON
HAL_Delay(10);

	//============´ÓÓÒµ½×ó´Óϵ½ÉÏ============//
//	LCD_WR_REG(0x0001, 0x0100);
//	LCD_WR_REG(0x03,0x1008);//MX, MY, RGB mode

	//============´Ó×óµ½ÓÒ´Óϵ½ÉÏ============//
//	LCD_WR_REG(0x0001, 0x0100);
//	LCD_WR_REG(0x03,0x1018);//MX, MY, RGB mode

	//============´ÓÓÒµ½×ó´ÓÉϵ½ÏÂ============//
//	LCD_WR_REG(0x0001, 0x0100);
//	LCD_WR_REG(0x03,0x1028);//MX, MY, RGB mode

	//============´Ó×óµ½ÓÒ´ÓÉϵ½ÏÂ============//
//	LCD_WR_REG(0x0001, 0x0100);
//	LCD_WR_REG(0x03,0x1038);//MX, MY, RGB mode

	
	//============´Ó×óµ½ÓÒ´ÓÉϵ½ÏÂ============//
//	LCD_WR_REG(0x0001, 0x0100);// set SS and SM bit
//	LCD_WR_REG(0x03,0x1030);//MX, MY, RGB mode set GRAM write direction and BGR=1.
	
//	Lcd_Light_ON;//´ò¿ª±³¹â

//	LCD_WR_REG(0x0001, 0x0100);
//	LCD_WR_REG(0x03,0x1008);//MX, MY, RGB mode


}

void LCD_Fill_Pic(unsigned int x, unsigned int y,unsigned int pic_H, unsigned int pic_V, const unsigned char*  pic)
{
	//DMA ·½Ê½
//	BlockWrite(x,x+pic_H-1,y,y+pic_V-1);
//	TK80_DMA_Init((u32)pic,pic_H*pic_V);//DMA³õʼ»¯
//	while((DMA2->ISR & 0x20)==0);
//	DMA2->IFCR |=1<<5;
	
	//========= ÂÖѯ·½Ê½=========//
  unsigned long i;
	unsigned long j;
	BlockWrite(x,x+pic_H-1,y,y+pic_V-1);
	j= pic_H*pic_V*2;
	SPI_CS(0);
	LCD_WriteByteSPI(0X72);
	for (i = 0; i <j; i++) 
	{
		LCD_WriteByteSPI(pic[i]);
	}
	SPI_CS(1);
}
//=============== ÔÚx£¬y ×ø±êÉÏ´òÒ»¸öÑÕɫΪColorµÄµã ===============
void DrawPixel(unsigned int x, unsigned int y, int Color)
{
	BlockWrite(x,x,y,y); 
  SPI_CS(0);
	LCD_WriteByteSPI(0X72);
	LCD_WriteByteSPI(Color>>8);
	LCD_WriteByteSPI(Color);
	SPI_CS(1);
}


void SPILCD_ShowChar(unsigned short x,unsigned short y,unsigned char num, unsigned int fColor, unsigned int bColor,unsigned char flag) 
{       
	unsigned char temp;
	unsigned int pos,i,j;  

	num=num-' ';//µÃµ½Æ«ÒƺóµÄÖµ
	i=num*16; 	
	for(pos=0;pos<16;pos++)
		{
			temp=nAsciiDot[i+pos];	//µ÷ͨµ÷ÓÃASCII×ÖÌå
			for(j=0;j<8;j++)
		   {                 
		        if(temp&0x80)
							DrawPixel(x+j,y,fColor);
						else 
							if(flag) DrawPixel(x+j,y,bColor); //Èç¹û±³¾°É«±êÖ¾flagΪ1
							temp<<=1; 
		    }
			 y++;
		}		 
}  


void PutGB1616(unsigned short x, unsigned short  y, unsigned char c[2], unsigned int fColor,unsigned int bColor,unsigned char flag)
{
	unsigned int i,j,k;
	unsigned short m;
	for (k=0;k<200;k++) { //64±êʾ×Ô½¨ºº×Ö¿âÖеĸöÊý£¬Ñ­»·²éѯÄÚÂë
	  if ((codeGB_16[k].Index[0]==c[0])&&(codeGB_16[k].Index[1]==c[1]))
			{ 
    	for(i=0;i<32;i++) 
			{
				m=codeGB_16[k].Msk[i];
				for(j=0;j<8;j++) 
				{		
					if((m&0x80)==0x80) {
						DrawPixel(x+j,y,fColor);
						}
					else {
						if(flag) DrawPixel(x+j,y,bColor);
						}
					m=m<<1;
				} 
				if(i%2){y++;x=x-8;}
				else x=x+8;
		  }
		}  
	  }	
	}

void LCD_PutString(unsigned short x, unsigned short y, char *s, unsigned int fColor, unsigned int bColor,unsigned char flag) 
	{
		unsigned char l=0;
		while(*s) 
			{
				if( (unsigned char)*s < 0x80) 
						{
							SPILCD_ShowChar(x+l*8,y,*s,fColor,bColor,flag);
							s++;l++;
						}
				else
						{
							PutGB1616(x+l*8,y,(unsigned char*)s,fColor,bColor,flag);
							s+=2;l+=2;
						}
			}
	}


main

int main(void)
{

  HAL_Init();
  SystemClock_Config();
  MX_GPIO_Init();	
//	LCD_GPIO_Config();
	LCD_Initial();
	Lcd_ColorBox(0,0,XSIZE_PHYS,YSIZE_PHYS,Blue);//ÓÃÀ¶É«ÇåÆÁ
//	HAL_Delay(500);
	Lcd_ColorBox(0,0,XSIZE_PHYS,YSIZE_PHYS,Red);//ÓúìÉ«ÇåÆÁ
//	HAL_Delay(500);
	Lcd_ColorBox(0,0,XSIZE_PHYS,YSIZE_PHYS,Green);//ÓÃÂÌÉ«ÇåÆÁ
//	HAL_Delay(500);
	Lcd_ColorBox(0,0,XSIZE_PHYS,YSIZE_PHYS,White);//Óð×É«ÇåÆÁ
	LCD_PutString(20,10,"STM32G474Test",Red,White,0);	
	LCD_PutString(20,30,"I LOVE EEPW",Red,White,0);	
 while(1);
 }

视频:

https://www.bilibili.com/video/BV1TuZJYQEX3/


工程师
2025-04-04 08:50:41     打赏
2楼

image.png

宏定义,没有看到指定的IO。建议补充。 注释有乱码,咱不认识火星文。


专家
2025-04-08 11:59:25     打赏
3楼

仔细阅读完代码,条例很清晰,感谢楼主分享。如果注释是中文就完美了,


高工
2025-04-08 13:22:06     打赏
4楼

屏幕的配置过程清晰明了,同款屏幕驱动适配发送命令过程可以借鉴使用


助工
2025-04-08 14:32:52     打赏
5楼

 步骤清晰, 原理明了的讲解驱动TFT过程. 建议优化一下排版. 可以适当讲解一下核心代码.


院士
2025-04-08 22:42:58     打赏
6楼

DIY嘛!转接板那是送分的。

完成MCU与LCD的数据写入功能,下一步楼主是不是要移植GUI库了吧!?

期待楼主的大作。


助工
2025-04-11 10:44:37     打赏
7楼

这个屏幕的驱动工作很完善,大佬绘制PCB用的是哪个EDA软件?


共7条 1/1 1 跳转至

回复

匿名不能发帖!请先 [ 登陆 注册 ]