匿名
未登录
登录
丢石头百科
搜索
查看“STM32CubeMX系列教程23:LCD触摸控制”的源代码
来自丢石头百科
名字空间
页面
讨论
更多
更多
页面选项
查看
查看源代码
历史
←
STM32CubeMX系列教程23:LCD触摸控制
因为以下原因,您没有权限编辑本页:
您所请求的操作仅限于该用户组的用户使用:
用户
您可以查看与复制此页面的源代码。
<b>一、触摸芯片简介</b> 7inch Capacitive Touch LCD (F) 是电容触摸屏,触控芯片是GT811,如下为GT811的中文数据手册。 <a class="attach" href="portal.php?mod=attachment&id=600" target="_blank">gt811_cn.pdf GT811可同时识别5个触摸点位的实时位置,移动轨迹及触摸面积。其管脚定义如下。 [[File:163210ftd1de1im4fij4h0.png]] 参考应用电路如下图,实际上我们在使用的时候只需关心四个引脚即可。I2C_SDA,I2C_SCL为I2C通信引脚,/RSTB为系统复位引脚,INT为中断信号引脚,但有触摸时,INT输出触发信号,如果MCU对应的管脚开启外部中断则会触发MCU进入外部中断。 [[File:163211oh425yjiywjv63ly.png]] <b>二、GT811控制方式</b> GT811提供标准的I2C通信接口,由SCL和SDA与MCU进行通信,其最高通信速度为600K bps。 GT811 的从设备地址有三组可选,以方便主控调配。三组地址分别为:0xBA/0xBB、 0x6E/0x6F 和 0x28/0x29。即:0xBA——对 GT811 进行写操作;0xBB——对 GT811 进行读操作。 [[File:163212ramc6wcuod66ozr2.png]] 上图为主 CPU 对 GT811 进行的写操作流程图。首先主 CPU 产生一个起始信号, 然后发送地址信息及读写位信息“0”表示写操作:0XBA。 在收到应答后,主 CPU 发送寄存器的 16 位地址,随后是 8 位要写入到寄存器的 数据内容。 GT811 寄存器的地址指针会在写操作后自动加 1,所以当主 CPU 需要对连续地 址的寄存器进行写操作时,可以在一次写操作中连续写入。写操作完成,主 CPU 发送停止信号结束当前写操作。 [[File:163212f00a902bm03jxxxm.png]] 上图为主 CPU 对 GT811 进行的读操作流程图。首先主 CPU 产生一个起始信号, 然后发送设备地址信息及读写位信息“0”表示写操作:0XAA。 在收到应答后,主 CPU 发送首寄存器的 16 位地址信息,设置要读取的寄存器地 址。在收到应答后,主 CPU 重新发送一次起始信号,发送读操作:0XAB。收到 应答后,主 CPU 开始读取数据。 GT811 同样支持连续的读操作,默认为连续读取数据。主 CPU 在每收到一个 Byte 数据后需发送一个应答信号表示成功接收。在接收到所需的最后一个 Byte 数据 后,主 CPU 发送“非应答信号 NACK”,然后再发送停止信号结束通讯。 GT811有两组寄存器,一组为配置&功能设置寄存器,在初始化的时候配置。触摸屏配置参数由制造商提供。我们只需了解下面这个四个寄存器即可,此处为设置显示屏的分辨率。 [[File:163212qr2o1iq7zgvrkk75.png]] 另一组为输出信息寄存器,读取这组寄存器既可以判断当前屏幕的触摸状态。TouchpointFlag寄存器存储当前触摸的点数,tp0~tp4位触点状态标识为,当tp0置1时,即表示有触点0按下。 GT811最多支持5个触点,若刚开始一次由三个触点按下,tp0,tp1,tp2均置1,表示有三个触点。若此时第二个触点释放,则tp1清零,只有tp0,tp2为1。当再次有触点按下时,则为tp1置1,最新按下的是触点2,而不是触点3和触点4。 [[File:163212zuz85mn46zroml62.png]] [[File:2CDF14AE0FCB4563AF08AABB5BD8E1CC]] <b>三、新建工程</b> <b> </b> 本章在前面显示字符个工程上修改,<b style="line-height: 1.5;"><b style="font-size: 14px;"><b style="font-size: 14px;">复制刚才的的工程修改文件夹名。打开Cube工程更加原理图重新配置。PD7设置为中断输入,本章采用模拟I2C,PD12,PD13设置为GPIO输出模式,PD11输出GPIO输出。并设置用户标签。</b></b></b> [[File:163214cqhfbeh5hsznybfo.png]] 开启外部中断。 [[File:163214iuyrvqyrt77q6nrn.png]] 生成报告以及初始化代码,编译程序。若程序没有出错,下载下面的应用程序解压放在BSP文件里面并添加进工程中。 <a class="attach" href="portal.php?mod=attachment&id=599" target="_blank">BSP.zip [[File:163214kh9fh793p81z9937.png]] 其中 TS_I2C 为模拟 I2C 驱动程序,下面为读写寄存器操作函数。 <syntaxhighlight lang="python"> /******************************************************************************* * Function Name : I2C_WR_Reg * Description : Writes to the selected register. * Input : - reg: address of the selected register. * - buf: Need to write the BUF pointer. * - len: The length of the array * Output : None * Return : ret -0 succeed -1 error * Attention : None *******************************************************************************/ uint8_t I2C_WriteReg(uint8_t I2c_Addr,uint16_t reg,uint8_t *buf,uint8_t len) { uint8_t i; uint8_t ret=0; I2C_Start(); I2C_Send_Byte(I2c_Addr); //Slaver Addr I2C_Wait_Ack(); #ifdef I2C_MEMADD_16BIT I2C_Send_Byte(reg>>8); //Data Addr high I2C_Wait_Ack(); #endif I2C_Send_Byte(reg&0xFF); //Data Addr low I2C_Wait_Ack(); for(i=0;i<len;i++) { I2C_Send_Byte(buf[i]); ret=I2C_Wait_Ack(); if(ret)break; } I2C_Stop(); return ret; } /******************************************************************************* * Function Name : i2C_RD_Reg * Description : Writes to the selected register. * Input : - reg: address of the selected register. * - buf: Need to read the BUF pointer. * - len: The length of the array * Output : None * Return : None * Attention : None *******************************************************************************/ void I2C_ReadReg(uint8_t I2c_Addr,uint16_t reg,uint8_t *buf,uint8_t len) { uint8_t i; I2C_Start(); I2C_Send_Byte(I2c_Addr); I2C_Wait_Ack(); #ifdef I2C_MEMADD_16BIT I2C_Send_Byte(reg>>8); //Data Addr high I2C_Wait_Ack(); #endif I2C_Send_Byte(reg&0xFF); //Data Addr low I2C_Wait_Ack(); I2C_Stop(); I2C_Start(); I2C_Send_Byte(I2c_Addr+1); I2C_Wait_Ack(); for(i=0;i<len;i++) { buf[i]=I2C_Read_Byte(i==(len-1)?0:1); } I2C_Stop(); }</syntaxhighlight> <syntaxhighlight lang="python"> </syntaxhighlight> <syntaxhighlight lang="python"> GT811.c为触摸芯片的驱动文件,下面简单介绍一下初始化函数和读取触摸状态函数。程序开始先拉低复位管脚复位芯片,注意如果延时时间过短则会导致复位不成功。读取GT811的ID值判断通信是否正常。设置屏幕分辨率并将配置参数写入到配置&功能寄存器组中。</syntaxhighlight> <syntaxhighlight lang="python"> <syntaxhighlight lang="python"> /** * @brief Initialize the GT811 communication bus * from MCU to GT811 : ie I2C channel initialization (if required). * @retval None */ uint8_t GT811_Init(void) { I2C_Init(); /* reset GT811 */ HAL_GPIO_WritePin(LCD_RST_GPIO_Port,LCD_RST_Pin, GPIO_PIN_RESET); HAL_Delay(200); HAL_GPIO_WritePin(LCD_RST_GPIO_Port,LCD_RST_Pin, GPIO_PIN_SET); HAL_Delay(200); /* if Version is correct, send the configuration parameters */ if(GT811_ReadID() == GT811_VERSION_VALUE) { /* touch screen configuration parameter (touch screen manufacturers provide) */ uint8_t GTP_CFG_DATA[]= { 0x12,0x10,0x0E,0x0C,0x0A,0x08,0x06,0x04,0x02,0x00,0x05,0x55,0x15,0x55,0x25,0x55,0x35,0x55,0x45,0x55, 0x55,0x55,0x65,0x55,0x75,0x55,0x85,0x55,0x95,0x55,0xA5,0x55,0xB5,0x55,0xC5,0x55,0xD5,0x55,0xE5,0x55, 0xF5,0x55,0x1B,0x03,0x00,0x00,0x00,0x13,0x13,0x13,0x0F,0x0F,0x0A,0x50,0x30,0x05,0x03,0x64,0x05,0xe0, 0x01,0x20,0x03,0x00,0x00,0x32,0x2C,0x34,0x2E,0x00,0x00,0x04,0x14,0x22,0x04,0x00,0x00,0x00,0x00,0x00, 0x20,0x14,0xEC,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0C,0x30,0x25,0x28,0x14,0x00, 0x00,0x00,0x00,0x00,0x00,0x01, }; /* config */ GTP_CFG_DATA[62] = GT811_MAX_WIDTH >> 8; GTP_CFG_DATA[61] = GT811_MAX_WIDTH & 0xff; GTP_CFG_DATA[60] = GT811_MAX_HEIGHT >> 8; GTP_CFG_DATA[59] = GT811_MAX_HEIGHT & 0xff; I2C_WriteReg(GT811_CMD_WR,GT811_CONFIG_REG,(uint8_t *)GTP_CFG_DATA,sizeof(GTP_CFG_DATA)); } return HAL_OK; }</syntaxhighlight> <code style="font-family: Consolas, 'Bitstream Vera Sans Mono', 'Courier New', Courier, monospace !important; font-size: 1em !important; color: black !important;"> </syntaxhighlight></code>如下为读触摸状态函数,先通过I2C读去输出信息寄存器,判断TouchpointFlag寄存器的tp0~tp4是否置1,即是否有触摸,若有则将寄存器的值转为坐标值,存储在TS_StateTypeDef 结构体的指针内存中。 <syntaxhighlight lang="python"> <syntaxhighlight lang="python"> void GT811_GetState(TS_StateTypeDef *TS_State) { uint8_t RegBuf[34]; /* Read touch message */ I2C_ReadReg(GT811_CMD_WR,GT811_READ_XY_REG,RegBuf,sizeof(RegBuf)); /* get touch massage */ TS_State->SensorId = RegBuf[0x00] >> 6; TS_State->touchDetected = RegBuf[0x00] & 0x1F; if(TS_State->touchDetected != 0) { //Touch point 1 coordinates TS_State->touchY[0] = GT811_MAX_HEIGHT - (((uint16_t)RegBuf[0x02] << 8) + RegBuf[0x03]); TS_State->touchX[0] = (((uint16_t)RegBuf[0x04] << 8) + RegBuf[0x05]); TS_State->touchWeight[0] = RegBuf[0x06]; //Touch point 2 coordinates TS_State->touchY[1] = GT811_MAX_HEIGHT - (((uint16_t)RegBuf[0x07] << 8) + RegBuf[0x08]); TS_State->touchX[1] = (((uint16_t)RegBuf[0x09] << 8) + RegBuf[0x0A]); TS_State->touchWeight[1] = RegBuf[0x0B]; //Touch point 3 coordinates TS_State->touchY[2] = GT811_MAX_HEIGHT - (((uint16_t)RegBuf[0x0C] << 8) + RegBuf[0x0D]); TS_State->touchX[2] = (((uint16_t)RegBuf[0x0E] << 8) + RegBuf[0x0F]); TS_State->touchWeight[2] = RegBuf[0x10]; //Touch point 4 coordinates TS_State->touchY[3] = GT811_MAX_HEIGHT - (((uint16_t)RegBuf[0x11] << 8) + RegBuf[0x18]); TS_State->touchX[3] = (((uint16_t)RegBuf[0x19] << 8) + RegBuf[0x1A]); TS_State->touchWeight[3] = RegBuf[0x1B]; //Touch point 5 coordinates TS_State->touchY[4] = GT811_MAX_HEIGHT - (((uint16_t)RegBuf[0x1C] << 8) + RegBuf[0x1D]); TS_State->touchX[4] = (((uint16_t)RegBuf[0x1E] << 8) + RegBuf[0x1F]); TS_State->touchWeight[4] = RegBuf[0x20]; } }</syntaxhighlight> </syntaxhighlight> <syntaxhighlight lang="python"> TS_StateTypeDef结构体在GT811.h中定义。 </syntaxhighlight> <syntaxhighlight lang="python"> <syntaxhighlight lang="python"> typedef struct { uint8_t touchDetected; /*!< Total number of active touches detected at last scan */ uint16_t touchX[TS_MAX_NB_TOUCH]; /*!< Touch X[0], X[1] coordinates on 12 bits */ uint16_t touchY[TS_MAX_NB_TOUCH]; /*!< Touch Y[0], Y[1] coordinates on 12 bits */ uint8_t touchWeight[TS_MAX_NB_TOUCH]; /*!< Touch_Weight[0], Touch_Weight[1] : weight property of touches */ uint32_t SensorId; /*!< type of gesture detected : take value of type @ref TS_GestureIdTypeDef */ } TS_StateTypeDef;</syntaxhighlight> </syntaxhighlight> <syntaxhighlight lang="python"> 删除原来的应用代码,在main文件中添加头文件。</syntaxhighlight> <syntaxhighlight lang="python"> <syntaxhighlight lang="python"> /* USER CODE BEGIN Includes */ #include "stm32746g_sdram.h" #include "stm32746g_LCD.h" #include "GT811.h" /* USER CODE END Includes */</syntaxhighlight> </syntaxhighlight> 声明变量,其中TS_State为当前触摸状态,TS_BKState为上一次触摸状态。TS_flag为触摸标志,TouchPoit存储触点数。PointColor存储各个触点的显示颜色。 <syntaxhighlight lang="python"> /* USER CODE BEGIN PV */ /* Private variables ---------------------------------------------------------*/ TS_StateTypeDef TS_State={0}; uint8_t TS_flag ; uint8_t TouchPoit; TS_StateTypeDef TS_BKState; uint8_t value = 0; uint16_t i; uint32_t PointColor[]={LCD_COLOR_BLUE,LCD_COLOR_GREEN,LCD_COLOR_RED,LCD_COLOR_MAGENTA,LCD_COLOR_YELLOW}; /* USER CODE END PV */</syntaxhighlight> <syntaxhighlight lang="python"> </syntaxhighlight> <syntaxhighlight lang="python"> </syntaxhighlight> 在while循环中添加如下应用程序,程序首先判断触摸标志,如果有触摸,则读取触摸状态。循环中分为三分部,第一部分即清楚上次显示的内容,即将显示内容设为背景色黑色覆盖。第二部分在对应触摸的位置显示一个点和水平垂直量两条先。第三部分就这次的触摸状态存储到备份状态结构体中,以便下一次擦除。 <syntaxhighlight lang="python"> <syntaxhighlight lang="python"> /* USER CODE BEGIN WHILE */ while (1) { /* USER CODE END WHILE */ /* USER CODE BEGIN 3 */ if(TS_flag == 1) { GT811_GetState(&TS_State); if(TS_State.touchDetected != 0) { TouchPoit = TS_BKState.touchDetected; for(i = 0;i < 5;i++) { if(TouchPoit & 0x01) { BSP_LCD_SetTextColor(LCD_COLOR_BLACK); BSP_LCD_FillCircle(TS_BKState.touchX[i],TS_BKState.touchY[i],20); BSP_LCD_DrawVLine(TS_BKState.touchX[i], 55, 580); BSP_LCD_DrawHLine(5, TS_BKState.touchY[i], 1004); } TouchPoit >>= 1; } TouchPoit = TS_State.touchDetected; for(i = 0;i < 5;i++) { if(TouchPoit & 0x01) { if(TS_State.touchY[i] < 75)TS_State.touchY[i] = 75; if(TS_State.touchY[i] > 580)TS_State.touchY[i] = 580; if(TS_State.touchX[i] < 20)TS_State.touchX[i] = 20; if(TS_State.touchX[i] > 1004)TS_State.touchX[i] = 1004; BSP_LCD_SetTextColor(PointColor[i]); BSP_LCD_FillCircle(TS_State.touchX[i],TS_State.touchY[i],20); BSP_LCD_DrawVLine(TS_State.touchX[i], 55, 580); BSP_LCD_DrawHLine(5, TS_State.touchY[i], 1004); TS_BKState.touchX[i] = TS_State.touchX[i]; TS_BKState.touchY[i] = TS_State.touchY[i]; } TouchPoit >>= 1; } TS_BKState.touchDetected = TS_State.touchDetected; } TS_flag = 0; } } /* USER CODE END 3 */</syntaxhighlight> </syntaxhighlight> <syntaxhighlight lang="python"> 在main文件后面添加外部中断回调函数,当屏幕有触摸是触发中断,触摸标志位置1。</syntaxhighlight> <syntaxhighlight lang="python"> <syntaxhighlight lang="python"> /* USER CODE BEGIN 4 */ /** * @} */ void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin) { if( GPIO_Pin == GPIO_PIN_7) { TS_flag = 1; } } /* USER CODE END 4 */</syntaxhighlight> </syntaxhighlight>编译程序下载到开发板中,触摸屏幕会显示触点。(以下为五点触控效果的显示) [[File:163214vyhyze9zgyk9ik6v.png]]
返回至
STM32CubeMX系列教程23:LCD触摸控制
。
导航
导航
首页
最近更改
随机页面
MediaWiki帮助
首页
首页
树莓派
主机
配件包
外壳
键鼠
电源
扩展板
显示屏
墨水屏
摄像模块
通信模块
继电器
电机驱动板
游戏机
产品分类
树莓派
Arduino
micro:bit
STM32
Espressif
WiFi模块
蓝牙模块
无线模块
LoRa模块
4G模块
GSM
GPRS
以太网
导航模块
北斗卫星
GPS
LCD
墨水屏
OLED
摄像头
USB模块
串口模块
RS232
RS485
CAN
传感器
温度模块
湿度模块
气压模块
继电器
电机模块
指纹模块
电平转换
音频模块
编程器
Wiki工具
Wiki工具
特殊页面
页面工具
页面工具
用户页面工具
更多
链入页面
相关更改
页面信息
页面日志