LCD简介

原理:

LCD即液晶显示器,给液晶施加电场,会改变它的分子排列,从而改变光线传播方向,配合偏振光片,它就具有控制光线透过率的作用,再配合彩色滤光片,就能改变某一颜色透光量的多少。做出可控红、绿、蓝光输出强度的显示结构,组成一个显示单位,通过控制红绿蓝的强度,可以使该单位混合输出不同的色彩,这样的一个显示单位被称为像素。(需要背光源)

硬件结构:
液晶显示面板+电容触摸面板+PCB底板(带液晶控制器芯片)
在这里插入图片描述

MINI板上的液晶控制器为ILI9341,主机通过8080接口与其进行连接,从而控制液晶的显示
在这里插入图片描述

程序细节

初始化:
1.初始化各个管脚,打开背光灯,模拟8080时序
2.记得禁止JTAG功能
3.初始化配置

常用指令的使用:
1.开辟一个窗口(设置x坐标和y坐标以及它们的高度和宽度)
2.填充像素(开辟了显示窗口后,再发送像素数据时,这些数据就会直接显示在它设定的窗口位置中)

/**
 * @brief  在ILI9341显示器上开辟一个窗口
 * @param  usX :在特定扫描方向下窗口的起点X坐标
 * @param  usY :在特定扫描方向下窗口的起点Y坐标
 * @param  usWidth :窗口的宽度
 * @param  usHeight :窗口的高度
 * @retval 无
 */
void ILI9341_OpenWindow ( uint16_t usX, uint16_t usY, uint16_t usWidth, uint16_t usHeight )
{	
	ILI9341_Write_Cmd ( CMD_SetCoordinateX ); 				 /* 设置X坐标 */
	ILI9341_Write_Data ( usX >> 8  );	 /* 先高8位,然后低8位 */
	ILI9341_Write_Data ( usX & 0xff  );	 /* 设置起始点和结束点*/
	ILI9341_Write_Data ( ( usX + usWidth - 1 ) >> 8  );
	ILI9341_Write_Data ( ( usX + usWidth - 1 ) & 0xff  );

	ILI9341_Write_Cmd ( CMD_SetCoordinateY ); 			     /* 设置Y坐标*/
	ILI9341_Write_Data ( usY >> 8  );
	ILI9341_Write_Data ( usY & 0xff  );
	ILI9341_Write_Data ( ( usY + usHeight - 1 ) >> 8 );
	ILI9341_Write_Data ( ( usY + usHeight - 1) & 0xff );
	
}

/**
 * @brief  在ILI9341显示器上以某一颜色填充像素点
 * @param  ulAmout_Point :要填充颜色的像素点的总数目
 * @param  usColor :颜色
 * @retval 无
 */
static __inline void ILI9341_FillColor ( uint32_t ulAmout_Point, uint16_t usColor )
{
	uint32_t i = 0;
	
	/* memory write */
	ILI9341_Write_Cmd ( CMD_SetPixel );	
		
	for ( i = 0; i < ulAmout_Point; i ++ )
		ILI9341_Write_Data ( usColor );
}

画直线的算法:
1.一个像素一个像素的画点;
2.取x、y较长的为长度(假设y>x,则循环长度为y)
3.若nx<y,则在kn(k为整数)次循环中x不自加,其余都自加

/**
 * @brief  在 ILI9341 显示器上使用 Bresenham 算法画线段 
 * @param  usX1 :在特定扫描方向下线段的一个端点X坐标
 * @param  usY1 :在特定扫描方向下线段的一个端点Y坐标
 * @param  usX2 :在特定扫描方向下线段的另一个端点X坐标
 * @param  usY2 :在特定扫描方向下线段的另一个端点Y坐标
 * @note 可使用LCD_SetBackColor、LCD_SetTextColor、LCD_SetColors函数设置颜色
 * @retval 无
 */
void ILI9341_DrawLine ( uint16_t usX1, uint16_t usY1, uint16_t usX2, uint16_t usY2 )
{
	uint16_t us; 
	uint16_t usX_Current, usY_Current;
	
	int32_t lError_X = 0, lError_Y = 0, lDelta_X, lDelta_Y, lDistance; 
	int32_t lIncrease_X, lIncrease_Y; 	
	
	
	lDelta_X = usX2 - usX1; //计算坐标增量 
	lDelta_Y = usY2 - usY1; 
	
	usX_Current = usX1; 
	usY_Current = usY1; 
	
	
	if ( lDelta_X > 0 ) 
		lIncrease_X = 1; //设置单步方向 
	
	else if ( lDelta_X == 0 ) 
		lIncrease_X = 0;//垂直线 
	
	else 
  { 
    lIncrease_X = -1;
    lDelta_X = - lDelta_X;
  } 

	
	if ( lDelta_Y > 0 )
		lIncrease_Y = 1; 
	
	else if ( lDelta_Y == 0 )
		lIncrease_Y = 0;//水平线 
	
	else 
  {
    lIncrease_Y = -1;
    lDelta_Y = - lDelta_Y;
  } 

	
	if (  lDelta_X > lDelta_Y )
		lDistance = lDelta_X; //选取基本增量坐标轴 
	
	else 
		lDistance = lDelta_Y; 

	
	for ( us = 0; us <= lDistance + 1; us ++ )//画线输出 
	{  
		ILI9341_SetPointPixel ( usX_Current, usY_Current );//画点 
		
		lError_X += lDelta_X ; 
		lError_Y += lDelta_Y ; 
		
		if ( lError_X > lDistance ) 
		{ 
			lError_X -= lDistance; 
			usX_Current += lIncrease_X; 
		}  
		
		if ( lError_Y > lDistance ) 
		{ 
			lError_Y -= lDistance; 
			usY_Current += lIncrease_Y; 
		}
	}  
}

字模的概念以及液晶上字符的显示:
对于英文编码,ASCII码便可以;而中文编码比较麻烦,例程中采用的是GB2312
若想要在液晶上显示字符,需要引入字模库(每个字符对应有一个字模,代表的是规定大小中像素的排列规则)
由于中文的字模库很大,需要放入外部存储设备,我暂时用了一个数组来保存需要显示的中文字符,显示的算法如下:

#define LENGTH_CH				4				//汉字的个数
#define CH_Height       		24
#define CH_Width				24

//汉字字模数组
u8 charer_Ch[LENGTH_CH][72]={{0x00,0x00,0x00,0x00,0x00,0x00,0x3F,0x00,0x04,0x21,0x3F,0xFC,0x23,0x00,0x10,0x22,0x00,0x10,0x22,0x00,0x10,0x24,0x3F,0x10,0x24,0x31,0x10,0x24,0x31,0x10,0x22,0x31,0x10,0x23,0x31,0x10,0x21,0x31,0x10,0x21,0xB1,0x10,0x21,0xBF,0x10,0x21,0x31,0x10,0x2F,0x30,0x10,0x22,0x00,0x10,0x20,0x00,0x10,0x20,0x00,0x10,0x20,0x01,0xB0,0x20,0x00,0x70,0x20,0x00,0x00,0x00,0x00,0x00},/*"阿",0*/
														{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x10,0x00,0x00,0x18,0x00,0x00,0x18,0x00,0x00,0x18,0x00,0x00,0x18,0x00,0x00,0x18,0x00,0x00,0x18,0x00,0x00,0x18,0x08,0x7F,0xFF,0xFC,0x00,0x18,0x00,0x00,0x18,0x00,0x00,0x18,0x00,0x00,0x18,0x00,0x00,0x18,0x00,0x00,0x18,0x00,0x00,0x18,0x00,0x00,0x18,0x00,0x00,0x18,0x10,0x1F,0xFF,0xF8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"士",1*/
														{0x00,0x00,0x00,0x00,0x10,0x00,0x00,0x18,0x00,0x00,0x10,0x00,0x00,0x10,0x00,0x00,0x10,0x00,0x00,0x10,0x08,0x3F,0xFF,0xFC,0x00,0x10,0x00,0x00,0x18,0x00,0x00,0x18,0x00,0x00,0x18,0x00,0x00,0x34,0x00,0x00,0x24,0x00,0x00,0x22,0x00,0x00,0x63,0x00,0x00,0x41,0x00,0x00,0xC0,0x80,0x01,0x80,0xC0,0x03,0x00,0x70,0x04,0x00,0x3C,0x18,0x00,0x08,0x20,0x00,0x00,0x00,0x00,0x00},/*"大",2*/
														{0x00,0x00,0x00,0x00,0x10,0x00,0x00,0x18,0x00,0x00,0x18,0x00,0x00,0x18,0x00,0x1F,0xFF,0xF0,0x00,0x18,0x00,0x00,0x18,0x00,0x00,0x18,0x00,0x00,0x18,0x00,0x00,0x10,0x08,0x3F,0xFF,0xFC,0x00,0x14,0x00,0x00,0x34,0x00,0x00,0x32,0x00,0x00,0x22,0x00,0x00,0x41,0x00,0x00,0xC1,0x80,0x01,0x80,0xC0,0x03,0x00,0x60,0x04,0x00,0x38,0x18,0x00,0x1C,0x20,0x00,0x08,0x00,0x00,0x00}};/*"夫",3*/
void Draw_char_Ch(uint16_t usX,uint16_t usY,u8 *ptr)
{
	u16 bytecount,bitcount;
	ILI9341_OpenWindow ( usX, usY, CH_Width, CH_Height);
	ILI9341_Write_Cmd ( CMD_SetPixel );
	for(bytecount=0;bytecount<24;bytecount++)
	{
		for(bitcount=0;bitcount<8;bitcount++)
		{
			if((ptr[bytecount*3]<<bitcount)&0x80)
			{
				ILI9341_Write_Data ( CurrentTextColor );
			}
			else
			{
				ILI9341_Write_Data ( CurrentBackColor );
			}
		}
		
		for(bitcount=0;bitcount<8;bitcount++)
		{
			if((ptr[bytecount*3+1]<<bitcount)&0x80)
			{
				ILI9341_Write_Data ( CurrentTextColor );
			}
			else
			{
				ILI9341_Write_Data ( CurrentBackColor );
			}
		}
		
		for(bitcount=0;bitcount<8;bitcount++)
		{
			if((ptr[bytecount*3+2]<<bitcount)&0x80)
			{
				ILI9341_Write_Data ( CurrentTextColor );
			}
			else
			{
				ILI9341_Write_Data ( CurrentBackColor );
			}
		}
	}
}

/*@brief  显示汉字字符串
* @param line:显示的行数
* @param ptr:输入一个二维数组的变量名(一维指针数组)
* @retval 无
*/
void Draw_string_Ch(uint16_t line,u8 (*ptr)[72])
{
	u16 usX=0;
	u16 wordcount;
	for(wordcount=0;wordcount<LENGTH_CH;wordcount++)
	{
		Draw_char_Ch(usX,line,ptr[wordcount]);
		usX+=24;
	}
}

使用步骤

	ILI9341_GramScan ( 6 );
	LCD_SetColors(RED,BLACK);
	ILI9341_Clear(0,0,LCD_X_LENGTH,LCD_Y_LENGTH);	/* 清屏,显示全黑 */
	Draw_string_Ch(24,charer_Ch);

英文的显示通过英文字符的ASCII码来实现对字模库的检索

Reference:
野火教程