📄 tftlcd.c
字号:
#include "COMM.H"
#include "font.h"
//液晶显示 淘宝超值27元的液晶
//加入了GRAM 读写的函数,可以读取指定GRAM的内容了
//正点原子@SCUT
//2008/12/15
//V1.2
//修改了数字显示函数TFT_ShowNum,可以支持自动识别数字范围.
//扩充显示范围到u32类型
//-----------------TFT端口定义----------------
#define TFT_RS (1<<0) //数据/命令选择端口 PB0
#define TFT_WR (1<<1) //数据端口 PB1
#define TFT_CS (1<<2) //片选端口 PB2
#define TFT_LED (1<<2) //TFT背光 PA2
#define TFT_RST (1<<3) //硬复位 PA3
#define TFT_RD (1<<4) //时钟端口 PA4
#define TFT_RS_SET(x) GPIOB->ODR=(GPIOB->ODR&~TFT_RS)|(x ? TFT_RS:0)
#define TFT_WR_SET(x) GPIOB->ODR=(GPIOB->ODR&~TFT_WR)|(x ? TFT_WR:0)
#define TFT_CS_SET(x) GPIOB->ODR=(GPIOB->ODR&~TFT_CS)|(x ? TFT_CS:0)
#define TFT_LED_SET(x) GPIOA->ODR=(GPIOA->ODR&~TFT_LED) |(x ? TFT_LED:0)
#define TFT_RST_SET(x) GPIOA->ODR=(GPIOA->ODR&~TFT_RST)|(x ? TFT_RST:0)
#define TFT_RD_SET(x) GPIOA->ODR=(GPIOA->ODR&~TFT_RD) |(x ? TFT_RD:0)
//PC0~7,作为数据线
#define DATAOUT(x) GPIOC->ODR=(GPIOC->ODR&0xffffff00)|(x&0xff);//数据输出
#define DATAIN GPIOC->IDR&0xff;//数据输入
//画笔颜色
u16 POINT_COLOR=RED;//默认红色
u16 BACK_COLOR=WHITE;//背景颜色.默认为白色
/*------------------------液晶说明------------------------------
液晶型号位置
大小:320*240
像素:65K色
VCC 3.3V
VCCIO 2.7~3.3V
数据线操作电压:3.3V
颜色排列:以一个十六位的数存放一个点的颜色 RGB:565 即:最高五位为红色
灰阶.中间六位为绿色灰阶.最低五位为蓝色灰阶.
例如:0XF800 纯红色
0X07E0 纯绿色
0X001F 纯蓝色
----------------------------------------------------------------*/
//写8位数据函数
//用宏定义,提高速度.
#define TFT_WR_DATA(data){\
TFT_RS_SET(1);\
TFT_CS_SET(0);\
DATAOUT(data);\
TFT_WR_SET(0);\
TFT_WR_SET(1);\
TFT_CS_SET(1);\
TFT_RS_SET(0);\
}
//写寄存器函数
void TFT_WR_REG(u8 data)
{
TFT_RS_SET(0);//写地址
TFT_CS_SET(0);
DATAOUT(data);
TFT_WR_SET(0);
TFT_WR_SET(1);
TFT_CS_SET(1);
TFT_RS_SET(1);
}
//写寄存器数据函数
//dbw:数据位数,1为16位,0为8位。
//index:寄存器编号
//val:值
//输入:dbw 数据位数,1为16位,0为8位。
void TFT_WR_CMD(u8 dbw,u8 index,u16 val)
{
TFT_WR_REG(index);
if(dbw)TFT_WR_DATA(val>>8);
TFT_WR_DATA(val&0xff);
}
//写16位数据函数
void TFT_WR_Data16(u16 val)
{
TFT_WR_DATA(val>>8);
TFT_WR_DATA(val&0xff);
}
//画点
//x:0~239
//y:0~319
//POINT_COLOR:此点的颜色
void TFT_DrawPoint(u8 x,u16 y)
{
TFT_WR_CMD(0,0x2,x);//设置到原点
TFT_WR_CMD(1,0x3,y);
//TFT_WR_CMD(0,0x04,0xEF); //结束列数(0~239)
//TFT_WR_CMD(1,0x05,0x013F);//结束行数(0~319)
TFT_WR_REG(0x0E);
TFT_WR_Data16(POINT_COLOR);
}
u16 Screen_Data[756];
//读取指定点的GRAM
unsigned int TFT_RD_GRAM(u8 x,u16 y)
{
u16 t;
TFT_WR_CMD(0,0x2,x);//设置到原点
TFT_WR_CMD(1,0x3,y);
TFT_WR_REG(0x0F);
GPIOC->CRL=0X88888888; //PC0-7 上拉输入
GPIOC->ODR|=0X00FF; //全部输出高
TFT_RS_SET(1);
TFT_CS_SET(0);
TFT_RD_SET(0);
TFT_RD_SET(1);
//丢弃第一个不确定的数
TFT_RD_SET(0);
TFT_RD_SET(1);
t=DATAIN;
t<<=8;
TFT_RD_SET(0);
TFT_RD_SET(1);
t+=DATAIN;
TFT_CS_SET(1);
TFT_RS_SET(0);
GPIOC->CRL=0X33333333; //PC0-7 输出
GPIOC->ODR|=0X00FF; //全部输出高
return t;
}
//从指定地址开始读取 42*18大小的方块
void READ_GRAM(u8 x,u16 y)
{
u8 t,i;
u16 temp;
for(t=0;t<18;t++)
{
for(i=0;i<42;i++)
{
temp=(u16)t*42+i;
Screen_Data[temp]=TFT_RD_GRAM(x+i,y+t);
}
}
}
//恢复指定地址的数据
void RECOVER_GRAM(u8 x,u16 y)
{
u8 t,i;
u16 temp;
for(t=0;t<18;t++)
{
for(i=0;i<42;i++)
{
temp=(u16)t*42+i;
POINT_COLOR=Screen_Data[temp];
TFT_DrawPoint(x+i,y+t);
}
}
}
//清屏函数
//全屏显示单色
void TFT_CLEAR(u16 color)
{
u32 n;
TFT_WR_CMD(0,0x2,0);//设置到原点
TFT_WR_CMD(1,0x3,0);
TFT_WR_CMD(0,0x04,239); //结束列数(0~239)
TFT_WR_CMD(1,0x05,319);//结束行数(0~319)
TFT_WR_REG(0x0E);
for(n=0;n<76800;n++)TFT_WR_Data16(color);//显示白色
SD_Init();//初始化SD卡,在意外拔出之后可以正常使用
}
//在指定区域内填充指定颜色
//区域大小:
// (xend-xsta)*(yend-ysta)
void TFT_Fill(u8 xsta,u16 ysta,u8 xend,u16 yend,u16 color)
{
u32 n;
TFT_WR_CMD(0,0x2,xsta);//设置到原点
TFT_WR_CMD(1,0x3,ysta);
TFT_WR_CMD(0,0x04,xend);//结束列数(0~239)
TFT_WR_CMD(1,0x05,yend);//结束行数(0~319)
TFT_WR_REG(0x0E);
n=(u32)(yend-ysta+1)*(xend-xsta+1);
while(n--)TFT_WR_Data16(color);//显示所填充的颜色.
//恢复初始状态
TFT_WR_CMD(0,0x2,0);//设置到原点
TFT_WR_CMD(1,0x3,0);
TFT_WR_CMD(0,0x04,239);//结束列数(0~239)
TFT_WR_CMD(1,0x05,319);//结束行数(0~319)
}
//画线
//x1,y1:起点坐标
//x2,y2:终点坐标
void TFT_DrawLine(u8 x1, u16 y1, u8 x2, u16 y2)
{
u16 x, y, t;
if((x1==x2)&&(y1==y2))TFT_DrawPoint(x1, y1);
else if(abs(y2-y1)>abs(x2-x1))//斜率大于1
{
if(y1>y2)
{
t=y1;
y1=y2;
y2=t;
t=x1;
x1=x2;
x2=t;
}
for(y=y1;y<y2;y++)//以y轴为基准
{
x=(u32)(y-y1)*(x2-x1)/(y2-y1)+x1;
TFT_DrawPoint(x, y);
}
}
else //斜率小于等于1
{
if(x1>x2)
{
t=y1;
y1=y2;
y2=t;
t=x1;
x1=x2;
x2=t;
}
for(x=x1;x<=x2;x++)//以x轴为基准
{
y =(u32)(x-x1)*(y2-y1)/(x2-x1)+y1;
TFT_DrawPoint(x,y);
}
}
}
//画矩形
void TFT_DrawRectangle(u8 x1, u16 y1, u8 x2, u16 y2)
{
TFT_DrawLine(x1,y1,x2,y1);
TFT_DrawLine(x1,y1,x1,y2);
TFT_DrawLine(x1,y2,x2,y2);
TFT_DrawLine(x2,y1,x2,y2);
}
//在指定位置画一个指定大小的圆
//(x,y):中心点
//r :半径
void draw_circle(u8 x0,u16 y0,u8 r)
{
int a,b;
int di;
a=0;
b=r;
di=3-2*r; //判断下个点位置的标志
while(a<=b)
{
TFT_DrawPoint(x0-b,y0-a); //3
TFT_DrawPoint(x0+b,y0-a); //0
TFT_DrawPoint(x0-a,y0+b); //1
TFT_DrawPoint(x0-b,y0-a); //7
TFT_DrawPoint(x0-a,y0-b); //2
TFT_DrawPoint(x0+b,y0+a); //4
TFT_DrawPoint(x0+a,y0-b); //5
TFT_DrawPoint(x0+a,y0+b); //6
TFT_DrawPoint(x0-b,y0+a);
a++;
/***使用Bresenham算法画圆**/
if(di<0)di +=4*a+6;
else
{
di+=10+4*(a-b);
b--;
}
TFT_DrawPoint(x0+a,y0+b);
}
}
//画一个触摸点
//用来校准用的
void drow_touch_point(u8 x,u16 y)
{
TFT_DrawLine(x-12,y,x+13,y);//横线
TFT_DrawLine(x,y-12,x,y+13);//竖线
TFT_DrawPoint(x+1,y+1);
TFT_DrawPoint(x-1,y+1);
TFT_DrawPoint(x+1,y-1);
TFT_DrawPoint(x-1,y-1);
draw_circle(x,y,6);//画中心圈
}
//在指定位置显示一个字符
//x:0~234
//y:0~308
//num:要显示的字符:" "--->"~"
//size:字体大小 12/16
//mode:叠加方式(1)还是非叠加方式(0)
void TFT_ShowChar(u8 x,u16 y,u8 num,u8 size,u8 mode)
{
#define MAX_CHAR_POSX 232
#define MAX_CHAR_POSY 304
u8 temp;
u8 pos,t;
if(x>MAX_CHAR_POSX||y>MAX_CHAR_POSY)return;
//设定一个字符所占的大小
//开辟空间
TFT_WR_CMD(0,0x00,0x04);
TFT_WR_CMD(0,0x2,x);//
TFT_WR_CMD(1,0x3,y);
TFT_WR_CMD(0,0x04,x+(size/2-1)); //结束列数(0~239)
TFT_WR_CMD(1,0x05,y+size-1);//结束行数(0~319)
TFT_WR_REG(0x0E);
num=num-' ';//得到偏移后的值
if(!mode) //非叠加方式
{
for(pos=0;pos<size;pos++)
{
if(size==12)temp=asc2_1206[num][pos];//调用1206字体
else temp=asc2_1608[num][pos]; //调用1608字体
for(t=0;t<size/2;t++)
{
if(temp&0x01)TFT_WR_Data16(POINT_COLOR);
else TFT_WR_Data16(BACK_COLOR);
temp>>=1;
}
}
}else//叠加方式
{
for(pos=0;pos<size;pos++)
{
if(size==12)temp=asc2_1206[num][pos];//调用1206字体
else temp=asc2_1608[num][pos]; //调用1608字体
for(t=0;t<size/2;t++)
{
if(temp&0x01)TFT_DrawPoint(x+t,y+pos);//画一个点
temp>>=1;
}
}
}
//恢复窗体大小
TFT_WR_CMD(0,0x04,239);//结束列数
TFT_WR_CMD(1,0x05,319);//结束行数
}
//在指定位置显示一个大字符
//30*60大小的
//num:0~9
//:/./C这三个字符
void TFT_ShowBigChar(u8 x,u16 y,u8 num)
{
u8 n,t;
u8 temp;
u8 t1,deadline;
TFT_WR_CMD(0,0x2,x);//设置到原点
TFT_WR_CMD(1,0x3,y);
TFT_WR_CMD(0,0x04,x+29);//结束列数(0~239)
TFT_WR_CMD(1,0x05,y+59); //结束行数(0~319)
if(num==':')t1=150;
else if(num=='.')t1=165;
else if(num=='C')t1=180;
else t1=15*num;
deadline=t1+15;
TFT_WR_REG(0x0E);
for(;t1<deadline;t1++)
{
for(n=0;n<16;n++)
{
temp=BIG_ASCII[t1][n];
for(t=0;t<8;t++)
{
if(temp&0x80) TFT_WR_Data16(POINT_COLOR);
else TFT_WR_Data16(BACK_COLOR);
temp<<=1;
if(((n%4)==3)&&t==5)break;
}
}
}
//恢复面板
TFT_WR_CMD(0,0x04,239);//结束列数(0~239)
TFT_WR_CMD(1,0x05,319); //结束行数(0~319)
}
//显示一个按钮,大小24*24
//0,>;1,<;
void TFT_ShowButton(u8 x,u16 y,u8 num)
{
u8 n,t;
u8 temp;
u8 t1,deadline;
TFT_WR_CMD(0,0x0,0x04);//扫描方式控制
TFT_WR_CMD(0,0x2,x);//设置到原点
TFT_WR_CMD(1,0x3,y);
TFT_WR_CMD(0,0x04,x+23);//结束列数(0~239)
TFT_WR_CMD(1,0x05,y+23); //结束行数(0~319)
t1=8*num;
deadline=t1+8;
TFT_WR_REG(0x0E);
for(;t1<deadline;t1++)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -