• STM32 CortexM4 主控板触摸屏保姆级别总结


    一、实物图

    二、触摸屏种类分类

       电阻式屏幕

    特点:定位准确且可以实现单点触摸;电阻式屏幕是一种传感器,它将矩形区域的触摸点的物理位置转换为代表X/Y轴的电压,现在很多的LCD屏幕都是采用了电阻式的触摸屏,这种屏幕可以用5、6、7、8线来产生偏置电压,同时可以读回触摸点的电压。

    电阻式触摸屏是一种传感器,基本上是薄膜加上玻璃的结构,薄膜和玻璃相邻的一面上均涂有ITO(纳米铟锡金属氧化物)涂层,ITO具有很好的导电性和透明性。当触摸操作时,薄膜下层的ITO会接触到玻璃上层的ITO,经由感应器传出相应的电信号,经过转换电路送到处理器,通过运算转化为屏幕上的X、Y值,而完成点选的动作,并呈现在屏幕上。

    其优缺点也很明显,缺点是他只能支持单点触摸,不能实现多点触发触摸功能;但是由于这个单点触摸的特点,使得它触摸的精度很高。


    1.  

    电感式触摸屏

    支持多点触摸,价格偏贵。工业应用最广泛,我们现在市面上的手机都是感应式的触摸屏,它的优缺点是跟电阻式的触摸屏相反,优点是可以实现多点感应,而缺点就是精度没那么高。

      

     红外线式

    特点是:价格十分低廉,但其外框易碎,容易产生光干扰,曲面情况下失真,所以一般情况下我们不会选择这样的触摸屏。这个一般用在特殊的工艺。

    表面声波式

    特点是:可以解决各种缺点,但是屏幕表面如果有水滴和尘土会使触摸屏变的迟钝。

    XPT2046采集触摸AD芯片

       触摸屏接口连接原理

     

    XPT2046特性

    工作电压范围为2.2V-5.25V,支持1.5V~5.25V的数字IO口,内建2.5V参考电压源;
    电源电压测量(0V-6V)内建结温测量功能触摸压力测量;
    采用SPI3线控制通信接口且有自动power-down功能;
    封装:QPN-16.TSSOP-16和VFBGA-48与TSC2046、AK4182A完全兼容

    XPT2046结构原理

     

     XPT2046引脚

    屏幕X/Y坐标的输入+/-端

     

     

     应用引脚

     

     使用到的引脚

    看原理图,我们知道,有红框圈起来的引脚要用我们进行配置:

     

    T_MISO  PB2 引脚

            XPT2046的串行数据输出端。STM32的数据输入端,数据在DCLK的下降沿                                   移出,当CS高电平时为高阻状态,配置为输入模式,空闲为高。

    T_PEN   PB1引脚

           笔中断输出,配置为输入模式,空闲模式为高电平;

    T_CS     PC13引脚

         片选信号。控制转换时序和使能串行输入输出寄存器,高电平时ADC掉电;

    T_MOSI   PF11引脚

         XPT2046的串行数据输入端,STM32的输出端,当CS为低电平时,数据在DCLK上升沿锁存进来;

    T_SCK   PB0引脚

          XPT2046外部时钟信号输入,STM32的时钟信号输出;

    小结

      STM32发数据的时候,片选拉低,DCLK拉高,把数据锁存在T_MOSI引脚传输出去;当STM32读数据的时候,片选拉低,DCLK拉低,读取T_MISO电平状态。

    XPT2046控制说明

    单端还是差分模式

    选择VBAT、 Temp和AUX时可以配置为单端模式,作为触摸屏应用时,可以配置为差分模式,这可有效消除由于驱动开关的寄生电阻及外部的干扰带来的测量误差,提高转换准确
    度。

     

    笔中断输出

    有人按下屏幕时,触摸屏下拉到地,也就是按下为低电平

     

    控制字节

    用于选择采集的是X还是Y轴的AD值,作用:控制字节由 DIN 输入的控制字如表 3 所示,它用来启动转换,寻址,设置 ADC 分辨率,配置和对 XPT2046 进行掉电控
    制。

    代码实例

     扫描触摸屏

    touch:存放读取到的x/y坐标值,返 回 值 : 0:有按下;1:无按下

    1. ********************************************************************************/
    2. unsigned char Xpt2046_ScanTouch(Touch_Typedef *touch)
    3. {
    4. Touch_Typedef ad;
    5. unsigned char ucRetVaule;
    6. if(T_PEN == 0)
    7. { //判断触摸屏有没有被按下
    8. if(T_PEN == 0)
    9. {
    10. Xpt2046_ReadXYAD(&ad);
    11. touch->xval = ad.xval * Kx + Bx;
    12. touch->yval = ad.yval * Ky + By;
    13. ucRetVaule = 0;
    14. }
    15. }
    16. else
    17. {
    18. touch->xval=0xffff;
    19. touch->yval=0xffff;
    20. ucRetVaule = 1;
    21. }
    22. return ucRetVaule;
    23. }

     

    读取X/Y轴AD值,并滤波处理

    1. void Xpt2046_ReadXYAD(Touch_Typedef *touch)
    2. {
    3. unsigned char i, j;
    4. unsigned short adx[5], ady[5];
    5. unsigned short temp;
    6. for(i=0; i<5; i++){ //先采集多次数据
    7. adx[i] = Xpt2046_ReadAD(0xd0);
    8. ady[i] = Xpt2046_ReadAD(0x90);
    9. }
    10. for(i=0; i<5; i++)
    11. { //先排序,找出最大和最小的值
    12. for(j=0; j<5-i-1; j++)
    13. {
    14. if(adx[j] > adx[j+1])
    15. {
    16. temp = adx[j];
    17. adx[j] = adx[j+1];
    18. adx[j+1] = temp;
    19. }
    20. if(ady[j] > ady[j+1])
    21. {
    22. temp = ady[j];
    23. ady[j] = ady[j+1];
    24. ady[j+1] = temp;
    25. }
    26. }
    27. }
    28. touch->xval = adx[2];
    29. touch->yval = ady[2];
    30. }

    读取轴AD值

    1. unsigned short Xpt2046_ReadAD(unsigned char cmd)
    2. {
    3. unsigned char vh, vl;
    4. T_CS = 0; //拉低片选,选中器件,开始通信
    5. Xpt2046_WriteByte(cmd); //发送测量命令
    6. Delay_Us(1); //等到芯片忙结束
    7. vh = Xpt2046_ReadByte();//读取数据的高位
    8. vl = Xpt2046_ReadByte();//读取数据的低位
    9. T_CS = 1; //拉低片选,取消选中,结束通信
    10. return ((vh<<8|vl)>>4); //返回结果,其中只有12位有效
    11. }

    触摸屏校准函数

    这个可以通用,需要的直接复制就好了

    1. void Xpt2046_TouchAdjust(void)
    2. {
    3. unsigned short lcd_pos[4][2] = {20, 20, 300, 20, 20, 460, 300, 460, };
    4. Touch_Typedef touch_pos[4]; //用来存放x,y的4个AD值
    5. unsigned char i, j;
    6. double len1 = 0.00f, len2 = 0.00f;
    7. Lcd_ShowString(30, 130, "touch adjust start", RED, WHITE, 16);
    8. while(1){
    9. for(i=0; i<4; i++){ //读取4个对应的触摸屏坐标
    10. for(j=0; j<30; j++){ //画一个十字架
    11. Lcd_DrawPoint(lcd_pos[i][0]-15+j, lcd_pos[i][1], RED);
    12. Lcd_DrawPoint(lcd_pos[i][0], lcd_pos[i][1]-15+j, RED);
    13. }
    14. printf("等待校验\r\n");
    15. while(T_PEN == 1); //等待按下触摸屏
    16. Delay_Ms(50); //延时50ms待数据稳定
    17. printf("按下触摸屏\r\n");
    18. Xpt2046_ReadXYAD(&touch_pos[i]);//获得触摸屏测量的x,y轴数值
    19. while(T_PEN == 0); //等待松开手
    20. Delay_Ms(200);
    21. for(j=0; j<30; j++){ //清掉十字架图标
    22. Lcd_DrawPoint(lcd_pos[i][0]-15+j, lcd_pos[i][1], WHITE);
    23. Lcd_DrawPoint(lcd_pos[i][0], lcd_pos[i][1]-15+j, WHITE);
    24. }
    25. }
    26. //校验坐标-计算点击的触摸点是否正确 如果不正确重新校准
    27. //水平两个点之间的距离比较
    28. len1 = (float)sqrt((touch_pos[1].xval-touch_pos[0].xval)*(touch_pos[1].xval-touch_pos[0].xval) \
    29. + (touch_pos[1].yval-touch_pos[0].yval)*(touch_pos[1].yval-touch_pos[0].yval));
    30. len2 = (float) sqrt((touch_pos[3].xval-touch_pos[2].xval)*(touch_pos[3].xval-touch_pos[2].xval) \
    31. + (touch_pos[3].yval-touch_pos[2].yval)*(touch_pos[3].yval-touch_pos[2].yval));
    32. if(((len1/len2)<0.95) || ((len1/len2)>1.05)){
    33. continue;
    34. }
    35. //垂直两个点之间的距离比较
    36. len1 = (float)sqrt((touch_pos[2].xval-touch_pos[0].xval)*(touch_pos[2].xval-touch_pos[0].xval) \
    37. + (touch_pos[2].yval-touch_pos[0].yval)*(touch_pos[2].yval-touch_pos[0].yval));
    38. len2 = (float)sqrt((touch_pos[3].xval-touch_pos[1].xval)*(touch_pos[3].xval-touch_pos[1].xval) \
    39. + (touch_pos[3].yval-touch_pos[1].yval)*(touch_pos[3].yval-touch_pos[1].yval));
    40. if(((len1/len2)<0.95) || ((len1/len2)>1.05)){
    41. continue; //点击的点不符合要求
    42. }
    43. //对角线两个点之间的距离比较
    44. len1 = (float)sqrt((touch_pos[3].xval-touch_pos[0].xval)*(touch_pos[3].xval-touch_pos[0].xval) \
    45. + (touch_pos[3].yval-touch_pos[0].yval)*(touch_pos[3].yval-touch_pos[0].yval));
    46. len2 = (float)sqrt((touch_pos[2].xval-touch_pos[1].xval)*(touch_pos[2].xval-touch_pos[1].xval) \
    47. + (touch_pos[2].yval-touch_pos[1].yval)*(touch_pos[2].yval-touch_pos[1].yval));
    48. if(((len1/len2)<0.95) || ((len1/len2)>1.05)){
    49. continue;
    50. }
    51. //计算校准参数 Kx (Ky)--斜率;Bx(By) --偏移量
    52. //计算x映射 Xlcd = Kx * touch_x + Bx
    53. Kx = (float)(lcd_pos[1][0]-lcd_pos[0][0]) / (touch_pos[1].xval-touch_pos[0].xval);
    54. Bx = lcd_pos[0][0] - Kx*touch_pos[0].xval;
    55. //计算y映射 Ylcd = Ky*touch_y + By
    56. Ky = (float)(lcd_pos[2][1]-lcd_pos[0][1]) / (touch_pos[2].yval-touch_pos[0].yval);
    57. By = lcd_pos[0][1] - Ky*touch_pos[0].yval;
    58. Lcd_Fill(0, 0, 320, 480, WHITE);
    59. Lcd_ShowString(30, 130, "touch adjust OK", RED, WHITE, 16);
    60. printf("校准参数 Ky=%f;Kx=%f;By=%d;Bx=%d;\r\n",Ky, Kx, By, Bx);
    61. Delay_Ms(1000);
    62. Delay_Ms(1000);
    63. Lcd_Fill(0, 0, 320, 480, WHITE);
    64. break;
    65. }
    66. }

  • 相关阅读:
    从文字到视频:借助ChatGPT与剪映轻松生成高质量视频(文末送书)
    攻克数据结构和算法——第五天:查找
    (附源码)计算机毕业设计SSM基于的砂石矿山管理系统
    睿趣科技:抖音店铺名字怎么更吸引人
    基于Python+Selenium的web自动化测试框架详解
    [linux] SFTP文件传输基本命令 --- xshell 直接上传文件
    【学习笔记】Half-GCD
    SpringSecurity+ Oauth2.0+JWT 0-1
    详解TCP/IP协议第五篇:详细介绍网络传输中的地址
    Java守护线程
  • 原文地址:https://blog.csdn.net/Lushengshi/article/details/126291716