STM32F407_多点电容触摸(GT911)驱动

目录标题

  • 前言
  • 1、简单介绍
  • 2、触摸芯片与主机的硬件连接
  • 3、内部寄存器
    • 3.1、控制寄存器(0X8040)
    • 3.2、配置寄存器组(0X8047~0X8100)
    • 3.3、状态寄存器(0x814E)
    • 3.4、坐标寄存器(0x8150-0x8177)
  • 4、初始化流程
    • 4.1、IIC地址选择
    • 4.2、更新GT911寄存器配置
  • 5、触摸点坐标值读取
  • 6、提示
  • 7、代码部分
    • 7.1、gt911.h
    • 7.2、GT911.c

前言

做毕设用到了电容触摸屏,移植了几天内才整好。在网上找到的好多例程都是电容屏、电阻屏都融合到一起去了,对于新手来说,不是太好理解,所以我来分享一下我的认识、例程和学习过程中遇到的问题以及要注意的点。

1、简单介绍

GT911、GT928、GT9147都属于GT9系列非单层多点触控芯片,他们支持的触控点数不同(GT928支持10个点、GT911支持5个点)、驱动和感应通道也可能不同。可是他们的寄存器和IIC通讯时序是相同的,也就是说驱动程序是兼容的。
所以如果是使用的GT9147也可以看看这个文档,整理下思路。

2、触摸芯片与主机的硬件连接

接口介绍
VCC电源
GND
SCL与GT911进行IIC通信的时钟线
SDA与GT911进行IIC通信的数据线
INT当发生触摸时,GT911的INT脚会输出上升/下降沿(内部寄存器可以配置),主机就可以通过外部中断处理去读取触点信息。
RST复位引脚,拉低100us以上,即可复位。正常工作时,应该保持拉高

3、内部寄存器

GT911上电初始化情况,是由其内部FLASH中的若干个寄存器来决定的,我们下面对其中比较重要的进行讲解。

3.1、控制寄存器(0X8040)

通过往里面写入不同的8bit数据。可以使其完成不同的任务。
在这里插入图片描述
如图示,一般的操作是在复位时,先往0X8040里面写2,对其进行软复位,然后判断是否需要对其配置寄存器进行更新,若需要更新,则写入新版本的配置参数(这部分配合着后面来看才能看懂),然后在往0X8040里面写0,结束软复位,后面就能正常读取触摸坐标了。
总结一下:

  • 要更新配置:(一般来说,买到的屏幕商家都已经预先写进去了,不需要更新)
    • 1、往0X8040写2(开始软复位)
    • 2、往0X8047~0X8100写入新的配置寄存器参数
    • 3、往0X8040写0(结束软复位)
    • 4、后面正常读触点坐标
  • 不更新配置:
    • 1、往0X8040写2(开始软复位)
    • 2、往0X8040写0(结束软复位)
    • 3、后面正常读触点坐标

3.2、配置寄存器组(0X8047~0X8100)

在这里插入图片描述
在这里插入图片描述

如上图示,这里共有186个寄存器,用于配置GT9147的各个参数,这些参数对于不同的屏幕也都各有不同。一般买回来的里面呢都自带的有(也就是说,原来就是好用的,不需要再自己进行操作了)

如果你要是不小心把原来的覆盖掉了,就只能再重新写一次了(我在调试过程中就是这样,把其它型号的配置参数写进去了,要命的是我还没有正确的了,最后还是从我同学的一块同款屏幕上将这186个寄存器的值都读出来,又重新写入到我的屏幕的GT911中,才弄好了)

在这样的情况下,你就需要对这些寄存器的一些特性,做些更深入的了解了。

  • 0x8047——这个寄存器中,保存的是当前配置参数的版本号,你新写入配置参数的版本号,必须要比它大或者在相等的情况下,其他参数有变化,否则不会生效。
  • 0x80FF——这里需要写入的是从0x8047到0x80FE之间184个数据和的补码,否则那你写入的配置也不会生效。
  • 0x8100——用于控制是否将配置保存在GT911的FLASH中,写0,则不保存配置,写1则保存配置。

3.3、状态寄存器(0x814E)

寄存器bit7bit6bit5 bit4bit3 bit2 bit1 bit0
0x814Ebuffer状态large detectReserved有效触点个数

我们只看此寄存器的最高位和低四位即可。
最高位表示的Buffer状态,若有数据(有触摸),则Buffer为1‘
低四位表示有效出点的个数,0~5,0表示此时没有触摸。5表示此时有5点触摸
(我们上面提到过gt911最多同时支持五个触控点数)

3.4、坐标寄存器(0x8150-0x8177)

在这里插入图片描述
在这里插入图片描述
如上图所示,我们可以将其分为5组,其分别用来表示5个触点坐标
下面以触点1的坐标数据寄存器为例做具体讲解:

寄存器bit7~0寄存器bit7~0
0x8150触点1X坐标低8位0x8151触点1X坐标高8位
0x8152触点1Y坐标低8位0x8153触点1Y坐标高8位
0x8154触点1触摸尺寸低8位0x8155触点1触摸尺寸高8位

一般只用到触点的x,y坐标,所以只需要读取0X8150-0X8153的数据,组合即可得到触点坐标。其它四组分别是:0X8158、0X8160、0X8168和0X8170等开头的的16个寄存器组成,分别针对触点2~5的坐标。同样GT911也支持寄存器地址自增,我们只需要发送寄存器组的首地址,然后连续读取即可,GT9147会自动地址自增,从而提高读取速度。

4、初始化流程

4.1、IIC地址选择

GT911作为从设备,其地址有两种选择:

7bit地址8bit写地址8bit读地址
0x5D0xBA0xBB
0x140x280x29

其配置方法如下:

  • 将地址配置为0x28/0x29

    • 1、将RST引脚设置为上拉推挽输出模式,将INT引脚设置为上拉输入模式
    • 2、将RST拉低,延时大于1ms
    • 3、将RST拉高,延时大于5ms
    • 4、将INT配置为悬浮输入态,RST维持拉高输出
      在这里插入图片描述
  • 将地址配置为0xBA/0xBB

    • 1、将RST和INT引脚配置为输出模式并拉低
    • 2、延时1ms
    • 3、将RST拉高,延时大于5ms
    • 4、将INT配置为悬浮输入态,RST维持拉高输出
      在这里插入图片描述
      注意:因为我使用的是查询扫描模式,所以没有配置INT引脚的外部中断模式,如果需要,这里也需要配置。

4.2、更新GT911寄存器配置

就像上面3.2说的,如果刚买回来的触摸屏幕,里面应该是本身就有适配此屏幕的参数配置的,这一条就可以省略直接进行下面的4.3,去读取触摸点坐标值。
注:这点尤为关键,因为你非常容易写进去错误的寄存器配置导致原来的配置被覆盖掉,你还不知道原来的配置参数是多少。
如果你真的需要更新它。

  • 1、向命令寄存器(0x8040)写入2,开始软复位
  • 2、把配置参数数组(那186个参数)写入寄存器(0x8047-0x8100).
    • 1)、 0x8047——这个寄存器中,保存的是当前配置参数的版本号,你新写入配置参数的版本号,必须要比它大或者在相等的情况下,其他参数有变化,否则不会生效。
    • 2)、0x80FF——这里需要写入的是从0x8047到0x80FE之间184个数据和的补码,否则那你写入的配置也不会生效。
    • 3)、0x8100——用于控制是否将配置保存在GT911的FLASH中,写0,则不保存配置,写1则保存配置。
  • 3、往向命令寄存器(0x8040)写入0,结束软复位

5、触摸点坐标值读取

当有触摸发生时,GT911会有3个提示:

  • 1、INT会输出上升沿或下降沿信号。(由寄存器配置参数决定)
  • 2、状态寄存器0x814E的最高位(buffer状态位)的值变为1,表示数据已准备好。
  • 3、状态寄存器0x814E的低4位的值会变为触摸点个数,提示有多少个点被按下。

注意:读完坐标后,要把0x814E寄存器清为0,表示坐标点已读。否则GT911会一直输出INT信号,不继续检测触摸。

读取方法:

  • 1、使用INT中断,当发生触摸时,会进入外部中断处理程序,在中断服务中,可以去读取0x8114E中的低四位获取触摸点数,然后再去读去相应寄存器,获取触点坐标,读完后将0x814E寄存器清零。
  • 2、轮询读取0x814E寄存器值,若最高位为1,则通过低四位获取触摸点数,然后去读相应触摸点数的坐标值,读完后将0x814E清零。若最高位为0,则退出,等待下次监测。

6、提示

  • 因为GT911的触摸检测频率小于100HZ,所以我们采用轮询读取时,读取频率设的小于100HZ即可。

7、代码部分

7.1、gt911.h

#ifndef __GT911_H
#define __GT911_H	
#include "sys.h"	

#include "ctiic.h"
#include "Serial.h"
#include "DWT_Delay.h" 
#include "string.h" 

#include "lcd_init.h"
#define TP_PRES_DOWN 0x80  //触屏被按下	  
#define TP_CATH_PRES 0x40  //有按键按下了 
#define CT_MAX_TOUCH  5    //电容屏支持的点数,固定为5点

//触摸屏控制器
typedef struct
{
	uint16_t x[CT_MAX_TOUCH]; 		//当前坐标
	uint16_t y[CT_MAX_TOUCH];		//电容屏有最多5组坐标,电阻屏则用x[0],y[0]代表:此次扫描时,触屏的坐标,用
								//x[4],y[4]存储第一次按下时的坐标. 
	uint8_t  sta;					//笔的状态 
								//b7:按下1/松开0; 
	                            //b6:0,没有按键按下;1,有按键按下. 
								//b5:保留
								//b4~b0:电容触摸屏按下的点数(0,表示未按下,1表示按下)
}_m_tp_dev;

extern _m_tp_dev tp_dev;	 	//触屏控制器在touch.c里面定义
//IO操作函数	 
#define GT_RST    		PBout(9)	//GT911复位引脚
#define GT_INT    		PBin(8)		//GT911中断引脚	
   	
//I2C读写命令	
#define GT_CMD_WR 		0X28     	//写命令
#define GT_CMD_RD 		0X29		//读命令
  
//GT911 部分寄存器定义 
#define GT_CTRL_REG 	0X8040   	//GT911控制寄存器
#define GT_CFGS_REG 	0X8047   	//GT911配置起始地址寄存器
#define GT_CHECK_REG 	0X80FF   	//GT911校验和寄存器
#define GT_PID_REG 		0X8140   	//GT911产品ID寄存器

#define GT_GSTID_REG 	0X814E   	//GT911当前检测到的触摸情况
#define GT_TP1_REG 		0X8150  	//第一个触摸点数据地址
#define GT_TP2_REG 		0X8158		//第二个触摸点数据地址
#define GT_TP3_REG 		0X8160		//第三个触摸点数据地址
#define GT_TP4_REG 		0X8168		//第四个触摸点数据地址
#define GT_TP5_REG 		0X8170		//第五个触摸点数据地址  
 
void GT911_Send_Cfg(uint8_t mode);                           /*更新GT911配置参数*/
uint8_t GT911_WR_Reg(uint16_t reg,uint8_t *buf,uint8_t len); /*向GT911写入一次数据*/
void GT911_RD_Reg(uint16_t reg,uint8_t *buf,uint8_t len);    /*从GT911读出一次数据*/
uint8_t GT911_Init(void);                                    /*初始化GT911触摸屏*/
uint8_t GT911_Scan(uint8_t mode);                            /*扫描触摸屏(采用查询方式)*/
#endif

7.2、GT911.c

#include "gt911.h"


_m_tp_dev tp_dev;				


/*五个触摸点的数据寄存器起始地址*/
const uint16_t GT911_TPX_TBL[5]={GT_TP1_REG,GT_TP2_REG,GT_TP3_REG,GT_TP4_REG,GT_TP5_REG};

//GT911配置参数表--适用于耀元鸿2.8寸IPS屏幕。不同尺寸屏幕配置参数会有区别
const uint8_t GT911_CFG_TBL[]=
{ 
0x61,0xf0,0x00,0x40,0x01,0x05,0x35,0x00,0x02,0x08,
0x1e,0x08,0x50,0x3c,0x0f,0x05,0x00,0x00,0x00,0x00,
0x50,0x00,0x00,0x18,0x1a,0x1e,0x14,0x87,0x27,0x0a,
0x4b,0x4d,0xd3,0x07,0x00,0x00,0x00,0x02,0x32,0x1c,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x32,0x00,0x00,

0x2a,0x32,0x64,0x94,0xd5,0x02,0x07,0x00,0x00,0x04,
0xa5,0x35,0x00,0x91,0x3d,0x00,0x80,0x46,0x00,0x70,
0x51,0x00,0x63,0x5d,0x00,0x63,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,

0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x14,0x12,0x10,0x0e,0x0c,0x0a,0x08,0x06,
0x04,0x02,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0x00,0x02,0x04,0x06,0x08,0x0a,0x0c,0x24,

0x22,0x21,0x20,0x1f,0x1e,0x1d,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,
};  

/*
* 函数名称: GT911_Send_Cfg
* 功能描述: 更新GT911配置参数
* 传入参数: mode:0,参数不保存到flash
*                1:参数保存到flash
*   返回值: 0,成功;1,失败.
*/
void GT911_Send_Cfg(uint8_t mode)
{
	uint8_t buf[2];
	uint8_t i=0;
	buf[0]=0;
	buf[1]=mode;	//是否写入到GT911 FLASH?  即是否掉电保存
	for(i=0;i<sizeof(GT911_CFG_TBL);i++)buf[0]+=GT911_CFG_TBL[i];//计算校验和
    buf[0]=(~buf[0])+1;
	GT911_WR_Reg(GT_CFGS_REG,(uint8_t*)GT911_CFG_TBL,sizeof(GT911_CFG_TBL));//发送寄存器配置
	GT911_WR_Reg(GT_CHECK_REG,buf,2);//写入校验和,和配置更新标记
} 


/*
* 函数名称: GT911_WR_Reg
* 功能描述: 向GT911写入一次数据
* 传入参数: reg:起始寄存器地址
*           buf:数据缓缓存区
*           len:写数据长度	
*   返回值: 0,成功;1,失败.
*/
uint8_t GT911_WR_Reg(uint16_t reg,uint8_t *buf,uint8_t len)
{
	uint8_t i;
	uint8_t ret=0;
	CT_IIC_Start();	
 	CT_IIC_Send_Byte(GT_CMD_WR);   	//发送写命令 	 
	CT_IIC_Wait_Ack();
	CT_IIC_Send_Byte(reg>>8);   	//发送高8位地址
	CT_IIC_Wait_Ack(); 	 										  		   
	CT_IIC_Send_Byte(reg&0XFF);   	//发送低8位地址
	CT_IIC_Wait_Ack();  
	for(i=0;i<len;i++)
	{	   
    	CT_IIC_Send_Byte(buf[i]);  	//发数据
		ret=CT_IIC_Wait_Ack();
		if(ret)break;  
	}
    CT_IIC_Stop();					//产生一个停止条件	    
	return ret; 
}
 
/*
* 函数名称: GT911_RD_Reg
* 功能描述: 从GT911读出一次数据
* 传入参数: reg:起始寄存器地址
*           buf:数据缓缓存区
*           len:读数据长度	
*   返回值: 无
*/
void GT911_RD_Reg(uint16_t reg,uint8_t *buf,uint8_t len)
{
	uint8_t i; 
 	CT_IIC_Start();	
 	CT_IIC_Send_Byte(GT_CMD_WR);   //发送写命令 	 
	CT_IIC_Wait_Ack();
 	CT_IIC_Send_Byte(reg>>8);   	//发送高8位地址
	CT_IIC_Wait_Ack(); 	 										  		   
 	CT_IIC_Send_Byte(reg&0XFF);   	//发送低8位地址
	CT_IIC_Wait_Ack();  
 	CT_IIC_Start();  	 	   
	CT_IIC_Send_Byte(GT_CMD_RD);   //发送读命令		   
	CT_IIC_Wait_Ack();	   
	for(i=0;i<len;i++)
	{	   
    	buf[i]=CT_IIC_Read_Byte(i==(len-1)?0:1); //发数据	  
	} 
    CT_IIC_Stop();//产生一个停止条件    
} 

/*
* 函数名称: GT911_Init
* 功能描述: 初始化GT911触摸屏
* 传入参数: 无
*   返回值: 0,初始化成功;1,初始化失败
*/
 
uint8_t GT911_Init(void)
{
	
//	uint8_t zancun[190]; /*测试使用*/
//	uint8_t i;
//	uint8_t z;
	
	uint8_t temp[5]; 
	GPIO_InitTypeDef  GPIO_InitStructure;	
	
  RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE);//使能GPIOB,C时钟

  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8 ;//PB1设置为上拉输入
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN;//输入模式
  GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;//推挽输出
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;//100MHz
  GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;//上拉
  GPIO_Init(GPIOB, &GPIO_InitStructure);//初始化
		
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;//PC13设置为推挽输出
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;//输出模式
	GPIO_Init(GPIOB, &GPIO_InitStructure);//初始化	

	
	
	CT_IIC_Init();      	//初始化电容屏的I2C总线  
	GT_RST=0;				//复位
	DWT_DelayMS(1);
 	GT_RST=1;				//释放复位		    
	DWT_DelayMS(5); 
	

	
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN;
  GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
	GPIO_Init(GPIOB, &GPIO_InitStructure);//初始化	
	
	DWT_DelayMS(10);  
	GT911_RD_Reg(GT_PID_REG,temp,4);//读取产品ID
	temp[4]=0;
	printf("CTP ID:%s\r\n",temp);	//打印ID
	if(strcmp((char*)temp,"911")==0)//ID==9147
	{
		temp[0]=0X02;			
		GT911_WR_Reg(GT_CTRL_REG,temp,1);//软复位GT911
		GT911_RD_Reg(GT_CFGS_REG,temp,1);//读取GT_CFGS_REG寄存器
		
		
		/*可用来读取GT911本地0x8047-0x80FE的寄存器参数*/
/*
		GT911_RD_Reg(GT_CFGS_REG,(uint8_t *)zancun,186);		 //读取出配置寄存器值
		for(i=0;i<186;i++)
		{
		    if(i<185){z+=zancun[i];}
			  if(i==185){printf("校验值1:%x\r\n",z);}
				printf("%x,",zancun[i]);                   //打印出配置寄存器值
		}
*/
		
		if(temp[0]<0X62)//默认版本比较低,需要更新flash配置
		{
			printf("Default Ver:%x\r\n",temp[0]);
//			GT911_Send_Cfg(1);//更新并保存配置
		}
		DWT_DelayMS(10);
		temp[0]=0X00;	 
		GT911_WR_Reg(GT_CTRL_REG,temp,1);//结束复位   
		return 0;
	} 
	return 0;
}



/*
* 函数名称: GT911_Scan
* 功能描述: 扫描触摸屏(采用查询方式)
* 传入参数: mode:0,正常扫描.
* 传出参数: 无
*   返回值: 当前触屏状态.0,触屏无触摸;1,触屏有触摸
*/
uint8_t GT911_Scan(uint8_t mode)
{
	uint8_t buf[4]; /*触屏坐标信息存储缓冲区*/
	uint8_t i=0;
	uint8_t res=0;  /*返回触摸状态*/
	uint8_t temp;   
	uint8_t tempsta;  /*保存当前触摸状态*/
 	static uint8_t t=0;//控制查询间隔,从而降低CPU占用率   
	t++;
	
	if((t%10)==0||t<10)//空闲时,每进入10次CTP_Scan函数才检测1次,从而节省CPU使用率
	{
		GT911_RD_Reg(GT_GSTID_REG,&mode,1);	//读取触摸点的状态  
		temp=0;
		GT911_WR_Reg(GT_GSTID_REG,&temp,1);//清标志 			
		if((mode&0XF)&&((mode&0XF)<6)) 
		{
			temp=0XFF<<(mode&0XF);		//将点的个数转换为1的位数,匹配tp_dev.sta定义 
			tempsta=tp_dev.sta;			//保存当前的tp_dev.sta值
			tp_dev.sta=(~temp)|TP_PRES_DOWN|TP_CATH_PRES; 
			tp_dev.x[4]=tp_dev.x[0];	//保存触点0的数据
			tp_dev.y[4]=tp_dev.y[0];
			for(i=0;i<5;i++)
			{
				if(tp_dev.sta&(1<<i))	//触摸有效?
				{
					GT911_RD_Reg(GT911_TPX_TBL[i],buf,4);	//读取XY坐标值  
					tp_dev.y[i]=240-(((uint16_t)buf[1]<<8)+buf[0]);
					tp_dev.x[i]=((uint16_t)buf[3]<<8)+buf[2];
					printf("x[%d]:%d,y[%d]:%d\r\n",i,tp_dev.x[i],i,tp_dev.y[i]);
				}			
			 } 
			res=1;
			if(tp_dev.x[0]>LCD_W||tp_dev.y[0]>LCD_H)//非法数据(坐标超出了)
			{ 
				if((mode&0XF)>1)		//有其他点有数据,则复第二个触点的数据到第一个触点.
				{
					tp_dev.x[0]=tp_dev.x[1];
					tp_dev.y[0]=tp_dev.y[1];
					t=0;				//触发一次,则会最少连续监测10次,从而提高命中率
				}
				else					//非法数据,则忽略此次数据(还原原来的)  
				{
					tp_dev.x[0]=tp_dev.x[4];
					tp_dev.y[0]=tp_dev.y[4];
					mode=0X80;		
					tp_dev.sta=tempsta;	//恢复tp_dev.sta
				}
			 }
			 else t=0;					//触发一次,则会最少连续监测10次,从而提高命中率
		}
	}
	if((mode&0X8F)==0X80)//无触摸点按下
	{ 
		if(tp_dev.sta&TP_PRES_DOWN)	//之前是被按下的
		{
			tp_dev.sta&=~(1<<7);	//标记按键松开
		}
		tp_dev.x[0]=0xffff;
		tp_dev.y[0]=0xffff;
		tp_dev.sta&=0XE0;	//清除点有效标记	
	} 	
	if(t>240)t=10;//重新从10开始计数
	return res;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/464282.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

OpenHarmony—应用UX设计原则

设计原则 当为多种不同的设备开发应用时&#xff0c;有如下设计原则&#xff1a; 差异性 充分了解所要支持的设备&#xff0c;包括屏幕尺寸、交互方式、使用场景、用户人群等&#xff0c;对设备的特性进行针对性的设计。 一致性 除了要考虑每个设备的特性外&#xff0c;还…

修复 error Delete `␍` prettier/prettier 错误

修复 error Delete ␍ prettier/prettier 错误 问题背景报错信息报错原因解决办法修改CRLF----针对单个文件yarn run lint --fix 一键修复&#xff08;官方提供&#xff09; 问题背景 今天在使用 openapi 自动生成前端接口代码的时候&#xff0c;爆了一个类似 eslint 规范的错…

AtCoder Beginner Contest 345 A - E 题解

A - Leftrightarrow 思路 判断第一个字符是否为&#xff0c;最后一个字符是否为&#xff0c;都满足的话&#xff0c;再判断中间字符是否都为 代码 #include<iostream> using namespace std; #define int long longbool check(string s){int ns.size();if(s[0]!<) …

Elasticsearch 索引库操作 文档操作

索引库就类似数据库表&#xff0c;mapping映射就类似表的结构。要向es中存储数据&#xff0c;必须先创建“库”和“表”。 mapping映射属性 mapping是对索引库中文档的约束&#xff0c;常见的mapping属性包括&#xff1a; type&#xff1a; 字段数据类型&#xff0c;常见的简…

Gogs 创建新的仓库并提交代码

Gogs 创建新的仓库并提交代码 1. 登录2. 仓库 -> 我的仓库3. 创建新的仓库4. 仓库5. Copy6. 公开代码​7. 提交成功 Gogs - gitReferences Gogs 是一款极易搭建的自助 Git 服务。 1. 登录 2. 仓库 -> 我的仓库 3. 创建新的仓库 4. 仓库 5. Copy 6. 公开代码 strongfo…

SpringBoot(RESTful,统一响应结构,输出日志,增删改查功能,分页功能,批量删除,常见bug)【详解】

目录 一、准备工作 1. 前后端分离开发流程 2. 开发规范 1.RESTful请求风格 2.统一响应结果 3.代码中输出日志 二、部门管理&#xff08;增删改查功能&#xff09; 1. 查询部门列表 2. 删除部门 3. 新增部门 4. 修改部门 三、员工管理&#xff08;分页功能和批量删除…

数字后端 EDA 软件分享

数字后端 EDA 软件分享 推荐这几家的EDA工具吧&#xff0c;虽说我也支持国产工具&#xff0c;但是我还是选择了这几家的工具 apache cadence mentor synopsys 下图我现在用的eda环境&#xff0c;利用网上的资源&#xff0c;自己独立在vmware上搭建好的EDA环境 除去pdk&#…

MySQL语法分类 DQL(6)分页查询

为了更好的学习这里给出基本表数据用于查询操作 create table student (id int, name varchar(20), age int, sex varchar(5),address varchar(100),math int,english int );insert into student (id,name,age,sex,address,math,english) values (1,马云,55,男,杭州,66,78),…

Matlab/simulink基于模糊PID智能控制的温度控制系统建模仿真

参考文献 Matlab/simulink基于模糊PID智能控制的温度控制系统建模仿真 该系统主要对某小区换热站的温度控制策略和控制方案进行了设计&#xff0c;其设计内 容主要包括三部分。首先是基于模糊PID智能控制的温度控制系统设计。在温度控制 算法方面&#xff0c;该设计于传统的P…

MySQL实战:监控

监控指标 性能类指标 名称说明QPS数据库每秒处理的请求数量TPS数据库每秒处理的事务数量并发数数据库实例当前并行处理的会话数量连接数连接到数据库会话的数量缓存命中率Innodb的缓存命中率 功能类指标 名称说明可用性数据库是否正常对外提供服务阻塞当前是否有阻塞的会话…

操作系统:malloc与堆区内存管理

malloc是函数而不是系统调用&#xff0c;他的底层是同调调用brk和mmap这两个系统调用实现功能的&#xff0c;具体选择brk还是mmap要看申请的空间大小以及malloc中的阈值&#xff08;一般是128kb&#xff09; 注意申请的空间只有使用才会触发缺页中断映射到物理内存 不理解的话先…

搞机笔记 MI8 dipper

刷回MIUI 之前刷了 lineage-19.1-20220728-nightly-dipper-signed 基于安卓12&#xff0c;实现了以下功能 TWRPmagisk & ROOTmicroG 退回MIUI的原因有&#xff1a; lineage 墓碑 管不住APP后台&#xff0c;太卡了MIUI提供了3GB的虚拟内存lineage 不支持人脸识别lineag…

小蓝的漆房——算法思路

题目链接&#xff1a;1.小蓝的漆房 - 蓝桥云课 (lanqiao.cn) 本题只要是通过枚举的方法&#xff0c;算出涂成每一种颜色所需的天数&#xff0c;最后在所有天数中找出最小值&#xff08;由题可知&#xff0c;最多只有60种颜色&#xff0c;所以可以尝试算出每种颜色所需的时间&am…

在雄安新区买新房要注意什么?有哪些注意事项?

雄安新区新建住宅均价每平方米11735元起&#xff0c;二手房每平方米8950元起。 整体价格非常有优势。 雄安新区房价走势与区域发展直接相关。 而且&#xff0c;雄安新区已经成立五周年了。 2022年&#xff0c;雄安新区多项重点项目将陆续竣工。 雄安新区城市基础设施建设已初具…

Spring注解开发(Spring学习笔记六)

1、在Spring4之后&#xff0c;要使用注解开发&#xff0c;必须保证aop包的导入 2、使用注解需要导入context约束&#xff0c;增加注解的支持(没有注解和支持注解是使用不了的) <?xml version"1.0" encoding"UTF-8"?> <beans xmlns"http:/…

用尾插的思路实现 “合并两个有序链表”

一、题目 将两个升序链表合并为一个新的 升序 链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。 示例 1&#xff1a; 输入&#xff1a;l1 [1,2,4], l2 [1,3,4] 输出&#xff1a;[1,1,2,3,4,4]示例 2&#xff1a; 输入&#xff1a;l1 [], l2 [] 输出&#…

二. CUDA编程入门-CUDA中的线程与线程束

目录 前言0. 简述1. 执行一下我们的第一个CUDA程序2. CUDA中的grid和block3. block和thread的遍历(traverse)4. nvcc编译器5. Makefile部分6. 执行我们的第二个CUDA程序7. Makefile添加的部分总结参考 前言 自动驾驶之心推出的 《CUDA与TensorRT部署实战课程》&#xff0c;链接…

[C语言]——VS实用调用技巧

一.什么是bug bug本意是“昆⾍”或“⾍⼦”&#xff0c;现在⼀般是指在电脑系统或程序中&#xff0c;隐藏着的⼀些未被发现的缺陷或问题&#xff0c;简称程序漏洞。 “Bug” 的创始⼈格蕾丝赫柏&#xff08;Grace Murray Hopper&#xff09;&#xff0c;她是⼀位为美国海军⼯…

MQ组件之RabbitMQ学习

MQ组件之RabbitMQ入门 同步调用和异步调用 在微服务架构中&#xff0c;服务之间的调用有同步调用和异步调用两种方式。 我们使用OpenFeign去调用是同步调用&#xff0c;同步调用的缺点很明显&#xff0c;在下图的场景中&#xff0c;支付完成后需要调用订单服务、仓库服务、短…

MyBatisPlus 之二:SpringBoot 快速整合 MyBatisPlus 详细步骤

SpringBootMyBatisPlus Spring Boot 结合 MyBatis Plus 是一种常见的 Java 后端开发框架组合&#xff0c;能够快速构建高性能、易于维护的 CRUD 应用程序。以下是 Spring Boot 集成 MyBatis Plus 的基本步骤 一、快速体验 注意&#xff1a;下面版本 idea2020 SpringBoot2.* …