630 lines
11 KiB
C
630 lines
11 KiB
C
/**
|
||
******************************************************************************
|
||
*
|
||
* TFT 1.14寸显示屏驱动文件,目前使用SPI
|
||
*
|
||
* 版本修订:
|
||
* 修改时间 版本号 修改内容
|
||
* 2022-12-07 v1.0 开始构建本文件;
|
||
*
|
||
* Create :2016年09月09日
|
||
* Update :2022年12月07日
|
||
* Author :dengchow
|
||
*
|
||
******************************************************************************
|
||
***/
|
||
|
||
#include "Driver_tftspi.h"
|
||
|
||
#define LCD_MODE 2
|
||
// 0 // 竖屏
|
||
// 1
|
||
// 2 // 横屏
|
||
// 3
|
||
|
||
uint16_t POINT_COLOR = 0x0000;//画笔颜色
|
||
uint16_t BACK_COLOR = 0xFFFF;//背景色
|
||
|
||
_TFTCmdTypeStruct TFTCmd;//管理LCD重要参数
|
||
|
||
/**
|
||
* @brief :模拟SPI发送数据
|
||
* @note :--
|
||
* @param :dat,待发送的数据
|
||
* @return :void
|
||
*
|
||
* @data :2023/01/21
|
||
* @design :
|
||
**/
|
||
static void _spi_write_data(uint8_t dat)
|
||
{
|
||
#ifdef LCD_SPI_SOFT
|
||
for (uint8_t i=0; i<8; i++)
|
||
{
|
||
LCD_SCL_L;
|
||
if (dat & 0x80) {
|
||
LCD_SDA_H;
|
||
} else {
|
||
LCD_SDA_L;
|
||
}
|
||
LCD_SCL_H;
|
||
dat <<= 1;
|
||
}
|
||
#endif
|
||
}
|
||
|
||
/**
|
||
* @brief :写寄存器地址
|
||
* @note :--
|
||
* @param :reg, 寄存器地址
|
||
* @return :void
|
||
*
|
||
* @data :2017/03/04
|
||
* @design :
|
||
**/
|
||
void TFT_WR_REG(uint16_t reg)
|
||
{
|
||
TFT_DC_CMD();
|
||
_spi_write_data(reg);
|
||
|
||
TFT_DC_DATA();
|
||
}
|
||
|
||
|
||
|
||
/**
|
||
* @brief :写数据
|
||
* @note :--使用此函数前先调用TFT_WR_REG(),即写寄存器函数!
|
||
* @param :dat, 要写入的值
|
||
* @return :void
|
||
*
|
||
* @data :2017/03/04
|
||
* @design :
|
||
**/
|
||
void TFT_WR_DATA8(uint8_t dat)
|
||
{
|
||
_spi_write_data(dat);
|
||
}
|
||
|
||
void TFT_WR_DATA(uint16_t dat)
|
||
{
|
||
_spi_write_data(dat>>8);
|
||
_spi_write_data(dat);
|
||
}
|
||
|
||
|
||
|
||
/**
|
||
* @brief :读数据
|
||
* @note :--读数据前先写寄存器地址!
|
||
* @param :void
|
||
* @return :uint16_t, 读到的值
|
||
*
|
||
* @data :2017/03/04
|
||
* @design :
|
||
**/
|
||
uint16_t TFT_RD_DATA(void)
|
||
{
|
||
return BACK_COLOR; // NO USED!
|
||
}
|
||
|
||
|
||
|
||
/**
|
||
* @brief :选择lcd设备
|
||
* @note :--
|
||
* @param :idx, lcd序号
|
||
en, 1选中/0未选中
|
||
* @return :void
|
||
*
|
||
* @data :2017/03/04
|
||
* @design :
|
||
**/
|
||
void TFT_Select(uint8_t idx, uint8_t en)
|
||
{
|
||
if (0 == en)
|
||
{
|
||
switch (idx)
|
||
{
|
||
case 0: LCD_CS0_DIS; break;
|
||
|
||
default: {
|
||
LCD_CS0_DIS;
|
||
break;
|
||
}
|
||
}
|
||
} else {
|
||
switch (idx)
|
||
{
|
||
case 0: LCD_CS0_EN; break;
|
||
|
||
default: {
|
||
LCD_CS0_EN;
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
|
||
|
||
/**
|
||
* @brief :向寄存器写数据
|
||
* @note :--
|
||
* @param :reg, 寄存器地址
|
||
dat, 要写入的值
|
||
* @return :void
|
||
*
|
||
* @data :2017/03/04
|
||
* @design :
|
||
**/
|
||
void TFT_WriteReg(uint16_t reg, uint16_t dat)
|
||
{
|
||
TFT_WR_REG(reg);
|
||
TFT_WR_DATA(dat);
|
||
}
|
||
|
||
|
||
|
||
/**
|
||
* @brief :从寄存器读数据
|
||
* @note :--
|
||
* @param :Reg, 寄存器地址
|
||
* @return :uint16_t, 读到的数据
|
||
*
|
||
* @data :2017/03/04
|
||
* @design :
|
||
**/
|
||
uint16_t TFT_ReadReg(uint16_t reg)
|
||
{
|
||
return 0xFFFF; // NO USED!
|
||
}
|
||
|
||
|
||
|
||
/**
|
||
* @brief :开始写GRAM
|
||
* @note :--
|
||
* @param :void
|
||
* @return :void
|
||
*
|
||
* @data :2017/03/04
|
||
* @design :
|
||
**/
|
||
void TFT_StartWriteRAM(void)
|
||
{
|
||
TFT_WR_REG(0x2C);
|
||
}
|
||
|
||
|
||
|
||
/**
|
||
* @brief :写GRAM
|
||
* @note :--
|
||
* @param :color, 颜色值
|
||
* @return :void
|
||
*
|
||
* @data :2017/03/04
|
||
* @design :
|
||
**/
|
||
void TFT_WriteRAM(uint16_t color)
|
||
{
|
||
TFT_WR_DATA(color);
|
||
}
|
||
|
||
|
||
|
||
/**
|
||
* @brief :tft开启显示
|
||
* @note :
|
||
* @param :void
|
||
* @return :void
|
||
*
|
||
* @data :2017/03/04
|
||
* @design :
|
||
**/
|
||
void TFT_DisplayOn(void)
|
||
{
|
||
// NO USED!
|
||
}
|
||
|
||
|
||
|
||
/**
|
||
* @brief :tft关闭显示
|
||
* @note :--
|
||
* @param :void
|
||
* @return :void
|
||
*
|
||
* @data :2017/03/04
|
||
* @design :
|
||
**/
|
||
void TFT_DisplayOff(void)
|
||
{
|
||
// NO USED!
|
||
}
|
||
|
||
|
||
|
||
/**
|
||
* @brief :设置光标位置
|
||
* @note :--
|
||
* @param :X1, 横坐标(0~TFTCmd.width)
|
||
Y1, 纵坐标(0~TFTCmd.height)
|
||
X2, 横坐标(0~TFTCmd.width)
|
||
Y3, 纵坐标(0~TFTCmd.height)
|
||
* @return :void
|
||
*
|
||
* @data :2017/03/04
|
||
* @design :
|
||
**/
|
||
void TFT_SetCursor(uint16_t X1, uint16_t Y1, uint16_t X2, uint16_t Y2)
|
||
{
|
||
#if (LCD_MODE == 0)
|
||
const uint16_t _k_x_base = 52;
|
||
const uint16_t _k_y_base = 40;
|
||
#endif
|
||
#if (LCD_MODE == 1)
|
||
const uint16_t _k_x_base = 53;
|
||
const uint16_t _k_y_base = 40;
|
||
#endif
|
||
#if (LCD_MODE == 2)
|
||
const uint16_t _k_x_base = 40;
|
||
const uint16_t _k_y_base = 53;
|
||
#endif
|
||
#if (LCD_MODE == 3)
|
||
const uint16_t _k_x_base = 40;
|
||
const uint16_t _k_y_base = 52;
|
||
#endif
|
||
|
||
TFT_WR_REG(0x2A); //列地址设置
|
||
TFT_WR_DATA(X1+_k_x_base);
|
||
TFT_WR_DATA(X2+_k_x_base);
|
||
|
||
TFT_WR_REG(0x2B); //行地址设置
|
||
TFT_WR_DATA(Y1+_k_y_base);
|
||
TFT_WR_DATA(Y2+_k_y_base);
|
||
}
|
||
|
||
|
||
|
||
/**
|
||
* @brief :设置tft的自动扫描方向
|
||
* @note :--ILI9341的其他函数可能会受到此函数设置的影响,所以,一般设置为L2R_U2D!
|
||
--针对ILI9341进行修改,修复无法横屏的bug!
|
||
--设置ILI9341默认为RGB格式!
|
||
* @param :direct, 扫描方向(_TFTScanDir枚举类型中定义!)
|
||
* @return :void
|
||
*
|
||
* @data :2018/01/24
|
||
* @design :
|
||
**/
|
||
void TFT_SetScanDir(_TFTScanDir direct)
|
||
{
|
||
// NO USED!
|
||
}
|
||
|
||
|
||
|
||
/**
|
||
* @brief :设置tft显示方向
|
||
* @note :--
|
||
* @param :direct, 显示方向(_TFTDispDir枚举类型定义!)
|
||
* @return :void
|
||
*
|
||
* @data :2017/03/04
|
||
* @design :
|
||
**/
|
||
void TFT_SetDisplayDir(_TFTDispDir direct)
|
||
{
|
||
if(direct == DISP_PORTRAIT)//竖屏
|
||
{
|
||
TFTCmd.dir = DISP_PORTRAIT;
|
||
TFTCmd.width = CFG_LCD_Y_SIZE;
|
||
TFTCmd.height = CFG_LCD_X_SIZE;
|
||
}else{//横屏
|
||
TFTCmd.dir = DISP_HORIZON;
|
||
TFTCmd.width = CFG_LCD_X_SIZE;
|
||
TFTCmd.height = CFG_LCD_Y_SIZE;
|
||
}
|
||
|
||
TFTCmd.wramcmd = 0; // NO USED!
|
||
TFTCmd.setxcmd = 0; // NO USED!
|
||
TFTCmd.setycmd = 0; // NO USED!
|
||
}
|
||
|
||
|
||
|
||
|
||
/**
|
||
* @brief :设置tft窗口大小
|
||
* @note :--窗体大小,width*height!
|
||
* @param :XS , 窗口起始横坐标
|
||
YS , 窗口起始纵坐标
|
||
width , 窗口宽度,必须大于0!
|
||
height, 窗口高度,必须大于0!
|
||
* @return :void
|
||
*
|
||
* @data :2017/03/04
|
||
* @design :
|
||
**/
|
||
void TFT_SetWindowSize(uint16_t XS, uint16_t YS, uint16_t width, uint16_t height)
|
||
{
|
||
// NO USED!
|
||
}
|
||
|
||
|
||
|
||
/**
|
||
* @brief :tft初始化设置
|
||
* @note :--
|
||
* @param :void
|
||
* @return :void
|
||
*
|
||
* @data :2017/03/04
|
||
* @design :
|
||
**/
|
||
void TFT_InitConfig(void)
|
||
{
|
||
TFT_BACK_LED_CLOSE();
|
||
|
||
TFT_Select(0xff, 1); // SELECT ALL DEVICE!
|
||
|
||
TFT_RST_HIGH();
|
||
delay_ms(1);
|
||
TFT_RST_LOW();
|
||
delay_ms(10);
|
||
TFT_RST_HIGH();
|
||
delay_ms(120);
|
||
|
||
TFT_WR_REG(0x36);
|
||
#if (LCD_MODE == 0)
|
||
TFT_WR_DATA8(0x00);
|
||
#endif
|
||
#if (LCD_MODE == 1)
|
||
TFT_WR_DATA8(0xC0);
|
||
#endif
|
||
#if (LCD_MODE == 2)
|
||
TFT_WR_DATA8(0x70);
|
||
#endif
|
||
#if (LCD_MODE == 3)
|
||
TFT_WR_DATA8(0xA0);
|
||
#endif
|
||
|
||
TFT_WR_REG(0x3A);
|
||
TFT_WR_DATA8(0x05);
|
||
|
||
TFT_WR_REG(0xB2);
|
||
TFT_WR_DATA8(0x0C);
|
||
TFT_WR_DATA8(0x0C);
|
||
TFT_WR_DATA8(0x00);
|
||
TFT_WR_DATA8(0x33);
|
||
TFT_WR_DATA8(0x33);
|
||
|
||
TFT_WR_REG(0xB7);
|
||
TFT_WR_DATA8(0x35);
|
||
|
||
TFT_WR_REG(0xBB);
|
||
TFT_WR_DATA8(0x19);
|
||
|
||
TFT_WR_REG(0xC0);
|
||
TFT_WR_DATA8(0x2C);
|
||
|
||
TFT_WR_REG(0xC2);
|
||
TFT_WR_DATA8(0x01);
|
||
|
||
TFT_WR_REG(0xC3);
|
||
TFT_WR_DATA8(0x12);
|
||
|
||
TFT_WR_REG(0xC4);
|
||
TFT_WR_DATA8(0x20);
|
||
|
||
TFT_WR_REG(0xC6);
|
||
TFT_WR_DATA8(0x0F);
|
||
|
||
TFT_WR_REG(0xD0);
|
||
TFT_WR_DATA8(0xA4);
|
||
TFT_WR_DATA8(0xA1);
|
||
|
||
TFT_WR_REG(0xE0);
|
||
TFT_WR_DATA8(0xD0);
|
||
TFT_WR_DATA8(0x04);
|
||
TFT_WR_DATA8(0x0D);
|
||
TFT_WR_DATA8(0x11);
|
||
TFT_WR_DATA8(0x13);
|
||
TFT_WR_DATA8(0x2B);
|
||
TFT_WR_DATA8(0x3F);
|
||
TFT_WR_DATA8(0x54);
|
||
TFT_WR_DATA8(0x4C);
|
||
TFT_WR_DATA8(0x18);
|
||
TFT_WR_DATA8(0x0D);
|
||
TFT_WR_DATA8(0x0B);
|
||
TFT_WR_DATA8(0x1F);
|
||
TFT_WR_DATA8(0x23);
|
||
|
||
TFT_WR_REG(0xE1);
|
||
TFT_WR_DATA8(0xD0);
|
||
TFT_WR_DATA8(0x04);
|
||
TFT_WR_DATA8(0x0C);
|
||
TFT_WR_DATA8(0x11);
|
||
TFT_WR_DATA8(0x13);
|
||
TFT_WR_DATA8(0x2C);
|
||
TFT_WR_DATA8(0x3F);
|
||
TFT_WR_DATA8(0x44);
|
||
TFT_WR_DATA8(0x51);
|
||
TFT_WR_DATA8(0x2F);
|
||
TFT_WR_DATA8(0x1F);
|
||
TFT_WR_DATA8(0x1F);
|
||
TFT_WR_DATA8(0x20);
|
||
TFT_WR_DATA8(0x23);
|
||
|
||
TFT_WR_REG(0x21);
|
||
|
||
TFT_SetDisplayDir(DISP_HORIZON);
|
||
TFT_SetWindowSize(0, 0, TFTCmd.width, TFTCmd.height);
|
||
|
||
TFT_WR_REG(0x11);
|
||
delay_ms(120);
|
||
|
||
TFT_WR_REG(0x29);
|
||
TFT_WR_REG(0x2C);
|
||
|
||
TFT_ClearScreen(WHITE);
|
||
|
||
TFT_Select(0xff, 0); // UNSELECT ALL DEVICE!
|
||
|
||
TFT_BACK_LED_OPEN();
|
||
}
|
||
|
||
|
||
|
||
/**
|
||
* @brief :tft清屏
|
||
* @note :--以特定的颜色填充整块屏幕!
|
||
* @param :color, 要清屏的填充色
|
||
* @return :void
|
||
*
|
||
* @data :2017/03/04
|
||
* @design :
|
||
**/
|
||
void TFT_ClearScreen(uint16_t color)
|
||
{
|
||
TFT_FillSingleColor(0, 0, TFTCmd.width, TFTCmd.height, color);
|
||
}
|
||
|
||
|
||
|
||
/**
|
||
* @brief :特殊延时
|
||
* @note :--当mdk -O1时间优化时需要设置,一般不涉及!
|
||
* @param :t, 特殊延时
|
||
* @return :void
|
||
*
|
||
* @data :2017/03/04
|
||
* @design :
|
||
**/
|
||
//static void opt_delay(uint32_t t)
|
||
//{
|
||
// while(t--);
|
||
//}
|
||
|
||
|
||
|
||
/**
|
||
* @brief :tft读点
|
||
* @note :--
|
||
* @param :X, 横坐标(0~TFTCmd.width)
|
||
Y, 纵坐标(0~TFTCmd.height)
|
||
* @return :uint16_t, RGB格式的颜色值
|
||
*
|
||
* @data :2017/03/04
|
||
* @design :
|
||
**/
|
||
uint16_t TFT_ReadPoint(uint16_t X, uint16_t Y)
|
||
{
|
||
return BACK_COLOR; // NO USED!
|
||
}
|
||
|
||
|
||
|
||
/**
|
||
* @brief :tft画点
|
||
* @note :--
|
||
* @param :X , 横坐标(0~TFTCmd.width)
|
||
Y , 纵坐标(0~TFTCmd.height)
|
||
color, 颜色(取自调色板定义的颜色或者其他颜色!)
|
||
* @return :void
|
||
*
|
||
* @data :2017/03/04
|
||
* @design :
|
||
**/
|
||
void TFT_DrawPoint(uint16_t X, uint16_t Y, uint16_t color)
|
||
{
|
||
if ((X >= TFTCmd.width) || (Y >= TFTCmd.height))
|
||
return;
|
||
|
||
TFT_SetCursor(X, Y, X, Y);
|
||
TFT_StartWriteRAM();
|
||
TFT_WR_DATA(color);
|
||
}
|
||
|
||
|
||
|
||
/**
|
||
* @brief :tft快速画点
|
||
* @note :--本函数需要Driver_tft.c支持!
|
||
* @param :X , 横坐标(0~TFTCmd.width)
|
||
Y , 纵坐标(0~TFTCmd.height)
|
||
color, 颜色
|
||
* @return :void
|
||
*
|
||
* @data :2017/03/04
|
||
* @design :
|
||
**/
|
||
void TFT_FastDrawPoint(uint16_t X, uint16_t Y, uint16_t color)
|
||
{
|
||
TFT_DrawPoint(X, Y, color);
|
||
}
|
||
|
||
|
||
|
||
/**
|
||
* @brief :在指定区域内填充单个颜色
|
||
* @note :--填充矩形区域,大小为:(XE-XS)*(YE-YS)
|
||
* @param :XS , 起点横坐标
|
||
YS , 起点纵坐标
|
||
XE , 终点横坐标
|
||
YE , 终点纵坐标
|
||
Color, 要填充的颜色
|
||
* @return :void
|
||
*
|
||
* @data :2017/03/04
|
||
* @design :
|
||
**/
|
||
void TFT_FillSingleColor(uint16_t XS, uint16_t YS, uint16_t XE, uint16_t YE, uint16_t color)
|
||
{
|
||
uint16_t height, width;
|
||
|
||
width = XE - XS;
|
||
height = YE - YS;
|
||
|
||
TFT_SetCursor(XS, YS, XE-1, YE-1);
|
||
TFT_StartWriteRAM();
|
||
|
||
for (uint16_t i=0; i<width*height; i++ ) {
|
||
TFT_WR_DATA(color);
|
||
}
|
||
}
|
||
|
||
|
||
|
||
/**
|
||
* @brief :在指定区域内填充指定颜色块
|
||
* @note :--填充矩形区域,大小为:(XE-XS)*(YE-YS)
|
||
* @param :XS , 起点横坐标
|
||
YS , 起点纵坐标
|
||
XE , 终点横坐标
|
||
YE , 终点纵坐标
|
||
*color, 要填充的颜色
|
||
* @return :void
|
||
*
|
||
* @data :2017/03/04
|
||
* @design :
|
||
**/
|
||
void TFT_FillBlockColor(uint16_t XS, uint16_t YS, uint16_t XE, uint16_t YE, uint16_t *color)
|
||
{
|
||
uint16_t height, width;
|
||
|
||
width = XE - XS;
|
||
height = YE - YS;
|
||
|
||
TFT_SetCursor(XS, YS, XE-1, YE-1);
|
||
TFT_StartWriteRAM();
|
||
|
||
for (uint16_t i=0; i<width*height; i++ ) {
|
||
TFT_WR_DATA(color[i]);
|
||
}
|
||
}
|
||
|
||
/* ******************** Copyright (C), 2017-2017, TYUT TSS-plan by SERI.LJI ******************** */
|