📄 tft_lcd.c
字号:
#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 + -