完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
|
|
相关推荐
1个回答
|
|
1.触摸屏简介
目前最常用的触摸屏有两种:电阻式触摸屏和电容式触摸屏 1.1 电阻式触摸屏 电阻式的触摸屏结构如下图示,它主要由表面硬涂层、两个ITO层、间隔点以及玻璃底层构成,这些结构层都是透明的,整个触摸屏覆盖在液晶面板上,透过触摸屏可看到液晶面板。表面涂层起到保护作用,玻璃底层起承载的作用,而两个ITO层是触摸屏的关键结构,它们是涂有铟锡金属氧化物的导电层。两个ITO层之间使用间隔点使两层分开,当触摸屏表面受到压力时,表面弯曲使得上层ITO与下层ITO接触,在触点处连通电路。 两个ITO涂层的两端分别引出X-、X+、Y-、Y+四个电极,这是电阻屏最常见的四线结构,通过这些电极,外部电路向这两个涂层可以施加匀强电场或检测电压。 电阻触摸屏的校准:确定位置和对应的电压值之间的比例关系 X0 = Xfac * ADC_X + Xoff电阻触摸屏的优缺点
1.2 电容式触摸屏 与电阻式触摸屏不同,电容式触摸屏不需要通过压力使触点变形。它的基本原理是利用充电时间检测电容大小,若手指触摸屏幕,会影响触摸点附近两个电极之间的耦合,从而改变两个电极之间的电容量,若检测到某电容的电容量发生了改变,即可获知该电容处有触摸动作从而通过检测出电容值的变化来获知触摸信号。 由于本例程使用的是电阻式触摸屏,这里电容式触摸屏不做详细介绍 2. 硬件设计 D1指示灯用来提示系统运行状态,K_UP按键用来强制校准电阻触摸屏(电容屏无需校准),AT24C02用来存储电阻触摸屏校准数据,TFTLCD模块用来显示触摸
3. 软件设计 3.1 STM32CubeMX设置
3.2 MDK-ARM编程 添加按键驱动文件key.c和key.h,参考按键输入例程 添加AT24C02驱动文件24cxx.c和24cxx.h,参考I2C总线例程 添加TFTLCD驱动文件tftlcd.c 和tftlcd.h,参考TFTLCD显示例程 添加XPT2046触摸芯片驱动文件touch.c和touch.h 两个重要的结构体: typedef struct{ /*存储触点读取到的数据*/ uint16_t x; //x轴物理坐标值 uint16_t y; //y轴物理坐标值 uint16_t lcdx; //x轴彩屏坐标值 uint16_t lcdy; //y轴彩屏坐标值 }TouchTypeDef; typedef struct{ /*保存校正因素*/ uint8_t posState; //校正参数标志 int16_t xOffset; //x轴偏移量 int16_t yOffset; //y轴偏移量 float xFactor; //x轴比例因数 float yFactor; //y轴比例因数 }PosTypeDef; 触摸屏初始化及读取物理坐标(ADC值)函数: void TOUCH_Init(void){ //读取AT24C02的TOUCH_ADJ_ADDR地址处的值 HAL_I2C_Mem_Read(&hi2c2,ADDR_24CXX_READ,TOUCH_ADJ_ADDR,I2C_MEMADD_SIZE_8BIT,&TouchAdj.posState,sizeof(TouchAdj),0xff); if(TouchAdj.posState != TOUCH_ADJ_OK){ //检查是否有校正数据 TOUCH_Adjust(); //如果没有校正数据,则启动校正函数 } } /*封装SPI读取数据函数*/ uint8_t WR_Cmd(uint8_t cmd){ uint8_t Tx_DATA = cmd; uint8_t Rx_DATA = 0; HAL_SPI_TransmitReceive(&hspi1,&Tx_DATA,&Rx_DATA,1,500); return Rx_DATA; } /*读取X轴或Y轴的ADC值,并进行滤波处理*/ uint16_t TOUCH_Read_AD(uint8_t cmd){ uint8_t i, j; uint16_t NUMH,NUML; uint16_t NUM[TOUCH_READ_TIMES] = {0}; uint16_t temp,value; uint32_t totalValue; //注意数据类型 for(i=0; i WR_Cmd(cmd); NUMH = WR_Cmd(0XFF); NUML = WR_Cmd(0XFF); NUM = (NUMH<<8)+ NUML; NUM >>= 3; //最低三位无用 TOUCH_CS_HIGH(); //结束SPI通讯 } //滤波处理:1.从大到小排序 for(i=0; i<(TOUCH_READ_TIMES - 1); i++){ for(j=i+1; j temp = NUM; NUM = NUM[j]; NUM[j] = temp; } } } //滤波处理:2.去掉最大值和最小值,求余下的平均值 j = TOUCH_READ_TIMES - 1; totalValue = 0; for(i=1; i } value = totalValue/(TOUCH_READ_TIMES - 2); return value; } /*读取X轴和Y轴的ADC值,再次进行滤波*/ uint8_t TOUCH_ReadXY(uint16_t *xValue, uint16_t *yValue){ uint16_t xValue1, yValue1, xValue2, yValue2; xValue1 = TOUCH_Read_AD(TOUCH_X_CMD); yValue1 = TOUCH_Read_AD(TOUCH_Y_CMD); xValue2 = TOUCH_Read_AD(TOUCH_X_CMD); yValue2 = TOUCH_Read_AD(TOUCH_Y_CMD); //计算两点之间的采样差值 if(xValue1 > xValue2) *xValue = xValue1 - xValue2; else *xValue = xValue2 - xValue1; if(yValue1 > yValue2) *yValue = yValue1 - yValue2; else *yValue = yValue2 - yValue1; //判断采样差值是否在可控范围内 if((*xValue > TOUCH_MAX+0) || (*yValue > TOUCH_MAX+0)) return 0xFF; //求平均值 *xValue = (xValue1 + xValue2) / 2; *yValue = (yValue1 + yValue2) / 2; //判断得到的值,是否在取指范围内,避免出现飞点现象 if((*xValue > TOUCH_X_MAX+0) || (*xValue < TOUCH_X_MIN) || (*yValue > TOUCH_Y_MAX+0) || (*yValue < TOUCH_Y_MIN)) return 0xFF; return 0; } 触摸屏校准函数: /*读校准点的物理坐标*/ uint8_t TOUCH_ReadAdjust(uint16_t x, uint16_t y, uint16_t *xValue, uint16_t *yValue){ uint8_t i; uint32_t timeCont; LCD_Clear(BACK_COLOR); LCD_DrowSign(x, y, RED); //x和y为指定的校准点的彩屏坐标值 i = 0; while(1){ //读该指定校准点的物理坐标值 if(!TOUCH_ReadXY(xValue, yValue)){ i++; if(i > 10){ LCD_DrowSign(x, y, BACK_COLOR); return 0; } } timeCont++; if(timeCont > 0xFFFFFFFE){ //超时退出 LCD_DrowSign(x, y, BACK_COLOR); return 0xFF; } } } /*触摸屏校准函数*/ void TOUCH_Adjust(void){ uint16_t px[2], py[2], xPot[4], yPot[4]; float xFactor, yFactor; //读取4个校准点的物理坐标值 if(TOUCH_ReadAdjust(LCD_ADJX_MIN, LCD_ADJY_MIN, &xPot[0], &yPot[0])) return; HAL_Delay(500); if(TOUCH_ReadAdjust(LCD_ADJX_MIN, LCD_ADJY_MAX, &xPot[1], &yPot[1])) return; HAL_Delay(500); if(TOUCH_ReadAdjust(LCD_ADJX_MAX, LCD_ADJY_MIN, &xPot[2], &yPot[2])) return; HAL_Delay(500); if(TOUCH_ReadAdjust(LCD_ADJX_MAX, LCD_ADJY_MAX, &xPot[3], &yPot[3])) return; HAL_Delay(500); //处理读取到的四个点的数据,整合成对角的两个点 px[0] = (xPot[0] + xPot[1]) / 2; py[0] = (yPot[0] + yPot[2]) / 2; px[1] = (xPot[3] + xPot[2]) / 2; py[1] = (yPot[3] + yPot[1]) / 2; //求出比例因数 xFactor = (float)LCD_ADJ_X / (px[1] - px[0]); yFactor = (float)LCD_ADJ_Y / (py[1] - py[0]); //求出偏移量 TouchAdj.xOffset = (int16_t)LCD_ADJX_MAX - ((float)px[1] * xFactor); TouchAdj.yOffset = (int16_t)LCD_ADJY_MAX - ((float)py[1] * yFactor); //将比例因数进行数据处理,并保存 TouchAdj.xFactor = xFactor ; TouchAdj.yFactor = yFactor ; TouchAdj.posState = TOUCH_ADJ_OK; //将得出的校正因数保存到AT24C02中的TOUCH_ADJ_ADDR地址处 HAL_I2C_Mem_Write(&hi2c2,ADDR_24CXX_WRITE,TOUCH_ADJ_ADDR,I2C_MEMADD_SIZE_8BIT,&TouchAdj.posState,sizeof(TouchAdj),0xff); } 触摸屏扫描函数: uint8_t TOUCH_Scan(void){ if(TOUCH_ReadXY(&TouchData.x, &TouchData.y)) return 0xFF; //没有触摸,直接返回0xFF //根据物理坐标值,计算出彩屏坐标值 TouchData.lcdx = TouchData.x * TouchAdj.xFactor + TouchAdj.xOffset; TouchData.lcdy = TouchData.y * TouchAdj.yFactor + TouchAdj.yOffset; //查看彩屏坐标值是否超过彩屏大小 if(TouchData.lcdx > tftlcd_data.width) TouchData.lcdx = tftlcd_data.width; if(TouchData.lcdy > tftlcd_data.height) TouchData.lcdy = tftlcd_data.height; return 0; } 在main.c文件下编写触摸屏测试代码 int main(void){ uint8_t key; uint16_t penColor = BLUE; HAL_Init(); SystemClock_Config(); MX_GPIO_Init(); MX_FSMC_Init(); MX_I2C2_Init(); MX_SPI1_Init(); MX_USART1_UART_Init(); /* USER CODE BEGIN 2 */ TFTLCD_Init(); AT24CXX_Init(); HAL_Delay(2000); LCD_Clear(WHITE); TOUCH_Init(); /* USER CODE END 2 */ while (1){ key=KEY_Scan(0); if(key==KEY_UP_PRES){ //按下KEY_UP键进入校准函数 TOUCH_Adjust(); } if(TOUCH_Scan() == 0){ if(TouchData.lcdy > tftlcd_data.height - 18){ //选择画笔颜色 if(TouchData.lcdx>220) penColor = YELLOW; else if(TouchData.lcdx>200) penColor = CYAN; else if(TouchData.lcdx>180) penColor = GREEN; else if(TouchData.lcdx>160) penColor = MAGENTA; else if(TouchData.lcdx>140) penColor = RED; else if(TouchData.lcdx>120) penColor = BLUE; }else{ //画点 LCD_Fill(TouchData.lcdx-1, TouchData.lcdy-1, TouchData.lcdx+2, TouchData.lcdy+2, penColor); } //清屏 if ((TouchData.lcdx > tftlcd_data.width-8*4) && (TouchData.lcdy < 16))//215 = TFT_XMAX - 24{ LCD_Fill(0, 0, tftlcd_data.width,tftlcd_data.height-16, BACK_COLOR); LCD_ShowString(tftlcd_data.width-8*4,0,tftlcd_data.width,tftlcd_data.height,16,(uint8_t *)"RST"); } } HAL_GPIO_TogglePin(GPIOC,GPIO_PIN_0); HAL_Delay(10); } } 4. 下载验证 编译无误下载到开发板后,可以看到D1指示灯不断闪烁,触摸屏显示界面如下图示 |
|
|
|
只有小组成员才能发言,加入小组>>
调试STM32H750的FMC总线读写PSRAM遇到的问题求解?
1614 浏览 1 评论
X-NUCLEO-IHM08M1板文档中输出电流为15Arms,15Arms是怎么得出来的呢?
1541 浏览 1 评论
970 浏览 2 评论
STM32F030F4 HSI时钟温度测试过不去是怎么回事?
682 浏览 2 评论
ST25R3916能否对ISO15693的标签芯片进行分区域写密码?
1592 浏览 2 评论
1863浏览 9评论
STM32仿真器是选择ST-LINK还是选择J-LINK?各有什么优势啊?
644浏览 4评论
STM32F0_TIM2输出pwm2后OLED变暗或者系统重启是怎么回事?
515浏览 3评论
531浏览 3评论
stm32cubemx生成mdk-arm v4项目文件无法打开是什么原因导致的?
504浏览 3评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2024-11-21 23:26 , Processed in 0.833838 second(s), Total 78, Slave 61 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号