📄 touch.c
字号:
#include "touch.h"
//触摸屏初始化
//使用外部8M晶振,PLL到72M频率
//正点原子@SCUT
//2008/12/14
//V1.0
//SPI开始
void start_spi()
{
TCLK_SET(0);
TCS_SET(1);
TDIN_SET(1);
TCLK_SET(1);
TCS_SET(0);
}
//SPI写数据
//向7846写入1byte数据
void WriteByteADS(u8 num)
{
u8 count=0;
TCLK_SET(0);
for(count=0;count<8;count++)
{
if(num&0x80)TDIN_SET(1);
else TDIN_SET(0);
num<<=1;
TCLK_SET(0);//上升沿有效
TCLK_SET(1);
}
}
//SPI读数据
//从7846读取adc值
u16 ReadWordADS(void)
{
u8 count=0;
u16 Num=0;
for(count=0;count<12;count++)
{
Num<<=1;
TCLK_SET(1);//下降沿有效
TCLK_SET(0);
if(DOUT)Num++;
}
return(Num);
}
//读取一次X,Y值
//读到的X,Y坐标值必须都大于100
//成功返回1,不成功返回0
//读数限制在100~3800之间.
u8 read_once(void)
{
start_spi();//启动SPI
WriteByteADS(CMD_RDX);
//ADS7846的转换时间最长为6us
TCLK_SET(1);delay_us(3);
TCLK_SET(0);delay_us(3);
Pen_Point.X=4096-ReadWordADS();//读X坐标,并转换
WriteByteADS(CMD_RDY);
//ADS7846的转换时间最长为6us
TCLK_SET(1);delay_us(3);
TCLK_SET(0);delay_us(3);
Pen_Point.Y=4096-ReadWordADS();//读Y轴坐标
TCS_SET(1);
//限制触摸屏读数范围,个人根据实际情况定
if(Pen_Point.X<3950&&Pen_Point.X>200&&Pen_Point.Y<3950&&Pen_Point.Y>200)return 1;//读数成功
else return 0; //读数失败
}
//读取ADS7846
//连续读取10次数据,对十次数据排序,然后对
//中间三次取平均值,得到最终的X,Y值
u8 Read_Ads7846(void)
{
u8 t,t1,count=0;
u16 databuffer[2][10];//数据组
u16 temp=0;
do //循环读数10次
{
if(read_once())//读数成功
{
databuffer[0][count]=Pen_Point.X;
databuffer[1][count]=Pen_Point.Y;
count++;
}
}while(NPEN&&count<10);
if(count==10)//一定要读到10次数据,否则丢弃
{
do//将数据X升序排列
{
t1=0;
for(t=0;t<count-1;t++)
{
if(databuffer[0][t]>databuffer[0][t+1])//升序排列
{
temp=databuffer[0][t+1];
databuffer[0][t+1]=databuffer[0][t];
databuffer[0][t]=temp;
t1=1;
}
}
}while(t1);
do//将数据Y升序排列
{
t1=0;
for(t=0;t<count-1;t++)
{
if(databuffer[1][t]>databuffer[1][t+1])//升序排列
{
temp=databuffer[1][t+1];
databuffer[1][t+1]=databuffer[1][t];
databuffer[1][t]=temp;
t1=1;
}
}
}while(t1);
Pen_Point.X=(databuffer[0][3]+databuffer[0][4]+databuffer[0][5])/3;
Pen_Point.Y=(databuffer[1][3]+databuffer[1][4]+databuffer[1][5])/3;
//TFT_ShowString(100,140,"X read:");TFT_ShowNum(142,140,Pen_Point.X); //
//TFT_ShowString(100,152,"Y read:");TFT_ShowNum(142,152,Pen_Point.Y);
return 1;
}
return 0;//读数失败
}
//中断,检测到PEN脚的一个下降沿.
//置位Pen_Point.Key_Sta为按下状态
//中断线0线上的中断检测
void EXTI0_IRQHandler(void)
{
Pen_Point.Key_Sta=Key_Down;//按键按下
EXTI->PR=1<<0; //清除LINE0上的中断标志位
}
//按键处理程序
//type:按键响应类型
//0,单点,定点,不扩展.一定要按键松开才返回
//1,单点,滑动,不扩展.滚动条操作/连加操作
//2,扩展按键支持:
//即:MOVE_LEFT,MOVE_RIGHT,MOVE_UP,MOVE_DOWN使能
u8 Touch_Key_Pro(u8 type)
{
u16 tempx,tempy;//暂时保存X,Y坐标
u8 ml=0,mr=0,mu=0,md=0;//四个方向上移动次数
u8 first=1;
//按键还是按下的
//手动按触摸屏的时候,至少需要15ms才能退出这个循环
do
{
Pen_Point.Key_Sta=Key_Up;//按键状态变为松开
if(Read_Ads7846())//成功读数
{
if(first)
{
Pen_Point.X0=Pen_Point.X;Pen_Point.Y0=Pen_Point.Y;//得到初始按下的坐标
tempx=Pen_Point.X;tempy=Pen_Point.Y;
//printf("X0:%d Y0:%d\n",Pen_Point.X,Pen_Point.Y);
first=0; //标记清空
}else if(type==2) //扩展按键
{
if(tempx>Pen_Point.X)ml++;
else mr++;
if(tempy>Pen_Point.Y)mu++;
else md++;
//设定一个门限值,不能让一次移动大于这个值,如果一次大于这个值
//认为触摸屏误动作了.400的时候,反映比较慢
if(abs(tempx-Pen_Point.X)>700||abs(tempy-Pen_Point.Y)>700)//有抖动
{
ml=mr=mu=md=0;//全部清掉
tempx=Pen_Point.X=Pen_Point.X0;//坐标复位
tempy=Pen_Point.Y=Pen_Point.Y0;
break;//退出数据采集,结果为点采集
}
tempx=Pen_Point.X;tempy=Pen_Point.Y;//转移临时坐标
}else if(type==1)break;
//printf("X:%d Y:%d\n",Pen_Point.X,Pen_Point.Y);
}
delay_ms(10);//10ms消抖
}while(NPEN||Pen_Point.Key_Sta==Key_Down);//PEN=0或者按键状态为按下状态;
delay_ms(50);
Pen_Point.Key_Sta=Key_Up;//按键状态变为松开
//单次/不扩展 键值处理
if(abs(tempx-Pen_Point.X0)<=200&&abs(tempy-Pen_Point.Y0)<=200||type<2)//单次按键/不扩展按键功能
{
if(Pen_Point.xfac!=0)//已经校准过了
{
Pen_Point.X0=Pen_Point.xfac*Pen_Point.X0+Pen_Point.xoff;
Pen_Point.Y0=Pen_Point.yfac*Pen_Point.Y0+Pen_Point.yoff;
}
Pen_Point.X=Pen_Point.X0;Pen_Point.Y=Pen_Point.Y0;
return CLICK_POINT;//没有移动
}
//扩展键值处理
if(abs(tempx-Pen_Point.X0)<=500&&abs(tempy-Pen_Point.Y0)<=500)return 0;//滑动距离最少要大于500
else if(Pen_Point.xfac!=0)//已经校准过了
{
Pen_Point.X0=Pen_Point.xfac*Pen_Point.X0+Pen_Point.xoff;
Pen_Point.Y0=Pen_Point.yfac*Pen_Point.Y0+Pen_Point.yoff;
tempx=Pen_Point.xfac*tempx+Pen_Point.xoff;
tempy=Pen_Point.yfac*tempy+Pen_Point.yoff;
}
if(abs(ml-mr)>abs(mu-md))//数量 满足
{
if(abs(tempx-Pen_Point.X0)>abs(tempy-Pen_Point.Y0))//质量满足
{
if(tempx>Pen_Point.X0)return MOVE_RIGHT;
else return MOVE_LEFT;
}else //质量不满足
{
if(tempy>Pen_Point.Y0)return MOVE_DOWN;
else return MOVE_UP;
}
}else
{
if(abs(tempy-Pen_Point.Y0)>abs(tempx-Pen_Point.X0))//质量满足
{
if(tempy>Pen_Point.Y0)return MOVE_DOWN;
else return MOVE_UP;
}else //质量不满足
{
if(tempx>Pen_Point.X0)return MOVE_RIGHT;
else return MOVE_LEFT;
}
}
}
//判断触点是不是在指定区域之内
//(x1,y1):起始坐标
//(x2,y2):结束坐标
//返回值 :1,在该区域内.0,不在该区域内.
u8 Is_In_Area(u8 x1,u16 y1,u8 x2,u16 y2)
{
if(Pen_Point.X<=x2&&Pen_Point.X>=x1&&Pen_Point.Y<=y2&&Pen_Point.Y>=y1)return 1;
else return 0;
}
//把触摸屏得到的数据转换为数字(按钮值)
//M_Type:按钮模式;
//0,系统菜单
//1,文件浏览模式
//2,时间模式下,按键的获取,连按支持!
//3,音乐播放模式下
//4,功能选择模式下
//5,收音机模式下
//6,闹钟中断程序按键
//返回值:对应的按键值(1~n)
//返回0,则表示此次按键无效
u8 Touch_To_Num(u8 M_Type)
{
u8 xtemp;
u16 t,ytemp;
switch(M_Type)
{
case 0://系统菜单下
xtemp=Touch_Key_Pro(1);//不使用扩展按钮
if(!(xtemp&CLICK_POINT))return 0;//不是点触直接退出
ytemp=10;
for(t=0;t<9;t++)
{
xtemp=80*(t%3)+10;
if(t>5)ytemp=216;
else if(t>2)ytemp=113;
if(Is_In_Area(xtemp,ytemp,xtemp+59,ytemp+90))return t+1;//返回按键值
}
break;
case 1://1,文件浏览模式
xtemp=Touch_Key_Pro(2);//支持扩展
if(xtemp&CLICK_POINT) //点触摸 得到1~8的值
{
for(t=0;t<8;t++)
{
if(Is_In_Area(0,42+t*32,239,42+(t+1)*32))return t+1;
}
if(Is_In_Area(0,300,40,319))return 9;//选择按钮被按下
if(Is_In_Area(200,300,239,319))return 10;//返回按钮被按下
return 0;//按键无效
}
if(xtemp)return xtemp&0xf0;//滑动触摸了!!
break;
case 2://2,时间模式下,按键的获取,连按支持!
xtemp=Touch_Key_Pro(1);//不扩展
if(xtemp&CLICK_POINT) //点触摸 得到1~8的值
{
if(Is_In_Area(4,142,28,166))return 1;
else if(Is_In_Area(60,142,84,166))return 2;
else if(Is_In_Area(96,142,120,166))return 3;
else if(Is_In_Area(136,142,160,166))return 4;
else if(Is_In_Area(172,142,196,166))return 5;
else if(Is_In_Area(212,142,236,166))return 6;
else if(Is_In_Area(4,206,28,230))return 7;
else if(Is_In_Area(60,206,84,230))return 8;
else if(Is_In_Area(96,206,120,230))return 9;
else if(Is_In_Area(136,206,160,230))return 10;
else if(Is_In_Area(172,206,196,230))return 11;
else if(Is_In_Area(212,206,236,230))return 12;
else if(Is_In_Area(0,300,40,319))return 13;//选择按钮被按下
else if(Is_In_Area(200,300,239,319))return 14;//返回按钮被按下
return 0;//按键无效
}
break;
case 3://MP3界面下面的按钮值
xtemp=Touch_Key_Pro(1);//不扩展
if(xtemp&CLICK_POINT) //点触摸 得到1~8的值
{
if(Is_In_Area(214,72,240,96))return 1;//循环模式更改
else if(Is_In_Area(87,103,153,119))return 2; //supper bass
else if(Is_In_Area(8,223,56,247))return 3; //音效存/取
else if(Is_In_Area(64,223,112,247))return 4; //音量
else if(Is_In_Area(120,223,168,247))return 5;//其他
else if(Is_In_Area(178,224,204,276))return 6;//回车
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -