引脚功能描述

控制字的控制位命令

控制字节各位描述

单端模式输入配置

差分模式输入配置

时序

前8个时钟用来通过DIN引脚输入控制字节,接着的12个时钟周期将完成真正的模数转换,剩下的3个多时钟周期将用来完成被转换器忽略的最后字节(DOUT置低)

举例





  1. #define TOUCH_READ_TIMES 40 //读取次数
  2. #define TOUCH_ERR_RANGE 20 //误差范围
  3. #define TOUCH_X_CMD 0xD0 //读取X轴
  4. #define TOUCH_Y_CMD 0x90 //读取Y轴
  5. #define TOUCH_Continue_Read 0xFF
  6. #define TOUCH_X_MAX 4000 //X最大值
  7. #define TOUCH_X_MIN 100 //X最小值
  8. #define TOUCH_Y_MAX 4000 //Y最大值
  9. #define TOUCH_Y_MIN 100 //X最小值
  10. #define LCD_CALx_MIN (10) //校准点最小值X
  11. #define LCD_CALx_MAX (tftlcd_data.width - LCD_CALx_MIN) //校准点最大值X
  12. #define LCD_CALy_MIN (10) //校准点最小值Y
  13. #define LCD_CALy_MAX (tftlcd_data.height - LCD_CALy_MIN) //校准点最大值Y
  14. #define LCD_CAL_X (LCD_CALx_MAX - LCD_CALx_MIN) //方框的宽度
  15. #define LCD_CAL_Y (LCD_CALy_MAX - LCD_CALy_MIN) //方框的高度
  16. #define TOUCH_CAL_OK 'Y' //校准OK标志
  17. #define TOUCH_CAL_ADDR 200 //校准参数在at24c02的保存地址
  18. typedef struct
  19. {
  20. u8 flag;
  21. short xoffset;
  22. short yoffset;
  23. float xFactor;
  24. float yFactor;
  25. } calibrate_t;
  26. calibrate_t calibrate = {0};
  27. u16 touchX;
  28. u16 touchY;
  29. void TOUCH_init()
  30. {
  31. GPIO_InitTypeDef gpioa =
  32. {
  33. GPIO_Pin_5 | GPIO_Pin_6 | GPIO_Pin_7,
  34. GPIO_Speed_50MHz,
  35. GPIO_Mode_AF_PP
  36. };
  37. GPIO_InitTypeDef gpiod6 =
  38. {
  39. GPIO_Pin_6,
  40. GPIO_Speed_50MHz,
  41. GPIO_Mode_Out_PP
  42. };
  43. GPIO_InitTypeDef gpiod7 =
  44. {
  45. GPIO_Pin_7,
  46. GPIO_Speed_50MHz,
  47. GPIO_Mode_IPU
  48. };
  49. SPI_InitTypeDef spi =
  50. {
  51. SPI_Direction_2Lines_FullDuplex,
  52. SPI_Mode_Master, //0x0104
  53. SPI_DataSize_8b,
  54. SPI_CPOL_High,
  55. SPI_CPHA_2Edge,
  56. SPI_NSS_Soft,
  57. SPI_BaudRatePrescaler_256,
  58. SPI_FirstBit_MSB,
  59. 7
  60. };
  61. RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI1 | RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOD, ENABLE);
  62. GPIO_Init(GPIOA, &gpioa);
  63. GPIO_Init(GPIOD, &gpiod6);
  64. GPIO_Init(GPIOD, &gpiod7);
  65. SPI_Init(SPI1, &spi); //初始化SPI
  66. SPI_Cmd(SPI1, ENABLE); //使能SPI
  67. }
  68. u16 TOUCH_read(u16 cmd)
  69. {
  70. u8 i = 0, j = 0;
  71. u16 tmp;
  72. u16 value[TOUCH_READ_TIMES] = {0};
  73. u32 total_value = 0;
  74. SPI1_SetSpeed(SPI_BaudRatePrescaler_32); //设置SPI速度
  75. for(i = 0; i < TOUCH_READ_TIMES; i++) //读取次数
  76. {
  77. TOUCH_CS = 0;
  78. SPI1_read_write(cmd);
  79. value[i] = SPI1_read_write(TOUCH_Continue_Read) << 8; //详见时序
  80. value[i] |= SPI1_read_write(TOUCH_Continue_Read);
  81. value[i] >>= 3;
  82. TOUCH_CS = 1;
  83. }
  84. for (i = 0; i < TOUCH_READ_TIMES; i++) //排序
  85. {
  86. for (j = i + 1; j < TOUCH_READ_TIMES; j++)
  87. {
  88. if (value[i] < value[j])
  89. {
  90. tmp = value[i];
  91. value[i] = value[j];
  92. value[j] = tmp;
  93. }
  94. }
  95. }
  96. for (i = 1; i < TOUCH_READ_TIMES - 1; i++) //去掉一个最大值,一个最小值
  97. {
  98. total_value += value[i];
  99. }
  100. total_value /= (TOUCH_READ_TIMES - 2); //求平均值
  101. return total_value;
  102. }
  103. u8 TOUCH_readXY(u16 *x, u16 *y)
  104. {
  105. u16 valueX1, valueY1, valueX2, valueY2;
  106. valueX1 = TOUCH_read(TOUCH_X_CMD); //读取触摸值
  107. valueY1 = TOUCH_read(TOUCH_Y_CMD);
  108. valueX2 = TOUCH_read(TOUCH_X_CMD);
  109. valueY2 = TOUCH_read(TOUCH_Y_CMD);
  110. *x = valueX1 > valueX2 ? (valueX1 - valueX2) : (valueX2 - valueX1);
  111. *y = valueY1 > valueY2 ? (valueY1 - valueY2) : (valueY2 - valueY1);
  112. if((*x > TOUCH_ERR_RANGE) || (*y > TOUCH_ERR_RANGE)) //判断容错范围
  113. {
  114. return 0xFF;
  115. }
  116. *x = (valueX1 + valueX2) / 2;
  117. *y = (valueY1 + valueY2) / 2;
  118. if((*x < TOUCH_X_MIN || *x > TOUCH_X_MAX) || //判断边界范围
  119. (*y < TOUCH_Y_MIN || *y > TOUCH_Y_MAX))
  120. {
  121. return 0xFF;
  122. }
  123. return 0;
  124. }
  125. void TOUCH_start_calibrate(u16 x, u16 y, u16 *valueX,u16 *valueY) //开始校准
  126. {
  127. u8 i = 0;
  128. LCD_Clear(BACK_COLOR); //清屏
  129. LCD_DrowSign(x, y, BACK_COLOR); //画十字
  130. while(1)
  131. {
  132. if(TOUCH_readXY(valueX, valueY) != 0xFF)
  133. {
  134. i++;
  135. if(i > 10)
  136. {
  137. LCD_DrowSign(x, y, BACK_COLOR);
  138. break;
  139. }
  140. }
  141. }
  142. }
  143. void TOUCH_calibrate()
  144. {
  145. u16 px[2], py[2], valueX[4], valueY[4];
  146. float xFactor = 0, yFactor = 0;
  147. TOUCH_start_calibrate(LCD_CALx_MIN, LCD_CALy_MIN, &valueX[0], &valueY[0]); //第一次校准
  148. delay_ms(500);
  149. TOUCH_start_calibrate(LCD_CALx_MIN, LCD_CALy_MAX, &valueX[1], &valueY[1]);
  150. delay_ms(500);
  151. TOUCH_start_calibrate(LCD_CALx_MAX, LCD_CALy_MIN, &valueX[2], &valueY[2]);
  152. delay_ms(500);
  153. TOUCH_start_calibrate(LCD_CALx_MAX, LCD_CALy_MAX, &valueX[3], &valueY[3]);
  154. delay_ms(500);
  155. //整合成对角的两点
  156. px[0] = (valueX[0] + valueX[1]) / 2;
  157. py[0] = (valueY[0] + valueY[2]) / 2;
  158. px[1] = (valueX[3] + valueX[2]) / 2;
  159. py[1] = (valueY[3] + valueY[1]) / 2;
  160. //求出比例因子
  161. xFactor = (float)LCD_CAL_X / (px[1] - px[0]);
  162. yFactor = (float)LCD_CAL_Y / (py[1] - py[0]);
  163. //求出偏移量
  164. calibrate.xoffset = (short)LCD_CALx_MAX - ((float)px[1] * xFactor);
  165. calibrate.yoffset = (short)LCD_CALy_MAX - ((float)py[1] * yFactor);
  166. calibrate.xFactor = xFactor ;
  167. calibrate.yFactor = yFactor ;
  168. printf("xoffset %d\n", calibrate.xoffset);
  169. printf("yoffset %d\n", calibrate.yoffset);
  170. printf("xFactor %f\n", calibrate.xFactor);
  171. printf("yFactor %f\n", calibrate.yFactor);
  172. //保存校准数据到at24c02
  173. calibrate.flag = TOUCH_CAL_OK;
  174. at24c02Write_buf((u8*)&calibrate, TOUCH_CAL_ADDR, sizeof(calibrate));
  175. }
  176. u8 TOUCH_scan() //查看是否触摸
  177. {
  178. u16 valueX;
  179. u16 valueY;
  180. if(TOUCH_readXY(&valueX, &valueY) == 0xFF)
  181. {
  182. return 0xFF;
  183. }
  184. //根据物理坐标,计算彩屏坐标
  185. touchX = valueX * calibrate.xFactor + calibrate.xoffset;
  186. touchY = valueY * calibrate.yFactor + calibrate.yoffset;
  187. if((touchX > tftlcd_data.width) || (touchY > tftlcd_data.height))
  188. {
  189. return 0xFF;
  190. }
  191. return 0;
  192. }
  193. int main(void)
  194. {
  195. I2C_init();
  196. TOUCH_init();
  197. at24c02Read_buf((u8*)&calibrate, TOUCH_CAL_ADDR, sizeof(calibrate));
  198. if(calibrate.flag != TOUCH_CAL_OK) //判断是否已经校准
  199. {
  200. TOUCH_calibrate();
  201. }
  202. LCD_ShowString(tftlcd_data.width-40,0,tftlcd_data.width,tftlcd_data.height,16,"clear");
  203. while(1)
  204. {
  205. if(TOUCH_scan() == 0)
  206. {
  207. LCD_Fill(touchX-1, touchY-1, touchX+2, touchY+2, FRONT_COLOR); //画粗线
  208. if((touchX > tftlcd_data.width-40) && (touchY < 20))
  209. {
  210. LCD_Fill(0, 0, tftlcd_data.width,tftlcd_data.height, BACK_COLOR); //清屏
  211. LCD_ShowString(tftlcd_data.width-40,0,tftlcd_data.width,tftlcd_data.height,16,"clear");
  212. }
  213. }
  214. }
  215. }

stm32 触摸屏 XPT2046的更多相关文章

  1. 第29章 电容触摸屏—触摸画板—零死角玩转STM32-F429系列

    第29章     电容触摸屏—触摸画板 全套200集视频教程和1000页PDF教程请到秉火论坛下载:www.firebbs.cn 野火视频教程优酷观看网址:http://i.youku.com/fir ...

  2. 基于野火M3开发板(STM32F103VET6)的迷宫小球(重力感应控制)游戏开发

    2013-03-03 这是研一上学期<实时嵌入式系统实验>课程的大作业,是利用野火板的资源,加上一个AHRS(Attitude and Heading Reference System,姿 ...

  3. LVGL库入门教程01-移植到STM32(触摸屏)

    LVGL库移植STM32 LVGL库简介 LVGL(Light and Versatile Graphics Library)是一个免费.开源的嵌入式图形库,可以创建丰富.美观的界面,具有许多可以自定 ...

  4. STM32之触摸屏

    一.触摸屏控制器简介 1.TSC2046概貌 2.TSC2046引脚描述 3.TSC2046应用电路 4.常见接线方法 YU=Y- YD=Y+ XL=X- XR=X+ 二.TSC2046编程注意事项 ...

  5. (stm32学习总结)—LCD—液晶显示

    显示器简介 显示器属于计算机的 I/O 设备,即输入输出设备.它是一种将特定电子信息输出到屏幕上再反射到人眼的显示工具.常见的有 CRT 显示器.液晶显示器.LED 点阵显示器及OLED 显示器 本章 ...

  6. [stm32][ucos][ucgui] 2、LED闪烁、串口、滑块、文本编辑框简单例程

    上一篇:[stm32][ucos] 1.基于ucos操作系统的LED闪烁.串口通信简单例程 * 内容简述: 本例程操作系统采用ucos2.86a版本, 建立了7个任务            任务名   ...

  7. FreeModbus 移植于STM32 实现Modbus RTU通信

    http://ntn314.blog.163.com/blog/static/161743584201233084434579/ 毕业设计自己要做个基于STM32的PLC能直接跑语句表的,现在看来好像 ...

  8. STM32采集电阻触摸贴膜

    今天为了解决一个测量电阻屏压力的问题,自己直接用STM32做了一个测量电阻屏的程序(直接把触摸屏的四根线接到单片机引脚上),通过AD切换采集,采集X轴电压,Y轴电压,和压力..最后附上自己的程序 先说 ...

  9. 利用XPT2046制作一个电位器AD转换装置

    XPT2046是一款四线制电阻触摸屏控制芯片,内含12位分辨率125KHz转换速率逐步逼近型A/D转换器,支持从1.5V到5.25V的低电压I/O接口. 所谓逐步逼近型,就是输入一个模拟量,其与100 ...

随机推荐

  1. 深入学习c++--多线程编程(二)【当线程间需要共享非const资源】

    1. 遇到的问题 #include <iostream> #include <thread> #include <chrono> #include <futu ...

  2. php nginx window系统 gettext方式实现UTF-8国际化多语言(i18n)

    开始应用: 步骤一:搭建环境(服务器已经完成,环境已经搭建好了) 1.首先查看你的php扩展目录下是否有php_gettext.dll这个文件,如果没有,这就需要你下载一个或是从其他地方拷贝一个,然后 ...

  3. Linux记录-批量更改当前目录的文件后缀名

    #!/bin/bash path=. for file in $(ls $path) do if [ -f $file ] then filename=${file%.*} bak=${file#*. ...

  4. *438. Find All Anagrams in a String 找到字符串中所有字母异位词

    1. 原始题目 给定一个字符串 s 和一个非空字符串 p,找到 s 中所有是 p 的字母异位词的子串,返回这些子串的起始索引. 字符串只包含小写英文字母,并且字符串 s 和 p 的长度都不超过 201 ...

  5. python中多层循环的一键退出

    在单层循环的退出中,使用break即能退出,那么多层循环呢?机智的人们使用flag标识符的方式,例如: a=['a',1,2,3,4] b=['b',1,2,3,4] c=['c',1,2,3,4] ...

  6. BladeX部署说明(win7)

    一:安装jdk-8u221-windows-x64 二:安装Nacos,解压nacos-server-1.0.0,运行bin目录下的startup.cmd,成功可以用浏览器访问:localhost:8 ...

  7. 【Leetcode_easy】925. Long Pressed Name

    problem 925. Long Pressed Name solution1: class Solution { public: bool isLongPressedName(string nam ...

  8. C#自带的Version判断版本号的大小

    Version version1 = new Version("1.0.0.25"); Version version2 = new Version("1.0.0.24& ...

  9. 文件描述符FD的含义/文件句柄

    使用sudo lsof -nP -iTCP -sTCP:LISTEN查看占用端口的程序;因为 lsof 需要访问核心内存和各种文件,所以必须以 root 用户的身份运行它才能够充分地发挥其功能 概念 ...

  10. R Multiple Plots

    R Multiple Plots In this article, you will learn to use par() function to put multiple graphs in a s ...