|
就是这种屏,商家给的例程在arduino是可以使用触摸功能,但其他例程只能显示。如何使用触摸功能呢
一、显示
屏幕后已把的引脚标注好了,使用ILI9341驱动芯片,8080-I 8位总线接口。具体如何驱动不细说,参考商家例程
二、电阻触摸屏原理
1、此屏幕并没有使用触摸芯片,只是使用最原始的连接方式。由表面硬涂层、两个ITO 层、间隔点以及玻璃底层构成。两个ITO 层是触摸屏的关键结构,它们是涂有铟锡金属氧化物的导电层。两个ITO 层之间使用间隔点使两层分开,当触摸屏表面受到压力时,表面弯曲使得上层ITO 与下层ITO 接触,在触点处连通电路。两个ITO 涂层的两端分别引出X-、X+、Y-、Y+四个电极(见图),这是电阻屏最常见的四线结构。
2、当触摸屏被按下时,两个ITO 层相互接触,从触点处把ITO 层分为两个电阻,且由于ITO 层均匀导电,两个电阻的大小与触点离两电极的距离成比例关系,利用这个特性可检测坐标,这也正是电阻触摸屏名称的由来。
3、检测方法
计算X坐标时,在X+电极施加驱动电压Vref,X-极接地,所以X+与X-处形成了匀强电场,而触点处的电压通过Y+电极采集得到,由于ITO 层均匀导电,触点电压与Vref之比等于触点X 坐标与屏宽度(Width,象数值)之比。
X = Vy+ / Vref * Width
计算Y 坐标时,在Y+电极施加驱动电压Vref,Y-极接地,所以Y+与Y-处形成了匀强电场,而触点处的电压通过X+电极采集得到,由于ITO 层均匀导电,触点电压与Vref之比等于触点Y 坐标与屏高度(Height,象数值)之比。
Y = Vx+ / Vref * Height
三、寻找引脚
根据触摸屏原理
1、因为要测量电压,其中X+与Y+必须使用模拟引脚(J3中的其中两个)
2、这两个引脚与想对应的引脚之间必定存在一定电阻,对应引脚为X-与Y-
我的屏经测量LCD_CS/LCD_D1、LCD_RS/LCD_D0之间约有几百欧电阻值。锁定这两对引脚,至于与X/Y轴如何对应,驱动编写后测试一下就可以知道。
四、触摸驱动
因为显示与触摸同时使用4个引脚,因此要进行功能切换
1、设置X轴采样,把Y+与Y-设置为模拟输入,并设置Y+为ADC采集。X+高电平,X-低电平
void Touch_Y_Setup(void)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
GPIO_InitStruct.Pin = ADC_YP_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
GPIO_InitStruct.Pull = GPIO_NOPULL;
HAL_GPIO_Init(ADC_YP_GPIO_Port, &GPIO_InitStruct);
GPIO_InitStruct.Pin = ADC_YM_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
GPIO_InitStruct.Pull = GPIO_NOPULL;
HAL_GPIO_Init(ADC_YM_GPIO_Port, &GPIO_InitStruct);
ADC_ChannelConfTypeDef sConfig = {0};
sConfig.Channel = ADC_CHANNEL_8;
//sConfig.Rank = ADC_RANK_CHANNEL_NUMBER;
sConfig.Rank = 1;
sConfig.SamplingTime = ADC_SAMPLETIME_41CYCLES_5;
if (HAL_ADC_ChangeChannel(&hadc, &sConfig) != HAL_OK)
{
Error_Handler();
}
HAL_GPIO_WritePin(ADC_XP_GPIO_Port, ADC_XP_Pin, GPIO_PIN_SET);
HAL_GPIO_WritePin(ADC_XM_GPIO_Port, ADC_XM_Pin, GPIO_PIN_RESET);
}
2、采集数据,连续采集两次,如果两次差异大认为没有触摸动作(X+引脚悬空),如果差异不大(我设置AD值为20以内),认为有效,取两次平均值输出。
uint16_t Get_Value(void)
{
uint16_t Value[2];
uint8_t i;
uint16_t Differ;
for (i=0;i<2;i++)
{
HAL_ADC_Start(&hadc); // 启动ADC转换
HAL_ADC_PollForConversion(&hadc, 10); // 等待转换完成,时间为50ms
Value = HAL_ADC_GetValue(&hadc);
}
HAL_ADC_Stop(&hadc);
Differ = Value[0]>Value[1] ? Value[0]-Value[1] : Value[1]-Value[0];
if ((Differ > ADC_DIFFER) || (Value[0] == 0) || (Value[1] ==0))
return 0xFFFF;
else
return Value[0]+Value[1] >> 1; // 取平均值
}
3、GPIO恢复显示设置
void Touch_Y_MspDeInit(void)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
HAL_GPIO_WritePin(ADC_YP_GPIO_Port, ADC_YP_Pin, GPIO_PIN_SET);
HAL_GPIO_WritePin(ADC_YM_GPIO_Port, ADC_YM_Pin, GPIO_PIN_RESET);
GPIO_InitStruct.Pin = ADC_YP_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
HAL_GPIO_Init(ADC_YP_GPIO_Port, &GPIO_InitStruct);
GPIO_InitStruct.Pin = ADC_YM_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
HAL_GPIO_Init(ADC_YM_GPIO_Port, &GPIO_InitStruct);
}
4、触摸屏校准,获取直线公式
void TouchScr_Calibration(void)
{
uint16_t Ad_X1,Ad_X2,Ad_Y1,Ad_Y2;
_adc Calib_Datas[5];
Calib_Datas[0] = Get_Point_Data(CROSS_CENTRE,CROSS_CENTRE);
Calib_Datas[1] = Get_Point_Data(CROSS_CENTRE,LCD_H - CROSS_CENTRE);
Calib_Datas[3] = Get_Point_Data(LCD_W - CROSS_CENTRE,LCD_H - CROSS_CENTRE);
Calib_Datas[2] = Get_Point_Data(LCD_W - CROSS_CENTRE,CROSS_CENTRE);
Calib_Datas[4] = Get_Point_Data(LCD_W>>1,LCD_H>>1);
Ad_X1 = Calib_Datas[0].x+Calib_Datas[1].x>>1;
Ad_X2 = Calib_Datas[2].x+Calib_Datas[3].x>>1;
Ad_Y1 = Calib_Datas[0].y+Calib_Datas[2].y>>1;
Ad_Y2 = Calib_Datas[1].y+Calib_Datas[3].y>>1;
Delta_X = (Ad_X2-Ad_X1)/(LCD_W-2*CROSS_CENTRE); // 计算X方向每点的AD值
Delta_Y = (Ad_Y2-Ad_Y1)/(LCD_H-2*CROSS_CENTRE); // 计算y方向每点的AD值
X0 = Ad_X1 - Delta_X * CROSS_CENTRE; // X方向0点处AD值
Y0 = Ad_Y1 - Delta_Y * CROSS_CENTRE; // Y方向0点处AD值
}
5、AD值反算坐标点
_position Cal_Pos(_adc Value)
{
_position Pos;
Pos.x = (uint16_t)((Value.x - X0) / Delta_X); // 反算X方向AD值对应的点位
Pos.y = (uint16_t)((Value.y - Y0) / Delta_Y); // 反算Y方向AD值对应的点位
return Pos;
}
五、效果
1、触摸屏校准
2、校准时获取的AD值,基本呈线性关系,中心点值可以忽略
3、简单手写效果,采样间隔有点大,所有断续情况稍严重。
|
本帖子中包含更多资源
您需要 登录 才可以下载或查看,没有账号?立即注册
x
|