| **银杏科技有限公司旗下技术文档发布平台** ||||
|技术支持电话|**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)液晶屏即显示当前触摸位置的坐标值。