⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 tft_lcd.c

📁 STM32综合例程(3.5.0固件库)
💻 C
📖 第 1 页 / 共 2 页
字号:
#include "stm32f10x.h"
#include <stdio.h>
#include "systick.h"
#include "tft_lcd.h"
#include "fonts.h"
#include "fonts_ascii16x24.h"

typedef struct
{
	__IO uint16_t LCD_REG;
	__IO uint16_t LCD_RAM;
}
LCD_TypeDef;

/* 定义LCD驱动器的访问地址 */
#define LCD_BASE        ((uint32_t)(0x60000000 | 0x0C000000))	 //FSMC
#define LCD             ((LCD_TypeDef *) LCD_BASE)   //TFT LCD

static __IO uint16_t s_TextColor = 0x0000;	    //文本色
static __IO uint16_t s_BackColor = 0xffff;		//背景色

/* armfly添加透明标志
	s_Transparent = 1 表示显示文字时,不修改背景颜色
*/
static __IO uint8_t s_Transparent = 0;	 //显示文字时修改背景色
void LCD_WriteReg(__IO uint16_t LCD_Reg, uint16_t LCD_RegValue);
/*******************************************************************************
*	函数名: LCD_Init
*	参  数: 无
*	返  回: 无
*	功  能: 初始化TFT显示器
*/
void LCD_Init(void)
{
	/* 配置LCD控制口线GPIO */
	LCD_CtrlLinesConfig();  //配置LCD控制线

	/* 配置FSMC接口,数据总线 */
	LCD_FSMCConfig();	//配置LCD数据线及地址线

	/* FSMC重置后必须加延迟才能访问总线设备  */
	DelayMS(20);	//延时

	/* 初始化LCD,写LCD寄存器进行配置 */
//	LCD_WriteReg(0x0000, 0x0000);
	LCD_WriteReg(0x0001, 0x0100);
	LCD_WriteReg(0x0002, 0x0100);

	/*
		R003H 寄存器很关键, Entry Mode ,决定了扫描方向
		参见:SPFD5420A.pdf 第15页

		240x400屏幕物理坐标(px,py)如下:
		    R003 = 0x1018                  R003 = 0x1008
		  -------------------          -------------------
		 |(0,0)              |        |(0,0)              |
		 |                   |        |
		 |  ^           ^    |        |   ^           ^   |
		 |  |           |    |        |   |           |   |
		 |  |           |    |        |   |           |   |
		 |  |           |    |        |   |           |   |
		 |  |  ------>  |    |        |   | <------   |   |
		 |  |           |    |        |   |           |   |
		 |  |           |    |        |   |           |   |
		 |  |           |    |        |   |           |   |
		 |  |           |    |        |   |           |   |
		 |                   |        |
		 |                   |        |                   |
		 |      (x=239,y=399)|        |      (x=239,y=399)|
		 |-------------------|        |-------------------|
		 |                   |        |                   |
		  -------------------          -------------------

		按照安富莱开发板LCD的方向,我们期望的虚拟坐标和扫描方向如下:(和上图第1个吻合)
		 --------------------------------
		|  |(0,0)                        |
		|  |     --------->              |
		|  |         |                   |
		|  |         |                   |
		|  |         |                   |
		|  |         V                   |
		|  |     --------->              |
		|  |                    (399,239)|
		 --------------------------------

		虚拟坐标(x,y) 和物理坐标的转换关系
		x = 399 - py;
		y = px;

		py = 399 - x;
		px = y;

	*/
	LCD_WriteReg(0x0003, 0x1018); /* 0x1018 1030 */

	LCD_WriteReg(0x0008, 0x0808);
	LCD_WriteReg(0x0009, 0x0001);
	LCD_WriteReg(0x000B, 0x0010);
	LCD_WriteReg(0x000C, 0x0000);
	LCD_WriteReg(0x000F, 0x0000);
	LCD_WriteReg(0x0007, 0x0001);
	LCD_WriteReg(0x0010, 0x0013);
	LCD_WriteReg(0x0011, 0x0501);
	LCD_WriteReg(0x0012, 0x0300);
	LCD_WriteReg(0x0020, 0x021E);
	LCD_WriteReg(0x0021, 0x0202);
	LCD_WriteReg(0x0090, 0x8000);
	LCD_WriteReg(0x0100, 0x17B0);
	LCD_WriteReg(0x0101, 0x0147);
	LCD_WriteReg(0x0102, 0x0135);
	LCD_WriteReg(0x0103, 0x0700);
	LCD_WriteReg(0x0107, 0x0000);
	LCD_WriteReg(0x0110, 0x0001);
	LCD_WriteReg(0x0210, 0x0000);
	LCD_WriteReg(0x0211, 0x00EF);
	LCD_WriteReg(0x0212, 0x0000);
	LCD_WriteReg(0x0213, 0x018F);
	LCD_WriteReg(0x0280, 0x0000);
	LCD_WriteReg(0x0281, 0x0004);
	LCD_WriteReg(0x0282, 0x0000);
	LCD_WriteReg(0x0300, 0x0101);
	LCD_WriteReg(0x0301, 0x0B2C);
	LCD_WriteReg(0x0302, 0x1030);
	LCD_WriteReg(0x0303, 0x3010);
	LCD_WriteReg(0x0304, 0x2C0B);
	LCD_WriteReg(0x0305, 0x0101);
	LCD_WriteReg(0x0306, 0x0807);
	LCD_WriteReg(0x0307, 0x0708);
	LCD_WriteReg(0x0308, 0x0107);
	LCD_WriteReg(0x0309, 0x0105);
	LCD_WriteReg(0x030A, 0x0F04);
	LCD_WriteReg(0x030B, 0x0F00);
	LCD_WriteReg(0x030C, 0x000F);
	LCD_WriteReg(0x030D, 0x040F);
	LCD_WriteReg(0x030E, 0x0300);
	LCD_WriteReg(0x030F, 0x0701);
	LCD_WriteReg(0x0400, 0x3500);
	LCD_WriteReg(0x0401, 0x0001);
	LCD_WriteReg(0x0404, 0x0000);
	LCD_WriteReg(0x0500, 0x0000);
	LCD_WriteReg(0x0501, 0x0000);
	LCD_WriteReg(0x0502, 0x0000);
	LCD_WriteReg(0x0503, 0x0000);
	LCD_WriteReg(0x0504, 0x0000);
	LCD_WriteReg(0x0505, 0x0000);
	LCD_WriteReg(0x0600, 0x0000);
	LCD_WriteReg(0x0606, 0x0000);
	LCD_WriteReg(0x06F0, 0x0000);
	LCD_WriteReg(0x07F0, 0x5420);
	LCD_WriteReg(0x07DE, 0x0000);
	LCD_WriteReg(0x07F2, 0x00DF);
	LCD_WriteReg(0x07F3, 0x0810);
	LCD_WriteReg(0x07F4, 0x0077);
	LCD_WriteReg(0x07F5, 0x0021);
	LCD_WriteReg(0x07F0, 0x0000);
	LCD_WriteReg(0x0007, 0x0173);

	/* 设置显示窗口 WINDOWS */
	LCD_WriteReg(0x0210, 0);	/* 水平起始地址 */
	LCD_WriteReg(0x0211, 239);	/* 水平结束坐标 */
	LCD_WriteReg(0x0212, 0);	/* 垂直起始地址 */
	LCD_WriteReg(0x0213, 399);	/* 垂直结束地址 */
}

/*******************************************************************************
*	函数名: LCD_SetTextColor
*	参  数: Color : 文本颜色
*	返  回: 无
*	功  能: 设置文本颜色,保存在全部变量s_TextColor
*/
void LCD_SetTextColor(__IO uint16_t Color)
{
	s_TextColor = Color;
}

/*******************************************************************************
*	函数名: LCD_SetBackColor
*	参  数: Color : 背景颜色
*	返  回: 无
*	功  能: 设置背景颜色,保存在全部变量 s_BackColor
*/
void LCD_SetBackColor(__IO uint16_t Color)
{
	s_BackColor = Color;
}

/*******************************************************************************
*	函数名: LCD_ClearLine
*	参  数: Line : 文本行号0 - 9
*	返  回: 无
*	功  能: 清除选定的文本行
*/
void LCD_ClearLine(uint8_t Line)
{
	LCD_DisplayString(0, Line, "                    ");
}

/*******************************************************************************
*	函数名: LCD_Clear
*	参  数: Color : 背景色
*	返  回: 无
*	功  能: 根据输入的颜色值清屏
*/
void LCD_Clear(uint16_t Color)
{
	uint32_t index = 0;

	LCD_SetCursor(0, 0);	/* 设置光标位置 */

	LCD_WriteRAM_Prepare(); 	/* 准备写显存 */

	for (index = 0; index < 400 * 240; index++)
	{
		LCD->LCD_RAM = Color;	  //把全部显存值设为背景色
	}
}

/*******************************************************************************
*	函数名: LCD_SetCursor
*	参  数: Xpos : X坐标; Ypos: Y坐标
*	返  回: 无
*	功  能: 设置光标位置
*/
void LCD_SetCursor(uint16_t Xpos, uint16_t Ypos)
{
	/*
		px,py 是物理坐标, x,y是虚拟坐标
		转换公式:
		py = 399 - x;
		px = y;
	*/

	LCD_WriteReg(0x0200, Ypos);  		/* px */
	LCD_WriteReg(0x0201, 399 - Xpos);	/* py */
}

/*******************************************************************************
*	函数名: LCD_SetTransparent
*	参  数: _mode ; 透明标志,1表示透明 0 表示不透明
*	返  回: 无
*	功  能: 设置光标位置
*/
void LCD_SetTransparent(uint8_t _mode)
{
	if (_mode == 0)
	{
		s_Transparent = 0;	/* 设置为背景不透明 */
	}
	else
	{
		s_Transparent = 1;	/* 设置为背景透明 */
	}
}

/*******************************************************************************
*	函数名: LCD_DrawChar
*	参  数:
*		Xpos : X坐标;
*		Ypos: Y坐标;
*		c : 指向字符点阵的指针
*	返  回: 无
*	功  能: 在LCD上显示一个字符(16x24)
*/
void LCD_DrawChar(uint16_t Xpos, uint16_t Ypos, const uint16_t *c)
{
	uint32_t index = 0, i = 0;
	uint8_t Yaddress;

	Yaddress = Ypos;

	LCD_SetCursor(Xpos, Ypos);

	if (s_Transparent == 0)
	{
		for (index = 0; index < 24; index++)	/* 字符高度 */
		{
			LCD_WriteRAM_Prepare();
			for (i = 0; i < 16; i++)	/* 字符宽度 */
			{
				if ((c[index] & (1 << i)) == 0x00)
				{
					LCD_WriteRAM(s_BackColor);
				}
				else
				{
					LCD_WriteRAM(s_TextColor);
				}
			}
			Yaddress++;
			LCD_SetCursor(Xpos, Yaddress);
		}
	}
	else	/* armfly 添加:实现文字叠加在图片上的功能 */
	{
		for (index = 0; index < 24; index++)	/* 字符高度 */
		{
			uint16_t x = Xpos;

			for (i = 0; i < 16; i++)	/* 字符宽度 */
			{
				if ((c[index] & (1 << i)) != 0x00)
				{
					LCD_SetCursor(x, Yaddress);

					LCD->LCD_REG = 0x202;
					LCD->LCD_RAM = s_TextColor;
				}
				x++;
			}
			Yaddress++;
		}
	}
}

/*******************************************************************************
*	函数名: LCD_DisplayChar
*	参  数:
*		Xpos : X坐标);
*		Ypos : Y坐标)
*		Ascii : 字符的ASCII代码,在0x20和0x7E之间
*	返  回: 无
*	功  能: 在LCD上显示一个字符(16x24)
*/
void LCD_DisplayChar(uint16_t Xpos, uint16_t Ypos, uint8_t Ascii)
{
	Ascii -= ' ';
	LCD_DrawChar(Xpos, Ypos, &Ascii_16x24[Ascii * 24]);
}

/*******************************************************************************
*	函数名: LCD_DisplayString
*	参  数:
*		Xpos : X坐标 0 - 399
*		Ypos : Y坐标 0 - 239
*		ptr  : 字符串指针;
*	返  回: 无
*	功  能: 在LCD指定文本行显示一个字符串
*/
void LCD_DisplayString(uint16_t Xpos, uint16_t Ypos, uint8_t *ptr)
{
	uint32_t i = 0;

	while ((*ptr != 0) & (i < 30))
	{
		LCD_DisplayChar(Xpos, Ypos, *ptr);		/* 在LCD上显示1个字符 */
		Xpos += 16;									/* 列地址减16 */
		ptr++;			/* 指针指向下一个字符 */
		i++;
	}
}

/*******************************************************************************
*	函数名: LCD_SetDisplayWindow
*	参  数:
*		Xpos : 显示行号
*		Ypos  : 字符串指针;
*		Height: 窗口高度
*		Width : 窗口宽度
*	返  回: 无
*	功  能: 设置显示窗口
*/
void LCD_SetDisplayWindow(uint16_t Xpos, uint16_t Ypos, uint8_t Height, uint16_t Width)
{
	/* 水平起始地址 */
	if (Xpos >= Height)
	{
		LCD_WriteReg(R80, (Xpos - Height + 1));
	}
	else
	{
		LCD_WriteReg(R80, 0);
	}

	/* 水平结束地址 */
	LCD_WriteReg(R81, Xpos);

	/* 垂直起始地址 */
	if (Ypos >= Width)
	{
		LCD_WriteReg(R82, (Ypos - Width + 1));
	}
	else
	{
		LCD_WriteReg(R82, 0);
	}

	/* 垂直结束地址 */
	LCD_WriteReg(R83, Ypos);

	LCD_SetCursor(Xpos, Ypos);
}

/*******************************************************************************
*	函数名: LCD_WindowModeDisable
*	参  数: 无
*	返  回: 无
*	功  能: 退出窗口显示模式,变为全屏显示模式
*/
void LCD_WindowModeDisable(void)
{
	LCD_SetDisplayWindow(239, 399, 240, 400);
	LCD_WriteReg(R3, 0x1018);	/* 这个寄存器改变扫描方向 */
}

/*******************************************************************************
*	函数名: LCD_DrawLine
*	参  数: Xpos :X坐标
*			YPos :Y坐标
*			Length    :长度
*			Direction :方向(Horizontal,Vertical)
*	返  回: 无
*	功  能: 在LCD上画1条线
*/

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -