| **银杏科技有限公司旗下技术文档发布平台** |||| |技术支持电话|**0379-69926675-801**||| |技术支持邮件|Gingko@vip.163.com||| ^ 版本 ^ 日期 ^ 作者 ^ 修改内容 ^ | V1.0 | 2020-10-16 | gingko | 初次建立 | \\ \\ \\ \\ \\ \\ \\ \\ ===== STM32CubeMX教程六十三——TOUCH实验 ===== 1.在主界面选择File-->New Project 或者直接点击ACCEE TO MCU SELECTOR {{ :icore4t:icore4t_cube_63_1.png?direct |}} 2.出现芯片型号选择,搜索自己芯片的型号,双击型号,或者点击Start Project进入配置 在搜索栏的下面,提供的各种查找方式,可以选择芯片内核、型号等等,可以帮助你查找芯片。本实验选取的芯片型号为:STM32H750IBKx。 {{ :icore4t:icore4t_cube_63_2.png?direct |}} 3.配置RCC,使用外部时钟源 {{ :icore4t:icore4t_cube_63_3.png?direct |}} 4.时基源选择SysTick {{ :icore4t:icore4t_cube_63_4.png?direct |}} 5.将PA10,PB7,PB8,PI1,PI2,PI3设置为GPIO_Output {{ :icore4t:icore4t_cube_63_5.png?direct |}} 6.引脚模式配置 {{ :icore4t:icore4t_cube_63_6.png?direct |}} 7.配置定时器 {{ :icore4t:icore4t_cube_63_7.png?direct |}} 定时器分配引脚如下所示 {{ :icore4t:icore4t_cube_63_8.png?direct |}} 8.配置FMC {{ :icore4t:icore4t_cube_63_9.png?direct |}} 9.配置SDMMC {{ :icore4t:icore4t_cube_63_10.png?direct |}} {{ :icore4t:icore4t_cube_63_11.png?direct |}} 10.配置LTDC {{ :icore4t:icore4t_cube_63_12.png?direct |}} {{ :icore4t:icore4t_cube_63_13.png?direct |}} 11.配置CRC {{ :icore4t:icore4t_cube_63_14.png?direct |}} 12.配置FATFS {{ :icore4t:icore4t_cube_63_15.png?direct |}} 13.时钟源设置,选择外部高速时钟源,配置为最大主频。 {{ :icore4t:icore4t_cube_63_16.png?direct |}} {{ :icore4t:icore4t_cube_63_17.png?direct |}} 14.工程文件的设置, 这里就是工程的各种配置 我们只用到有限几个,其他的默认即可 IDE我们使用的是 MDK V5.27 {{ :icore4t:icore4t_cube_63_18.png?direct |}} 15.点击Code Generator,进行进一步配置 {{ :icore4t:icore4t_cube_63_19.png?direct |}} * **Copy all used libraries into the project folder** * 将HAL库的所有.C和.H都复制到所建工程中 * 优点:这样如果后续需要新增其他外设又可能不再用STM32CubeMX的时候便会很方便 * 缺点:体积大,编译时间很长 * **Copy only the necessary library files** * 只复制所需要的.C和.H(推荐) * 优点:体积相对小,编译时间短,并且工程可复制拷贝 * 缺点:新增外设时需要重新用STM32CubeMX导入 * **Add necessary library files as reference in the toolchain project configuration file** * 不复制文件,直接从软件包存放位置导入.C和.H * 优点:体积小,比较节约硬盘空间 * 缺点:复制到其他电脑上或者软件包位置改变,就需要修改相对应的路径 * 自行选择方式即可 16.然后点击GENERATE CODE 创建工程 {{ :icore4t:icore4t_cube_63_20.png?direct |}} 创建成功,打开工程。 \\ \\ \\ ===== 实验六十三:TOUCH实验——电容触摸 ===== ==== 一、 实验目的与意义 ==== - 了解STM32 LTDC结构 - 了解STM32 LTDC特征 - 掌握LTDC液晶屏的使用方法 - 掌握LTDC应用之LCD电容触摸芯片GT911的使用方法 - 掌握KEIL MDK 集成开发环境使用方法 ==== 二、 实验设备及平台 ==== - iCore4T 双核心板 - 转接板和40P的FPC连接线。 - iCore4T 扩展底板 - iCore 4.3寸液晶屏底板 - Blaster(或相同功能)仿真器 - Micro USB线缆 - Keil MDK 开发平台 - STM32CubeMX开发平台 - 装有WIN XP(及更高版本)系统的计算机 ==== 三、 实验原理 ==== === 1. LTDC基础知识 === * (一)LTDC关键知识点: * 1)STM32H7的LTDC最大支持1024*768分辨率,且支持硬件双图层。实际支持的分辨率可能比1024*768要高一点,因为最 终可以支持的最大分辨率是芯片后期定标的。 * 2)支持32位色,24位色,16位色和8位色。 * 3)可编程窗口位置和大小,可编程行同步,场同步和数据使能信号的极性。 * 4)查色表 (CLUT,Color look-up table),每个图层最高可记录256种24位色。 * 5)支持如下8种颜色格式: * **ARGB8888** * 32位颜色格式,一个像素点占用4字节,其中低位 3 字节用于颜色分量,高位字节用于 Alpha 混合。红、绿、蓝和 Alpha通道(0x00表示完全透明,0xFF表示完全不透明)都是 8 位表示。 * 普通列表项目颜色格式:AAAAAAAARRRRRRRRGGGGGGGGBBBBBBBB。 * **RGB888** * 普通列表项目24位颜色格式,一个像素点占用3字节,分别用于红、绿、蓝。 * 普通列表项目颜色格式:RRRRRRRRGGGGGGGGBBBBBBBB。 * **RGB565** * 16位颜色格式,一个像素点占用2字节,分别用于红、绿、蓝。 * 颜色格式:RRRRRGGGGGGBBBBB。 * **ARGB1555** * 16位颜色格式,一个像素点占用2字节,Alpha通道使用1个位表示,等于0的时候表示完全透明,等于1的时候表示完全不透明。红、绿、蓝都是用5个位表示。 * 颜色格式:ARRRRRGGGGGBBBBB。 * **ARGB4444** * 16位颜色格式,一个像素点占用2字节,Alpha通道使用2个位表示(0x0表示完全透明,0x3表示完全不透明)。红、绿、蓝都是用4个位表示。 * 颜色格式:ARRRRRGGGGGBBBBB。 * **L8 (8-bit luminance or CLUT)** * 8位颜色格式,实际上仅仅是8位索引值,范围0–255,而每个索引值的具体颜色值在查色表CLUT里面存储。 * **AL44 (4-bit alpha + 4-bit luminance)** * 8位颜色格式,实际上是4位Alpha通道(0x0表示完全透明,0xF表示完全不透明)和4位的索引值,索引范围0–15,而每个索引值的具体颜色值在查色表CLUT里面存储。 * **AL88 (8-bit alpha + 8-bit luminance)** * 16位颜色格式,实际上是8位Alpha通道(0x00表示完全透明,0xFF表示完全不透明)和8位的索引值,索引范围0–255,而每个索引值的具体颜色值在查色表CLUT里面存储。 * (二)LTDC 硬件框图: {{ :icore4t:iCore4T_ARM_HAL_63_1.png?direct |}} * ltdc_aclk :为LTDC寄存器提供时钟,时钟来自AXI时钟域。 * ltdc_pclk :LTDC寄存器接口时钟。 * ltdc_ker_ck :用于生成LCD_CLK(像素时钟输出)的LTDC内核时钟。 * ltdc_li_it :LTDC行中断,用于触发MDMA。 * ltdc_it :LTDC全局中断请求。 * ltdc_err_it :LTDC全局错误中断请求。 * 下面是LCD接口引脚,用于外接显示屏: * LCD_CLK :像素时钟输出。 * LCD_HSYNC :水平同步信号。 * LCD_VSYN :垂直同步信号。 * LCD_DE :数据使能信号。 * LCD_R[7:0] :8位红色数据。 * LCD_G[7:0] :8 位绿色数据。 * LCD_B[7:0] :8位蓝色数据。 === 2.电阻触摸、电容触摸相关知识=== * 有了TFT裸屏后还要配套电阻触摸板或者电容触摸板才可以获取触摸信息。触摸板是贴到TFT屏上面的,然后再通过电阻触摸芯片就可以获取电阻触摸板的信息,通过电容触摸芯片采集电容触摸板的信息。目前市面上常用的电阻触摸IC是STMPE811,电容触摸IC是GT811、GT911和FT5X06。其中,电阻触摸和电容触摸两者的区别如下: * 电阻触摸芯片STMPE811其实就是ADC,返回的是ADC数值,而电容触摸芯片GT811、GT911和FT5X06返回的是显示屏实际的坐标值。 * 使用电阻触摸芯片STMPE811需要做触摸校准,而使用电容触摸芯片GT811、GT911和FT5X06是自动校准的,无需手动校准。 === 3.电容触摸芯片GT911介绍=== * 在本实验中,选用电容触摸芯片GT911来实现电容触摸功能。 * 电容触摸相比电阻触摸简单,因为电容触摸不需要做触摸校准,而且用的是触摸板和触摸芯片一体的,也不需要做寄存器初始化配置,上电后直接读取参数即可。 * GT911、GT928、GT9147都属于GT9系列非单层多点触控芯片,他们支持的触控点数不同(GT928支持10个点、GT911支持5个点)、驱动和感应通道也可能不同。可是他们的寄存器和IIC通讯时序是相同的,也就是说驱动程序是兼容的。 * GT911是专为7”~8”设计的新一代5点电容触控方案,拥有26个驱动通道和14个感应通道,以满足更高的touch精度要求。GT911可同时识别5个触摸点位的实时准确位置,移动轨迹及触摸面积。并可根据主控需要,读取相应点数的触摸信息。 * 与主机的接口共有6PIN,分别为:VDD、GND、SCL、SDA、INT、RESET。 * INT、RESET不需要接上下拉电阻,可与主机直连。 * SCL、SDA需要接上拉电阻4.7K,毕竟400KHz的通信频率,没有上拉可能导致SCL、SDA边沿不够陡峭。 * RST是复位引脚,拉低100us以上,即可复位。正常工作时,应该保持拉高。 * INT是GT9xx的触摸信号输出引脚,在正常工作时,主机端要设置为悬浮输入,即不上下拉(GT9xx的驱动能力有限,如果外部上下拉,GT9xx可能驱动不了)。当有触摸发生时,INT引脚会输出上升沿或下降沿(内部寄存器可以配置),主机端可以一直读取INT脚的电平信号,也可以用端口外部中断检测。 === 4.电容触摸芯片GT911的I2C通讯=== * GT911提供标准的I2C通讯接口,由SCL和SDA与主CPU进行通讯。在系统中GT911始终作为从设备,所有通讯都是由主CPU发起,建议通讯速度为400Kbps或以下。其支持的I2C硬件电路支持时序如下: {{ :icore4t:iCore4T_ARM_HAL_63_2.png?direct |}} * GT911的I2C从设备地址有两组,分别为0xBA/0xBB和0x28/0x29。主控在上电初始化时控制Reset和INT口状态进行设定,设定方法及时序图如下: * 上电时序图: {{ :icore4t:iCore4T_ARM_HAL_63_3.png?direct |}} {{ :icore4t:iCore4T_ARM_HAL_63_4.png?direct |}} * **1)数据传输(以设备地址为0xBA/0xBB为例)** * 通讯总是由主 CPU 发起,有效的起始信号为:在 SCL 保持为“1”时,SDA 上发生由“1”到“0”的跳变。地址信息或数据流均在起始信号之后传输。 * 所有连接在I2C总线上的从设备,都要检测总线上起始信号之后所发送的8位地址信息, * 并做出正确反应。在收到与自己相匹配的地址信息时,GT911在第9个时钟周期,将SDA改为输出口,并置“0”,作为应答信号。若收到不与自己匹配的地址信息,即非0XBA或0XBB,GT911将保持闲置状态。 * SDA口上的数据按9个时钟周期串行发送9位数据:8位有效数据+1位接收方发送的应答信号ACK或非应答信号NACK。数据传输在SCL为“1”时有效。 * 当通讯完成时,由主CPU发送停止信号。停止信号是当SCL为“1”时,SDA状态由“0”到“1”的跳变。 * **2)对GT911写操作(以设备地址为0xBA/0xBB为例)** {{ :icore4t:iCore4T_ARM_HAL_63_5.png?direct |}} * 上图为主CPU对GT911进行的写操作流程图。首先主CPU产生一个起始信号,然后发送地址信息及读写位信息“0”表示写操作:0XBA。在收到应答后,主CPU发送寄存器的16位地址,随后是8位要写入到寄存器的数据内容GT911寄存器的地址指针会在写操作后自动加1,所以当主CPU需要对连续地址的寄存器进行写操作时,可以在一次写操作中连续写入。写操作完成,主CPU发送停止信号结束当前写操作。 * **3)对GT911读操作(以设备地址为0xBA/0xBB为例)** {{ :icore4t:iCore4T_ARM_HAL_63_6.png?direct |}} * 上图为主CPU对GT911进行的读操作流程图。首先主CPU产生一个起始信号,然后发送设备地址信息及读写位信息“0”表示写操作:0XBA。在收到应答后,主CPU发送首寄存器的16位地址信息,设置要读取的寄存器地址。在收到应答后,主CPU重新发送一次起始信号,发送读操作:0XBB。收到应答后,主CPU开始读取数据。 * GT911同样支持连续的读操作,默认为连续读取数据。主CPU在每收到一个Byte数据后需发送一个应答信号表示成功接收。在接收到所需的最后一个Byte数据后,主CPU发送“非应答信号NACK”,然后再发送停止信号结束通讯。 ===5.电容触摸芯片GT911功能描述=== * (一)工作模式 {{ :icore4t:iCore4T_ARM_HAL_63_7.png?direct |}} * **a)Normal Mode** * GT911在Normal Mode时,最快的坐标刷新周期为7ms-10ms间(依赖于配置信息的设定,配置信息可控周期步进长度为1ms)。 * Normal mode状态下,一段时间无触摸事件发生,GT911将自动转入Green mode,以降低功耗。GT911无触摸自动进入Green mode的时间可通过配置信息设置,范围为0~15s,步进为1s。 * **b)Green Mode** * 在Green mode下,GT911扫描周期约为40ms,若检测到有触摸动作发生,自动进入Normal mode。 * **c)Sleep Mode** * 主CPU通过I2C命令,使GT911进入Sleep mode(需要先将INT脚输出低电平)。当需要GT911退出Sleep mode时,主机输出一个高电平到INT脚(主机打高INT脚2~5ms),唤醒后GT911将进入Normal mode。 {{ :icore4t:iCore4T_ARM_HAL_63_8.png?direct |}} * (二)中断触发方式 * 当有触摸时,GT911 每个扫描周期均会通过 INT 脚发出脉冲信号,通知主 CPU 读取坐标信息。主CPU可以通过相关的寄存器位“INT”来设置触发方式。设为“0”表示上升沿触发,即在有用户操作时,GT911会在INT口输出上升沿跳变,通知 CPU;设为“1”表示下降沿触发,即在有用户操作时,GT911会在INT口输出下降沿跳变。 ==== 四、 实验程序 ==== === 1.主函数 === int main(void) { FATFS fatfs; HAL_Init(); SystemClock_Config(); i2c.initialize(); axp152.initialize(); axp152.set_dcdc1(3500);//[ARM & FPGA BK1/2/6 &OTHER] axp152.set_dcdc2(1200);//[FPGA INT & PLL D] axp152.set_aldo1(2500);//[FPGA PLL A] axp152.set_dcdc4(3300);//[POWER_OUTPUT] axp152.set_dcdc3(3300);//[FPGA BK4][Adjustable] axp152.set_aldo2(3300);//[FPGA BK3][Adjustable] axp152.set_dldo1(3300);//[FPGA BK7][Adjustable] axp152.set_dldo2(3300);//[FPGA BK5][Adjustable] MX_GPIO_Init(); MX_CRC_Init(); MX_LTDC_Init(); MX_TIM12_Init(); MX_SDMMC1_SD_Init(); MX_FATFS_Init(); MX_FMC_Init(); BSP_SDRAM_Init(); lcd.initialize(); HAL_TIM_PWM_Start(&htim12,TIM_CHANNEL_1); LED_ON; GUI_Init(); GUI_SetBkColor(GUI_BLACK); GUI_Clear(); LCD_ON; frame.process(); //界面处理 ===2.LTDC参数初始化结构体LTDC_InitTypeDef === * 此结构体用于配置LTDC的基本参数,具体定义如下: typedef struct { uint32_t HSPolarity; uint32_t VSPolarity; uint32_t DEPolarity; uint32_t PCPolarity; uint32_t HorizontalSync; uint32_tVerticalSync; uint32_t AccumulatedHBP; uint32_t AccumulatedVBP; uint32_t AccumulatedActiveW; uint32_t AccumulatedActiveH; uint32_t TotalWidth; uint32_t TotalHeigh; LTDC_ColorTypeDef Backcolor; } LTDC_InitTypeDef; * uint32_t HSPolarity 此参数用于设置水平同步信号极性,具体支持的参数如下: #define LTDC_HSPOLARITY_AL (0x00000000U) 水平同步极性低电平有效 #define LTDC_HSPOLARITY_AH LTDC_GCR_HSPOL 水平同步极性高电平有效 * uint32_t VSPolarity 此参数用于设置垂直同步信号极性,具体支持的参数如下 #define LTDC_VSPOLARITY_AL (0x00000000U) /* 垂直同步极性低电平有效 #define LTDC_VSPOLARITY_AH LTDC_GCR_VSPOL /* 垂直同步极性高电平有效 * uint32_t DEPolarity 此参数用于设置数据使能极性,具体支持的参数如下: #define LTDC_DEPOLARITY_AL (0x00000000U) /* 数据使能极性低电平有效 #define LTDC_DEPOLARITY_AH LTDC_GCR_DEPOL /* 数据使能极性高电平有效 * uint32_t PCPolarity 此参数用于设置像素时钟极性,具体支持的参数如下: #define LTDC_PCPOLARITY_IPC (0x00000000U) 像素时钟极性低电平有效 #define LTDC_PCPOLARITY_IIPC LTDC_GCR_PCPOL 像素时钟极性高电平有效 * uint32_t HorizontalSync 此参数用于设置水平同步宽度,范围 0 x 000 0xFFF 单位像素时钟个数 。 * uint32_t VerticalSync 此参数用于设置垂直同步宽度,范围 0 x 000 0x 7 FF 单位像素时钟个数。 * uint32_t AccumulatedHBP 此参数用于设置 HSYNC水平同步宽度+ HBP水平后沿之和,范围HSYNC水平同步宽度到0 xFFF,单位像素时钟个数。 * uint32_t AccumulatedVBP 此参数用于设置VSYNC垂直同步宽度+ VBP垂直后沿之和,范围VSYNC垂直同步宽度到0x7FF,单位像素时钟个数。 * uint32_t AccumulatedActiveW 此参数用于设置HSYNC水平同步宽度+ HBP水平后沿+ 有效宽度之和,范围AccumulatedHBP到0xFFF,单位像素时钟个数。 * uint32_t AccumulatedActiveH 此参数用于设置VSYNC垂直同步宽度+ VBP垂直后沿+ 有效高度之和,范围AccumulatedVBP到0x7FF,单位像素时钟个数。 * uint32_t TotalWidth 此参数用于设置HSYNC水平同步宽度+ HBP水平后沿+ 有效宽度+ HFP水平前沿之和,范围AccumulatedActiveW到0xFFF,单位像素时钟个数。 * uint32_t TotalHeigh 此参数用于设置VSYNC垂直同步宽度+ VBP垂直后沿+ 有效高度+VFP垂直前沿之和,范围AccumulatedActiveH到0x7FF,单位像素时钟个数。 * LTDC_ColorTypeDef Backcolor 此参数用于设置背景层颜色,结构体LTDC_ColorTypeDef的定义如下: typedef struct { uint8_t Blue; uint8_t Green; uint8_t Red; uint8_t Reserved; } LTDC_ColorTypeDef; * Bule用于设置蓝色值,范围0x00到0xFF。 * Green用于设置绿色值,范围0x00到0xFF。 * Red用于设置红色值,范围0x00到0xFF。 === 3.进行GUI界面处理 === static void frame_process(void) { gt911.initialize(); GUI_CURSOR_Show(); WM_SetCreateFlags(WM_CF_MEMDEV); GUI_CreateDialogBox(_aDialogCreate,GUI_COUNTOF(_aDialogCreate), _cbDialog, WM_HBKWIN, 0, 0); while(1){ if(systick._20ms_flag == 1){ systick._20ms_flag = 0; GUI_TOUCH_Exec(); GUI_Exec(); } if(touch_flag == 1){ touch_flag = 0; EDIT_SetValue(h_edit_0,gt911.x[0]); EDIT_SetValue(h_edit_1,gt911.y[0]); GUI_Exec(); } GUI_Exec(); } } ===4.gui_frame函数实现GUI图形界面坐标设置 === static int gui_frame(int startx,int starty,int endx,int endy) { GUI_SetColor(GUI_GRAY); GUI_DrawRect(startx,starty,endx,endy); GUI_SetColor(GUI_WHITE); GUI_DrawHLine(starty + 1,startx + 1,endx - 1); GUI_DrawHLine(endy + 1,startx,endx + 1); GUI_DrawVLine(startx + 1,starty + 1,endy - 1); GUI_DrawVLine(endx + 1,starty,endy + 1); return 0; } === 5.GT911写数据函数 === unsigned char GT911_WR_Reg(unsigned short int reg,unsigned char *buf,unsigned char len) { unsigned char i; unsigned char ret=0; i2c_touch.IIC_Start(); i2c_touch.IIC_Send_Byte(GT_CMD_WR); i2c_touch.IIC_Wait_Ack(); i2c_touch.IIC_Send_Byte(reg>>8); i2c_touch.IIC_Wait_Ack(); i2c_touch.IIC_Send_Byte(reg&0XFF); i2c_touch.IIC_Wait_Ack(); for(i=0;i === 6.GT911读数据函数 === void GT911_RD_Reg(unsigned short int reg,unsigned char *buf,unsigned char len) { unsigned char i; i2c_touch.IIC_Start(); i2c_touch.IIC_Send_Byte(GT_CMD_WR); i2c_touch.IIC_Wait_Ack(); i2c_touch.IIC_Send_Byte(reg>>8); i2c_touch.IIC_Wait_Ack(); i2c_touch.IIC_Send_Byte(reg&0XFF); i2c_touch.IIC_Wait_Ack(); i2c_touch.IIC_Start(); i2c_touch.IIC_Send_Byte(GT_CMD_RD); i2c_touch.IIC_Wait_Ack(); for(i=0;i === 7.scan函数:实现读取GT911触摸数据功能。 === * 芯片GT911返回的就是实际的坐标值,比如显示屏的分辨率是480*272,那么返回的就是在这个分辨率范围内的实际坐标值。 int scan(unsigned char mode) { unsigned char buf[4]; unsigned char i=0; unsigned char temp; GT911_RD_Reg(GT_GSTID_REG,&mode,1);//读取触摸点的状态 if(mode&0X80&&((mode&0XF)<6)) { temp=0; GT911_WR_Reg(GT_GSTID_REG,&temp,1);//清标志 } if((mode&0XF)&&((mode&0XF)<6)) { temp=0XFF<<(mode&0XF);//将点的个数转换为1的位数,匹配tp_dev.sta定义 gt911.sta=(~temp); for(i=0;i<5;i++) { if(gt911.sta&(1< ==== 五、 实验步骤 ==== - 把仿真器与iCore4T的SWD调试口相连(直接相连或者通过转接器相连); - 把iCore4T通过Micro USB线与计算机相连,为iCore4T供电; - 将屏幕连接到4.3寸液晶屏底板上,并将液晶屏底板与iCore4T底板通过排线相连。 - 打开Keil MDK 开发环境,并打开本实验工程; - 烧写程序到iCore4T上; - 也可以进入Debug 模式,单步运行或设置断点验证程序逻辑。 ==== 六、 实验现象 ==== 触摸iCore4T(4.3寸TFT_LCD)液晶屏即显示当前触摸位置的坐标值。