📄 touch.c
字号:
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;
}
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_WriteOneByte(40,temp&0xff);
FM24C16_WriteOneByte(41,(temp>>8)&0xff);
FM24C16_WriteOneByte(42,(temp>>16)&0xff);
FM24C16_WriteOneByte(43,(temp>>24)&0xff);
temp=Pen_Point.yfac*100000000;//保存y校正因素
FM24C16_WriteOneByte(44,temp&0xff);
FM24C16_WriteOneByte(45,(temp>>8)&0xff);
FM24C16_WriteOneByte(46,(temp>>16)&0xff);
FM24C16_WriteOneByte(47,(temp>>24)&0xff);
//保存x偏移量
FM24C16_WriteOneByte(48,Pen_Point.xoff&0xff);
FM24C16_WriteOneByte(49,(Pen_Point.xoff>>8)&0xff);
//保存y偏移量
FM24C16_WriteOneByte(50,Pen_Point.yoff&0xff);
FM24C16_WriteOneByte(51,(Pen_Point.yoff>>8)&0xff);
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_ReadOneByte(43);
tempfac=(tempfac<<8)+FM24C16_ReadOneByte(42);
tempfac=(tempfac<<8)+FM24C16_ReadOneByte(41);
tempfac=(tempfac<<8)+FM24C16_ReadOneByte(40);
Pen_Point.xfac=(float)tempfac/100000000;//得到x校准参数
tempfac=FM24C16_ReadOneByte(47);
tempfac=(tempfac<<8)+FM24C16_ReadOneByte(46);
tempfac=(tempfac<<8)+FM24C16_ReadOneByte(45);
tempfac=(tempfac<<8)+FM24C16_ReadOneByte(44);
Pen_Point.yfac=(float)tempfac/100000000;//得到y校准参数
//得到x偏移量
tempfac=FM24C16_ReadOneByte(49);
tempfac=(tempfac<<8)+FM24C16_ReadOneByte(48);
Pen_Point.xoff=tempfac;
//得到y偏移量
tempfac=FM24C16_ReadOneByte(51);
tempfac=(tempfac<<8)+FM24C16_ReadOneByte(50);
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);//清屏
TFT_ShowString(24,110,"Touch Screen Adjusting...");
delay_ms(1000);
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(1800);
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 + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -