touch.c
来自「多功能MP3代码」· C语言 代码 · 共 618 行 · 第 1/2 页
C
618 行
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;//回车
else if(Is_In_Area(214,224,238,248))return 7;//增加
else if(Is_In_Area(214,252,238,276))return 8; //减少
else if(Is_In_Area(28,288,52,312))return 9; //后一取
else if(Is_In_Area(108,288,132,312))return 10;//播放
else if(Is_In_Area(188,288,212,312))return 11;//上一曲
else if(Is_In_Area(30,83,210,98))return 12; //进度条按下,y方向扩大了一点范围
//else if(Is_In_Area(0,300,40,319))return 13;//选择按钮被按下
//else if(Is_In_Area(200,300,239,319))return 14;//返回按钮被按下
return 0;//按键无效
}
case 4://4,功能选择模式下
xtemp=Touch_Key_Pro(1);//不支持扩展
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;//按键无效
}
break;
case 5://5,收音机模式下
xtemp=Touch_Key_Pro(1);//不支持扩展
if(xtemp&CLICK_POINT) //点触摸 得到1~8的值
{
if(Is_In_Area(37,215,61,239))return 1;//循环模式更改
else if(Is_In_Area(93,215,117,239))return 2;//循环模式更改
else if(Is_In_Area(152,218,203,236))return 3; //音效存/取
else if(Is_In_Area(28,261,52,285))return 4; //后一取
else if(Is_In_Area(108,261,132,285))return 5;//播放
else if(Is_In_Area(188,261,212,285))return 6;//上一曲
else if(Is_In_Area(0,300,40,319))return 7;//选项按钮被按下
else if(Is_In_Area(200,300,239,319))return 8;//返回按钮被按下
return 0;//按键无效
}
break;
case 6://6,闹钟中断程序按键
xtemp=Touch_Key_Pro(1);//不支持扩展
if(xtemp&CLICK_POINT) //点触摸 得到1~8的值
{
if(Is_In_Area(111,151,153,169))return 1;//循环模式更改
return 0;//按键无效
}
break;
case 7://JPEG/BMP/TXT浏览按键模式
xtemp=Touch_Key_Pro(1);//不支持扩展
if(xtemp&CLICK_POINT) //点触摸 得到1~8的值
{
if(Is_In_Area(0,0,239,60))return KEY_PREV; //向上
else if(Is_In_Area(0,60,239,260))return KEY_FUNC; //不定
else if(Is_In_Area(0,260,239,319))return KEY_NEXT;//向下翻
return 0;//按键无效
}
break;
}
return 0;
}
//得到键盘返回值
//在闹钟修改时间的时候用到
//返回:0~11
//返回11:按键无效
//返回10:退格按键
u8 Get_KeyBoard_Val(void)
{
u8 t;
for(t=0;t<10;t++) //加载外框
{
if(Is_In_Area(14+18*t,269,30+18*t,285))return t;//16*16方框
}
if(Is_In_Area(194,269,226,285))return 10;//32*16方框
return 11;
}
//保存校准参数
//保存区域:FM24C16的 40~52这段地址区间,总共12个字节
void save_adjdata(void)
{
u32 temp;
//保存校正结果!
temp=Pen_Point.xfac*100000000;//保存x校正因素
FM24C16_WriteLenByte(40,temp,4);
temp=Pen_Point.yfac*100000000;//保存y校正因素
FM24C16_WriteLenByte(44,temp,4);
//保存x偏移量
FM24C16_WriteLenByte(48,Pen_Point.xoff,2);
//保存y偏移量
FM24C16_WriteLenByte(50,Pen_Point.yoff,2);
temp=FM24C16_ReadOneByte(52);
temp|=0x01;//标记校准过了
FM24C16_WriteOneByte(52,temp);
}
//得到保存在EEPROM里面的校准值
//返回值:1,成功获取数据
// 0,获取失败,要重新校准
u8 get_adjdata(void)
{
u32 tempfac;
tempfac=FM24C16_ReadOneByte(52);
if(tempfac&0x01)//触摸屏已经校准过了
{
tempfac=FM24C16_ReadLenByte(40,4);
Pen_Point.xfac=(float)tempfac/100000000;//得到x校准参数
tempfac=FM24C16_ReadLenByte(44,4);
Pen_Point.yfac=(float)tempfac/100000000;//得到y校准参数
//得到x偏移量
tempfac=FM24C16_ReadLenByte(48,2);
Pen_Point.xoff=tempfac;
//得到y偏移量
tempfac=FM24C16_ReadLenByte(50,2);
Pen_Point.yoff=tempfac;
return 1;
}
return 0;
}
//触摸屏校准代码
//得到四个校准参数
void touch_adjust(void)
{
u16 pos_temp[4][2];//坐标缓存值
u8 cnt=0;
u16 d1,d2;
u32 tem1,tem2;
float fac;
cnt=0;
POINT_COLOR=BLUE;
BACK_COLOR =WHITE;
TFT_CLEAR(WHITE);//清屏
POINT_COLOR=RED;//红色
TFT_CLEAR(WHITE);//清屏
drow_touch_point(20,20);//画点1
Pen_Point.Key_Sta=Key_Up;//消除触发信号
Pen_Point.xfac=0;//xfac用来标记是否校准过,所以校准之前必须清掉!以免错误
while(1)
{
if(Pen_Point.Key_Sta==Key_Down)//按键按下了
{
if(Touch_Key_Pro(0)&CLICK_POINT)//得到单次按键值
{
pos_temp[cnt][0]=Pen_Point.X;
pos_temp[cnt][1]=Pen_Point.Y;
cnt++;
}
switch(cnt)
{
case 1:
TFT_CLEAR(WHITE);//清屏
drow_touch_point(220,20);//画点2
break;
case 2:
TFT_CLEAR(WHITE);//清屏
drow_touch_point(20,300);//画点3
break;
case 3:
TFT_CLEAR(WHITE);//清屏
drow_touch_point(220,300);//画点4
break;
case 4: //全部四个点已经得到
//对边相等
tem1=abs(pos_temp[0][0]-pos_temp[1][0]);//x1-x2
tem2=abs(pos_temp[0][1]-pos_temp[1][1]);//y1-y2
tem1*=tem1;
tem2*=tem2;
d1=sqrt(tem1+tem2);//得到1,2的距离
tem1=abs(pos_temp[2][0]-pos_temp[3][0]);//x3-x4
tem2=abs(pos_temp[2][1]-pos_temp[3][1]);//y3-y4
tem1*=tem1;
tem2*=tem2;
d2=sqrt(tem1+tem2);//得到3,4的距离
fac=(float)d1/d2;
if(fac<0.95||fac>1.05)//不合格
{
cnt=0;
TFT_CLEAR(WHITE);//清屏
drow_touch_point(20,20);
continue;
}
tem1=abs(pos_temp[0][0]-pos_temp[2][0]);//x1-x3
tem2=abs(pos_temp[0][1]-pos_temp[2][1]);//y1-y3
tem1*=tem1;
tem2*=tem2;
d1=sqrt(tem1+tem2);//得到1,3的距离
tem1=abs(pos_temp[1][0]-pos_temp[3][0]);//x2-x4
tem2=abs(pos_temp[1][1]-pos_temp[3][1]);//y2-y4
tem1*=tem1;
tem2*=tem2;
d2=sqrt(tem1+tem2);//得到2,4的距离
fac=(float)d1/d2;
if(fac<0.95||fac>1.05)//不合格
{
cnt=0;
TFT_CLEAR(WHITE);//清屏
drow_touch_point(20,20);
continue;
}//正确了
//对角线相等
tem1=abs(pos_temp[1][0]-pos_temp[2][0]);//x1-x3
tem2=abs(pos_temp[1][1]-pos_temp[2][1]);//y1-y3
tem1*=tem1;
tem2*=tem2;
d1=sqrt(tem1+tem2);//得到1,4的距离
tem1=abs(pos_temp[0][0]-pos_temp[3][0]);//x2-x4
tem2=abs(pos_temp[0][1]-pos_temp[3][1]);//y2-y4
tem1*=tem1;
tem2*=tem2;
d2=sqrt(tem1+tem2);//得到2,3的距离
fac=(float)d1/d2;
if(fac<0.95||fac>1.05)//不合格
{
cnt=0;
TFT_CLEAR(WHITE);//清屏
drow_touch_point(20,20);
continue;
}//正确了
//计算结果
Pen_Point.xfac=(float)200/(pos_temp[1][0]-pos_temp[0][0]);//得到xfac
Pen_Point.xoff=(240-Pen_Point.xfac*(pos_temp[1][0]+pos_temp[0][0]))/2;//得到xoff
Pen_Point.yfac=(float)280/(pos_temp[2][1]-pos_temp[0][1]);//得到yfac
Pen_Point.yoff=(320-Pen_Point.yfac*(pos_temp[2][1]+pos_temp[0][1]))/2;//得到yoff
POINT_COLOR=BLUE;
TFT_CLEAR(WHITE);//清屏
TFT_ShowString(35,110,"Touch Screen Adjust OK!");//校正完成
delay_ms(1000);
TFT_CLEAR(WHITE);//清屏
save_adjdata();
return;//校正完成
}
}
}
}
//中断优先级管理/开启
void NVIC_TOUCHConfiguration(void)
{
NVIC_InitTypeDef NVIC_InitStructure;
//存储器映射,不用理
#ifdef VECT_TAB_RAM
NVIC_SetVectorTable(NVIC_VectTab_RAM, 0x0);
#else
NVIC_SetVectorTable(NVIC_VectTab_FLASH, 0x0);
#endif
//第0组,没有抢断优先级
//第4组,没有响应优先级
//第2组,有4个抢断,4个响应
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//优先级分到第2组 总共5组
NVIC_InitStructure.NVIC_IRQChannel = EXTI0_IRQChannel; //使用外部中断0
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;//阶级2,可以被1抢断.
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; //阶层0
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
//RTC中断配置
NVIC_InitStructure.NVIC_IRQChannel = RTC_IRQChannel;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;//阶层1
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; //阶层0,响应优先级较低
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
}
//外部中断初始化函数
void touch_init(void)
{
//注意,时钟使能之后,对GPIO的操作才有效
//所以上拉之前,必须使能时钟.才能实现真正的上拉输出
RCC->APB2ENR|=1<<2; //PA时钟使能
RCC->APB2ENR|=1<<3; //PB时钟使能
RCC->APB2ENR|=1<<0; //开启辅助时钟
AFIO->MAPR=0X04000000; //关闭JTAG
GPIOA->CRL&=0XFFFFF000;//PA.2输出 PA.0/1输入
GPIOA->CRL|=0X00000388;//3推挽输出 0/1上拉输入
GPIOA->ODR|=0X0007; //012 全部上拉
GPIOB->CRL&=0XFFF00FFF;
GPIOB->CRL|=0X00033000;//PB.3/4输出
GPIOB->ODR|=1<<4; //PB.4上拉
GPIOB->ODR|=1<<3; //PB.3上拉
Read_Ads7846(); //第一次读取初始化
NVIC_TOUCHConfiguration();
RCC->APB2ENR|=0x01; //使能io复用时钟
AFIO->EXTICR[0]|=0X00; //EXTI8映射到PA.0
EXTI->IMR|=1<<0; //开启line0上的中断
EXTI->EMR|=1<<0; //不屏蔽line0上的事件
EXTI->FTSR|=1<<0; //line0上事件下降沿触发
if(get_adjdata())return;//已经校准
else //未校准?
{
TFT_CLEAR(WHITE);//清屏
touch_adjust(); //屏幕校准,带自动保存
}
}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?