Files
m3s_stm32/HW_Devices/touch.c
T
2021-08-09 17:24:28 +08:00

318 lines
5.8 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/*
* touch.c
*
* Created on: 2021年8月7日
* Author: wuwenfeng
*/
#include "touch.h"
#include "LCD.h"
#include "eeprom.h"
//默认为touchtype=0的数据.
#define CMD_RDX 0X90
#define CMD_RDY 0XD0
//SPI写数据
//向触摸屏IC写入1byte数据
//num:要写入的数据
void TP_Write_Byte(char num)
{
for(uint8_t count=0;count<8;count++)
{
if(num&0x80){TDIN(1);}
else {TDIN(0);}
num<<=1;
TCLK(0);
TCLK(1); //上升沿有效
}
}
//SPI读数据
//从触摸屏IC读取adc值
//CMD:指令
//返回值:读到的数据
uint16_t TP_Read_AD(char CMD)
{
uint16_t Num=0;
TCLK(0); //先拉低时钟
TDIN(0); //拉低数据线
TCS(0); //选中触摸屏IC
TP_Write_Byte(CMD);//发送命令字
HAL_GetTick(); //稍微延时,ad转换需要时间
HAL_GetTick();
HAL_GetTick();
HAL_GetTick();
HAL_GetTick();
HAL_GetTick();
TCLK(1); //给1个时钟,清除BUSY
TCLK(0);
for(uint8_t count=0;count<16;count++)//读出16位数据,只有高12位有效
{
Num<<=1;
TCLK(0); //下降沿有效
TCLK(1);;
if(TDOUT){Num++;}
}
Num>>=4; //只有高12位有效.
TCS(1); //释放片选
return(Num);
}
//读取一个坐标值(x或者y)
//连续读取READ_TIMES次数据,对这些数据升序排列,
//然后去掉最低和最高LOST_VAL个数,取平均值
//xy:指令(CMD_RDX/CMD_RDY
//返回值:读到的数据
#define READ_TIMES 5 //读取次数
#define LOST_VAL 1 //丢弃值
uint16_t TP_Read_XOY(uint8_t xy)
{
uint16_t i, j;
uint16_t buf[READ_TIMES];
uint16_t sum=0;
uint16_t temp;
for(i=0;i<READ_TIMES;i++)buf[i]=TP_Read_AD(xy);
for(i=0;i<READ_TIMES-1; i++)//排序
{
for(j=i+1;j<READ_TIMES;j++)
{
if(buf[i]>buf[j])//升序排列
{
temp=buf[i];
buf[i]=buf[j];
buf[j]=temp;
}
}
}
sum=0;
for(i=LOST_VAL;i<READ_TIMES-LOST_VAL;i++)sum+=buf[i];
temp=sum/(READ_TIMES-2*LOST_VAL);
return temp;
}
//读取x,y坐标
//x,y:读取到的坐标ADC值
void TP_Read_XY_ADC(int16_t *x,int16_t *y)
{
int16_t xtemp,ytemp;
xtemp=TP_Read_XOY(CMD_RDX);
ytemp=TP_Read_XOY(CMD_RDY);
*x=xtemp;
*y=ytemp;
}
//连续2次读取触摸屏IC,且这两次的偏差不能超过
//ERR_RANGE,满足条件,则认为读数正确,否则读数错误.
//该函数能大大提高准确度
//x,y:读取到的坐标值
//返回值:0,失败;1,成功。
#define ERR_RANGE 10 //误差范围
uint8_t TP_Read_XY2(int16_t *x,int16_t *y)
{
int16_t x1,y1;
int16_t x2,y2;
TP_Read_XY_ADC(&x1,&y1);
TP_Read_XY_ADC(&x2,&y2);
if(((x2<=x1&&x1<x2+ERR_RANGE)||(x1<=x2&&x2<x1+ERR_RANGE))//前后两次采样在+-50内
&&((y2<=y1&&y1<y2+ERR_RANGE)||(y1<=y2&&y2<y1+ERR_RANGE)))
{
*x=(x1+x2)/2;
*y=(y1+y2)/2;
return 1;
}else return 0;
}
touch_device t0;// t0 yyds~
touch_config tconfig;
//触摸更新服务,状态机写法,循环获取坐标
void TP_Server()
{
if(TPEN==0) //如果有触摸
{
TP_Read_XY2(&t0.adc_x,&t0.adc_y); //先读取ad值
t0.pix_x=(t0.adc_x/tconfig.x_acc)-tconfig.x_offset;//转换为像素坐标
t0.pix_y=(t0.adc_y/tconfig.y_acc)-tconfig.y_offset;
}
}
//校准用,画一个目标坐标
//r=坐标半径,显示特效用
void TP_DrwaTrage(int x,int y,int r)
{
Draw_Circle(x,y,r+1,GRAY);
Draw_Circle(x,y,r,RED);
LCD_DrawLine(x,y,x+10,y,RED);
LCD_DrawLine(x,y,x,y+10,RED);
LCD_DrawLine(x,y,x-10,y,RED);
LCD_DrawLine(x,y,x,y-10,RED);
}
//触摸屏校准
void TP_adjustment()
{
//判断是否需要校准,从eeprom获取数据
EEPROM_READ_BATY(16,(char *)&tconfig,sizeof(touch_config));
if(tconfig.begin==0xab&&tconfig.end==0xcd)
{
return;
}
char str[64];
uint16_t y_adc,x_adc,step=0,r=10;
uint16_t y1,y2,y3,y4,x1,x2,x3,x4;
int y5,x5,xd,xl,yd,yl;
float acc_x,acc_y;
int offset_x,offset_y;
uint32_t wait=HAL_GetTick()+50000,ms100=0;
LCD_Clear(GRAY);
LCD_ShowString(0,50,"Calibrate the touch screen",16,RED,RED);
//TP_DrwaTrage(30,30,10);
while(HAL_GetTick()<wait)
{
if(TPEN==0)
{
wait=HAL_GetTick()+50000;
TP_Read_XY2(&x_adc,&y_adc);
sprintf(str,"ADC_X:%04d",x_adc);
LCD_ShowString(100, 0, str, 16, RED, GRAY);
sprintf(str,"ADC_Y:%04d",y_adc);
LCD_ShowString(100, 16, str, 16, RED, GRAY);
if(HAL_GetTick()>ms100)
{
ms100=HAL_GetTick()+100;
if(r>0){r--;}
}
}
if(step==0)
{
TP_DrwaTrage(30,30,r);
if(r==0)
{
step+=1;
y1=y_adc;
x1=x_adc;
sprintf(str,"point_1 x:%d y:%d",x1,y1);
LCD_ShowString(0,66,str,16,RED,RED);
}
}
if(step==1)
{
if(TPEN==1)
{
step+=1;
r=10;
}
}
if(step==2)
{
TP_DrwaTrage(290,30,r);
if(r==0)
{
step+=1;
y2=y_adc;
x2=x_adc;
sprintf(str,"point_2 x:%d y:%d",x2,y2);
LCD_ShowString(0,66+16,str,16,RED,RED);
}
}
if(step==3)
{
if(TPEN==1)
{
step+=1;
r=10;
}
}
if(step==4)
{
TP_DrwaTrage(30,210,r);
if(r==0)
{
step+=1;
y3=y_adc;
x3=x_adc;
sprintf(str,"point_3 x:%d y:%d",x3,y3);
LCD_ShowString(0,66+16+16,str,16,RED,RED);
}
}
if(step==5)
{
if(TPEN==1)
{
step+=1;
r=10;
}
}
if(step==6)
{
TP_DrwaTrage(290,210,r);
if(r==0)
{
step+=1;
y4=y_adc;
x4=x_adc;
sprintf(str,"point_4 x:%d y:%d",x4,y4);
LCD_ShowString(0,66+16+16+16,str,16,RED,RED);
}
}
if(step==7)
{
if(TPEN==1)
{
step+=1;
r=10;
}
}
if(step==8)
{
xd=((x1+x3)/2);
xl=((x2+x4)/2);
yd=((y1+y2)/2);
yl=((y3+y4)/2);
x5=xl-xd;
y5=yl-yd;
if(x5<0||y5<0)
{
sprintf(str,"ERROR");
LCD_ShowString(0,66+16+16+16+16,str,16,RED, GRAY);
}else
{
acc_x=x5/260.0;
acc_y=y5/180.0;
offset_x=(((xd/acc_x)-30)+((xl/acc_x)-290))/2;
offset_y=(((yd/acc_y)-30)+((yl/acc_y)-210))/2;
tconfig.x_acc=acc_x;
tconfig.x_offset=offset_x;
tconfig.y_acc=acc_y;
tconfig.y_offset=offset_y;
tconfig.begin=0xab;
tconfig.end=0xcd;
sprintf(str,"x_acc=%f y_acc=%f",acc_x,acc_y);
LCD_ShowString(0,66+16+16+16+16,str,16,RED,RED);
sprintf(str,"x_offset=%d y_offset=%d",offset_x,offset_y);
LCD_ShowString(0,66+16+16+16+16+16,str,16,RED,RED);
}
EEPROM_WRITE_BATY(16,(char *)&tconfig,sizeof(touch_config));
HAL_Delay(1000);
return;
}
}
}