zl程序教程

您现在的位置是:首页 >  其它

当前栏目

TFT-LCD显示直线、矩形、圆形

显示 矩形 直线 圆形 LCD
2023-09-11 14:21:43 时间

TFT-LCD显示直线、矩形、圆形

之前显示ASCII字符、中文和图片都是使用的取模软件,这次直接用代码驱动显示直线、矩形和圆形

在前面显示图片的工程上继续加函数

获取像素点

/**
 * @name   LCD_GetPointPiexl
 * @brief  获取像素点
 * @param  usX:X轴坐标
 * 			usY:Y轴坐标
 * @retval None  
 */
static uint16_t LCD_GetPointPiexl(uint16_t usX,uint16_t usY)
{
	uint16_t usR,usG,usB;
	uint16_t usColor;		//颜色数据,RGB565格式
	//判断坐标是否有效
	if((usX < LCD_WIGHT)&&(usY < LCD_HIGHT))
	{
		//设置窗口,大小为1x1
		LCD_SetWindows(usX,usY,1,1);
		//写入读GRAM命令0x2E
		LCD_WRITE_CMD(LCD_CMD_REGRAM);
		//开始读数据
		usR = LCD_READ_DATA();		//读Dummy数据,舍弃
		usR = LCD_READ_DATA();		//读RED数据
		usG = LCD_READ_DATA();		//读GREEN数据
		usB = LCD_READ_DATA();		//读BLUE数据
		usColor = (((usR>>11)<<11)|((usG>>10)<<5)|(usB>>11));	//组合成16位的RGB565数据格式
		printf("The Piexl color is 0x%.4x\r\n",usColor);
	}
	//返回颜色数据
	return usColor;
}

usR、usG、usB变量为16位,但首先读取出的RED数据占5位,且在高字节,GREEN数据占6位,同样在高字节,BLUE数据占5位,在高字节,所以组合时要通过移位,将RED数据放在usColor的高5位,GREEN数据占中间的6位,剩下的5位放BLUE数据,这样就组合成了RGB565的数据格式

设置像素点颜色

/**
 * @name   LCD_SetPointPiexl
 * @brief  设置像素点颜色
 * @param  usX:X轴坐标
 * 			usY:Y轴坐标
 * 			usColor:显示的颜色
 * @retval None  
 */
static void LCD_SetPointPiexl(uint16_t usX,uint16_t usY,LCD_Color_t usColor)
{
	//判断坐标是否有效
	if((usX < LCD_WIGHT)&&(usY < LCD_HIGHT))
	{
		//设置窗口,大小为1x1
		LCD_SetWindows(usX,usY,1,1);
		//写入颜色数据
		LCD_WRITE_DATA(usColor);
	}
}

画直线

画直线使用到了算法,不研究算法的话直接复制使用

/**
 * @name   LCD_DrawLine
 * @brief  LCD使用算法画直线
 * @param  usX_Start:X轴起始坐标
 * 			usY_Start:Y轴起始坐标
 * 			usX_End:X轴终点坐标
 * 			usY_End:Y轴终点坐标
 * 			usColor:显示的颜色
 * @retval None  
 */
static void LCD_DrawLine(uint16_t usX_Start,uint16_t usY_Start,uint16_t usX_End,uint16_t usY_End,LCD_Color_t usColor)
{
	uint16_t i;
	uint16_t j;					//动态查看画线效果变量
	uint16_t usX_Current,usY_Current;
	int16_t sError_X=0,sError_Y=0,sDelta_X,sDelta_Y,sDistance; 
	int16_t sIncrease_X, sIncrease_Y;

	//设置坐标增量
	sDelta_X = usX_End - usX_Start;
	sDelta_Y = usY_End - usY_Start;
	usX_Current = usX_Start;
	usY_Current = usY_Start;

	//算法,直接拿来用
	if(sDelta_X > 0)
  	{
    	/* 设置单步方向 */
    	sIncrease_X=1; 
	}
  	else if(sDelta_X == 0)
  	{
    	/* 垂直线 */
		sIncrease_X = 0;
	}
	else 
  	{ 
   		sIncrease_X = -1;
    	sDelta_X    = -sDelta_X;
  	}
  
	if(sDelta_Y > 0)
  	{
		sIncrease_Y = 1;
	}
	else if(sDelta_Y==0)
  	{
    	/* 水平线  */
		sIncrease_Y = 0;
	}
	else
  	{
    	sIncrease_Y = -1;
    	sDelta_Y    = -sDelta_Y;
  	}
	
	if(sDelta_X > sDelta_Y)
  	{
    	/* 选取基本增量坐标轴 */
		sDistance = sDelta_X;  
	}
	else
  	{
		sDistance = sDelta_Y; 
  	}

	//画线输出
	for(i=0;i<=sDistance+1;i++) 
	{
    	//画点
		TFT_LCD.LCD_SetPointPiexl(usX_Current,usY_Current,usColor); 
		sError_X += sDelta_X; 
		sError_Y += sDelta_Y;
		if(sError_X > sDistance)
		{ 
			sError_X    -= sDistance; 
			usX_Current += sIncrease_X; 
		}
		if(sError_Y > sDistance) 
		{ 
			sError_Y    -= sDistance; 
			usY_Current += sIncrease_Y; 
		}	
		
		//动态看画线效果,可删除
		for(j=0;j<20000;j++);
	}
}

画矩形

如果是填充矩形,则调用填充颜色函数按照矩形的宽和高填充颜色就行,如果是不填充矩形,则画四条直线

/**
 * @name   LCD_DrawRectangle
 * @brief  LCD画矩形
 * @param  usX_Start:X轴起始坐标
 * 			usY_Start:Y轴起始坐标
 * 			usWidth:矩形的宽度
 * 			usHeight:矩形的高度
 * 			usColor:显示的颜色
 * 			ucFilled:选择是否填充矩形	参数:Filled:填充,unFilled:不填充
 * @retval None  
 */
static void LCD_DrawRectangle(uint16_t usX_Start,
								uint16_t usY_Start,
								uint16_t usWidth,
								uint16_t usHeight,
								LCD_Color_t usColor,
								Filled_t ucFilled)
{
	//如果是填充矩形
	if(ucFilled == Filled)
	{
		TFT_LCD.LCD_FillColor(usX_Start,usY_Start,usWidth,usHeight,usColor);
	}
	//不填充矩形
	else
	{
		//画四条线
		TFT_LCD.LCD_DrawLine(usX_Start, usY_Start, usX_Start + usWidth - 1, usY_Start, usColor);
		TFT_LCD.LCD_DrawLine(usX_Start + usWidth - 1, usY_Start, usX_Start + usWidth - 1, usY_Start + usHeight - 1, usColor);
		TFT_LCD.LCD_DrawLine(usX_Start + usWidth - 1, usY_Start + usHeight - 1, usX_Start, usY_Start + usHeight - 1, usColor);
		TFT_LCD.LCD_DrawLine(usX_Start, usY_Start + usHeight - 1, usX_Start, usY_Start, usColor);
	}
}

画圆

使用 Bresenham 算法画圆

/**
 * @name   LCD_DrawCircle
 * @brief  在LCD屏幕上使用 Bresenham 算法画圆
 * @param  usX_Center:圆心X坐标
 * 			usY_Center:圆心Y坐标
 * 			usRadius:圆的半径(单位像素)
 * 			usColor:圆的颜色
 * 			ucFilled:选择是否填充圆形	参数:Filled:填充,unFilled:不填充
 * @retval None  
 */
static void LCD_DrawCircle(uint16_t usX_Center,uint16_t usY_Center,uint16_t usRadius,LCD_Color_t usColor,Filled_t ucFilled)
{
	int16_t sCurrentX, sCurrentY;
	int16_t sError;
  
	sCurrentX = 0;
  	sCurrentY = usRadius;	
	sError    = 3- (usRadius<<1);   //判断下个点位置的标志
	
	while(sCurrentX <= sCurrentY)
	{
		int16_t sCountY;		
		if(ucFilled)
    	{			
			for(sCountY=sCurrentX;sCountY<=sCurrentY;sCountY++)
			{                      
				TFT_LCD.LCD_SetPointPiexl(usX_Center + sCurrentX, usY_Center + sCountY, usColor); 
				TFT_LCD.LCD_SetPointPiexl(usX_Center - sCurrentX, usY_Center + sCountY, usColor);       
				TFT_LCD.LCD_SetPointPiexl(usX_Center - sCountY,   usY_Center + sCurrentX, usColor);
				TFT_LCD.LCD_SetPointPiexl(usX_Center - sCountY,   usY_Center - sCurrentX, usColor);
				TFT_LCD.LCD_SetPointPiexl(usX_Center - sCurrentX, usY_Center - sCountY, usColor);   
        		TFT_LCD.LCD_SetPointPiexl(usX_Center + sCurrentX, usY_Center - sCountY, usColor);
				TFT_LCD.LCD_SetPointPiexl(usX_Center + sCountY,   usY_Center - sCurrentX, usColor);
        		TFT_LCD.LCD_SetPointPiexl(usX_Center + sCountY,   usY_Center + sCurrentX, usColor);		
			}
    	}		
		else
		{          
			TFT_LCD.LCD_SetPointPiexl(usX_Center + sCurrentX, usY_Center + sCurrentY, usColor);
			TFT_LCD.LCD_SetPointPiexl(usX_Center - sCurrentX, usY_Center + sCurrentY, usColor);      
			TFT_LCD.LCD_SetPointPiexl(usX_Center - sCurrentY, usY_Center + sCurrentX, usColor);
			TFT_LCD.LCD_SetPointPiexl(usX_Center - sCurrentY, usY_Center - sCurrentX, usColor);
			TFT_LCD.LCD_SetPointPiexl(usX_Center - sCurrentX, usY_Center - sCurrentY, usColor);      
			TFT_LCD.LCD_SetPointPiexl(usX_Center + sCurrentX, usY_Center - sCurrentY, usColor);
			TFT_LCD.LCD_SetPointPiexl(usX_Center + sCurrentY, usY_Center - sCurrentX, usColor);
			TFT_LCD.LCD_SetPointPiexl(usX_Center + sCurrentY, usY_Center + sCurrentX, usColor);
    	}			
		sCurrentX++;		
		if(sError < 0) 
    	{
			sError += (4*sCurrentX + 6);	  
		}
		else
		{
			sError += (10 + 4*(sCurrentX - sCurrentY));   
			sCurrentY--;
		} 
	}
}

主函数调用

/*
* @name   Run
* @brief  系统运行
* @param  None
* @retval None   
*/
static void Run()
{
  //画直线
  TFT_LCD.LCD_DrawLine(50,20,200,20,Color_RED);
  TFT_LCD.LCD_DrawLine(50,30,200,30,Color_GREEN);
  TFT_LCD.LCD_DrawLine(50,40,200,40,Color_BLUE);
  TFT_LCD.LCD_DrawLine(50,50,200,50,Color_BLACK);
  TFT_LCD.LCD_DrawLine(50,60,200,60,Color_YELLOW);

  //中间直线
  TFT_LCD.LCD_DrawLine(120,90,120,290,Color_BLUE);

  //画填充矩形
  TFT_LCD.LCD_DrawRectangle(40,90,60,80,Color_BLACK,Filled);
	
  //画不填充矩形
	TFT_LCD.LCD_DrawRectangle(140,90,60,80,Color_BLACK,unFilled);

  //画不填充圆形
	TFT_LCD.LCD_DrawCircle(70,250,40,Color_RED,unFilled);

  //画填充圆形
	TFT_LCD.LCD_DrawCircle(170,250,40,Color_RED,Filled);


  //动态画矩形和圆形
  // uint8_t i;
  // for(i=10;i<=80;i+=20)
  // {
  //   TFT_LCD.LCD_DrawRectangle(50+i,50,20,20,Color_BLUE,Filled);    //动态画矩形
  //   TFT_LCD.LCD_DrawCircle(120,220,i,Color_RED,unFilled);          //动态画圆形
  //   HAL_Delay(1000);
  // }
	
  // for(i=80;i>=10;i-=20)
  // {
  //   TFT_LCD.LCD_DrawRectangle(50+i,50,20,20,Color_GRAY,Filled);    //动态画矩形
  //   TFT_LCD.LCD_DrawCircle(120,220,i,Color_GRAY,unFilled);         //动态画圆形
  //   HAL_Delay(1000);
  // }
}

显示效果

在这里插入图片描述