热释电矢量传感器设计

news2024/11/17 15:26:28

 1  概述

使用4个热释电传感器组成一个2X2的矩阵。通过曲线的相位差、 峰峰值等特征量来计算相关信息。本文使用STM32单片机设计、制作了热释电传感器矩阵;使用C#.NET设计了上位机软件。为以上研究做了试验平台。

2 硬件电路设计

2.1  热释电传感器介绍

    热释电红外探测器的信号产生原理主要是利用热释电材料的热释电效应。热释电材料是一种压电材料,是不具有中心对称性的晶体(如钽酸锂、硫酸三甘肽等),当这类晶体发生温度变化时使得晶体内部的原子位置变化,导致了晶体某一方向产生表面极化电荷的现象,会使晶体两端产生一个微小的电压差。如图2.1 示意了热释电效应的基本原理。如果当温度保持不变的时候,该电压会因为与空气中离散的荷中和而消失掉,所以只有温度场变化时热释电传感器才会敏感变化。

图2.1热释电效应

当热释电材料表面受到经菲涅尔透镜调制过的人体红外辐射照射后,晶体表面温度便会上升𝛥𝑇,使垂直于自发极化轴方向的晶体单位表面上的电荷𝛥𝑞发生自极化,晶体的电容值表示为𝐶,两电极之间的电压便可表示为𝛥𝑉 = 𝛥𝑞/𝐶。通过检测这一变化微弱的电压信号可以获取温度场变化趋势。本文采用D203s型号传感器,其等效电路如下图所示。当移动人体穿过其感应区时,热释电传感器输出信号反应了各热释电元件接收热辐射的通量变化量之差。连续时刻,当两片热释电元件接收的热辐射量差值不同时,便会产生一个变化的电压输出信号。

D203s等效电路

当人体沿一定方向、一定距离移动时将产生电压输出信号。图中可以看出,热释电探头的两片热释电元件分别对应两个柱形视场区域并且将其感应视场划分为盲区和高敏感区。当人体穿过其中一个敏感区域时,便会对相应的热释电元件产生一个阶跃输入,从而通过后续电路产生热释电压;而当人体穿过两敏感区的中间盲区时,由于人体红外能不能辐射到热释电元件,导致不会产生对应的输出电压。因此可以根据传感器输出时域电压信号序列,寻找一些可用特征以实现人体的检测、定位与识别。其中传感器输出信号与移动速度、距离等之间的关系如下所示:

其中 f 为输出信号的频率(HZ),Vb 为目标移动速度(m/s),fb为菲涅尔透镜

焦距(mm), s 为敏感元件大小(mm), L为目标距传感器距离(m)。

2.2 工作原理示意图

2.2 采集电路设计

根据 PIR 传感器的工作原理,当人体走过或者在菲涅尔透镜明暗相间的区域运动时,会使热释电元件表面上产生微弱的电流,然后由电路转换为电压信号输出,这个电压信号的幅值非常小,大概在 1mV 左右。信号幅值太小会导致容易受到外界环境的干扰,这样采集的数据就没有分析的意义。为了减小实验误差增加数据可靠性,设计了如下图所示的信号调理电路。

图2.3信号调理电路

   传感器在供电时需要10K限流电阻,输出需要47K的匹配电阻。在经过RC滤波电路后,经过两级放大电路放大,本文采用LM358运算放大器组成放大电路。一级放大和二级放大电路间采用电容耦合,这样可以去掉传感器输出的直流分量。第二级放大电路倍数可调,通过测试选取合适放大倍数。第二级放大电路参考电压设置在1.65V,主要是因为后去ADC为0~3.3V输入。通过信号调理电路可以得到0~3.3V的电压信号,方便ADC转换。

2.3单片机电路

采用DC5V供电,电路内需要供电的芯片有3.3V和5V两种。其中D203S及其信号处理部分、蜂鸣器采用5V供电,单片机、通信芯片等采用3.3V供电。为方便操作电源输如后增加自锁电源开关,开关后设计电容滤波来提高5V电压的精度、减少文波干扰。3.3V电源使用lm1117-3.3V电源芯片,该芯片可提供500ma的稳定电流,足够系统使用。如图2.4(a)为电源电路部分。设计电源指示灯一个,用于检测3.3V电源工作与否。

单片机最小系统如图2.4(b)所示,包括了晶振电路、boot电路、以及ADC电源部分。同时设计了复位电路,通过电阻、电容的充放电时间来实现单片机的复位过程。为了方便观测程序的运行与否设计了可控LED指示灯一个,通过定时器控制闪烁提示使用者系统健康状况。单片机采用SW调试方式,该方式仅需要4跟线就可完成程序的烧写、在线调试等功能。设计了4个独立按键,用于按键操作。同时设计了一个有源蜂鸣器电路,用于产生提示、告警声音。

(a)电源电路

(b)单片机电路

(c)外围电路

(d)按键与蜂鸣器

图2.4 单片机系统电路设计

  2.4串行通信电路

串行通信指数据是一位一位按顺序传送的通信方式,相对于并行通信,其突出优点是只需要一对传输线,缺点是传输速度较低。串行通信的传输方向通常有三种,单工、半双工和全双工。单向顾名思义只允许数据向一个方向传输;半双工允许两个方向传输,但在同一时刻只能往一个方向传输;全双工则允许双向同时传输数据。

串行通信有两种基本通信方式,异步通信和同步通信。异步通信不需要传输时钟信号,通信双方的时钟是各自独立的,但双方必须是相同的通信速率和数据格式,即相同的通信协议。其帧格式一般为:起始位+数据位+奇偶校验位+停止位。同步通信需要时钟同步,双方的数据收发是同时进行的。同步通信中一般字符与字符之间没有间隙,相对于异步通信不需要起始位和停止位,只需要同步信号和同步开始时的同步字符。波特率也称码元速率,为单位时间内传输符号的个数或载波调制状态改变次数,单位是Bd(Baud)。比特率又称码率,表示单位时间内传输的比特数,单位是bps(bit/s)。比特率和波特率的转换关系与信号的调制方式有关,通常为:比特率=波特率*调制位数(调制位数即码元位数)。在异步串行通信中,由于采用二进制编码,码元位数为一,通常情况下比特率=波特率。

串行异步通信

RS-232是美国电子工业联盟制定的串行数据通信接口标准,原始编号全称是EIA-RS-232(简称RS232),它被广泛用于DCE(Data Communication Equipment ) 和 DTE(Data Terminal Equipment) 之间的连接。DCE可以理解为数据通信端,比如modem设备;DTE可以理解为数据终端,比如电脑。最早的台式电脑都会保留9针的232接口,用于串口通信,目前基本被USB接口取代。现在RS232接口常用于仪器仪表设备,PLC以及嵌入式领域当作调试口来使用。图2.5给出了本文设计的RS232接口电路,为了调试方便保留了TTL电平接口(P2)。

图2.5通信电路

PCB设计

3  软件设计

软件由传感器系统软件和上位机软件组成,两个软件间通过异步串行通信进行数据交互。

3.1单片机软件设计

单片机软件架构如下图所示:包括驱动层,数据层和逻辑控制层。(具体源代码参见附录 单片机程序源码)

单片机软件设计流程如下图所示。首先初始化,然后通过定时器定时循环,采集4个热释电传感器数据,然后通过串口发送给上位机。同时预留了4个按键和一个蜂鸣器用于后续工作储备。

主函数代码,其它详见附录。

// 主函数 程序从这里开始
int main(void)
{
	u8 i=0,k=0;
	u8 sum;//发送数据的校验
	//串口有关变量
	u8 number=0;
	u8 State1=0x7F;
	u8 State2=0x0F;

	/*通信状态有关变量*/
	//接收标志
	u8  nGotTDZHT=0;
	u16 nBufTD=0;
	u8  nGotTDZHTBY=0;
	u16 nBufTDBY=0;
	 
	//主控计算机接收标志
	u8  nGotMPC=0;
	u16 nBufMPC=0;	
	//串口2的一些变量初始化	
	Inform_OUTPUT.DATA.Frame_Head1=0xAA;
	Inform_OUTPUT.DATA.LEN=14;
	Inform_OUTPUT.DATA.state1=State1;
	Inform_OUTPUT.DATA.state2=State2;
		
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
	delay_init(168);  
	LED_Init();//LED初始化
	// 定时器初始化
	TIM3_Int_Init(1000-1,168-1);
  	RS422_Init(115200);//初始化串口2用于连接工控机

	DMA1_Config(DMA1_Stream6,DMA_Channel_4,(u32)&USART2->DR,(u32)BUF2,SENTDATA_LEN);//串口2DMA初始化

  	Adc_Init();
	delay_us(2000);
	delay_ms(100);
	Beep=0;//关闭beep	
	while(1)
	{
		//接收到工控机数据(预留)
		if(New_PC==1) 
		{
			New_PC=0;
			nGotMPC=5;
			nBufMPC++;
			State2=State2|0X01;
		}
		if(TIME_on==1) //控制周期时间到,进行ADC和数据发送
		{
			TIME_on=0;
			//接收MIPC监控
			if(nGotMPC>0)
			{
				nGotMPC--;
				State2=State2|0X01;
			}
			else
			{
				State2=State2&0XFC;
			}
			// 读取ADC获得传感器采样值
			getAdcValues();
			


			i=i+1;
			if(i==50) //控制D1亮
			{ 
				i=0;
			  LED1=!LED1;
			}
			

			
			//串口2,给工控机发送数据
			Inform_OUTPUT.DATA.Sonser1Value=AdcValue[0];
			Inform_OUTPUT.DATA.Sonser2Value=AdcValue[1];
			Inform_OUTPUT.DATA.Sonser3Value=AdcValue[2];
			Inform_OUTPUT.DATA.Sonser4Value=AdcValue[3];	

 
			
			number++;
			number=number%16;
			Inform_OUTPUT.DATA.number=number<<4;	
	

			
    	 	sum=0;
	     	for(k=1;k<SENTDATA_LEN;k++)//计算校验和
	    	{
		      	if(k==3) continue;
				sum += Inform_OUTPUT.ARRAY[k];
	     	}
		   	Inform_OUTPUT.DATA.checksum=sum;
			// 发送数据
	     	memcpy(BUF2,&Inform_OUTPUT,SENTDATA_LEN);
		   	DMA_ClearFlag(DMA1_Stream6,  DMA_FLAG_TCIF6);//   
       		MYDMA_TxEnable(DMA1_Stream6,SENTDATA_LEN,USART2); 
							
		}		
		else
		{
			
		}
	}

}

3.2  上位机软件设计

C#是一种高级编程语言,当今主流开发语言占有率排名前五,该语言由微软2000年推出、面世,被微软誉为.NET平台最佳编程语言。C#以.NET类库为基础,是兼顾系统开发与应用程序开发的最佳语言。继承了C/C++简明的编程语法,封装了大多数C++类库。

C#.NET可以编写四类应用程序:

(1)桌面应用程序,主要包括Winform和WPF。二者都是优秀的桌面解决方案首选。Winform的使用者居多,主要因为Winform控件较丰富,其他语言也都用相应的winform开发环境,转行C#后选择Winform入手较快。

(2)Windows Store 应用程序。主要应用于移动、触摸设备的开发。

(3)Web应用程序。通过Web浏览器可以查看的Web页面,如ASP.NET。

    (4)WCF服务。一种灵活的分布式应用程序解决方案,可以通过局域网、广域网在各种操作系统间传递任何数据。

本文将使用Visual Studio 2010和C#语言开发一款基于.NET的winform应用程序。根据系统需求本文将针对应用程序在以下几个方面展开研究:

(1)用户系统

(2)可视化界面

(3)通信系统

(4)数据库系统

应用程序主题框架如下图所示:

考虑到程序的运行效率,将采用多线程方案。在windows系统中每一个应用程序都是一个独立的进程,进程之间不能共享资源。和进程类似,每一个进程中,独立运行的程序片段叫做线程,线程间可以共享本进程中的公共资源。每个线程间是并列关系,在CPU资源充足的情况下,他们是并行运行的。

多线程可以提高应用程序的响应。特别是复杂的图形界面,如果应用程序在等待某一资源,不会按时处理图形界面,这将导致图形界面出现卡顿。如果此时采用多线程技术,将等待处理交给后台线程处理,这样等待时间过长时,就不会影响图形界面的更新。

C#通过 System.Threading.Thread类实现线程的创建和管理。创建一个线程:

    Thread WriteLogThread = new Thread(new ThreadStart(WritingLog));

WriteLogThread.Start();

    其中线程名 WriteLogThread,线程函数 WritingLog。WriteLogThread.Start()将开启线程,线程启动后将调用WritingLog()函数。我将在此函数中写线程要执行的程序。具体使用请见CSDN Thread类。

3.2.1 曲线图界面

GDI全称Graphics Device Interface(图形设备接口),主要负责Window系统上的图形和图像输出,开发人员利用其后续版本GDI+内置函数可以方便在设备处理和动态显示图形图像。GDI+提供的主要功能包含二维几何图形的处理、图形图像显示、排版等。System. Drawing. dll程序集中就已经封装了GDI+的功能,在开始使用GDI+类时,需在项目工程中添加System. Drawing. dll的引用,通过GDI+技术程序员可以编写与图形设备进行交互的Windows或Web图形应用程序,应用程序与图形设备之间不能直接通信,而GDI+库的作用就是将程序发送的数据转换并传递给设备。

通过GDI+提供的API函数可以实现曲线图的绘制。本文使用GDI+、checkbox等控件实现了曲线图绘制。如下图所示,具有多种颜色的曲线图,曲线图上部为曲线名称(图例),向下有四行数字分别是鼠标当前值,圈取区间最大、最小以及平均值。改曲线图可以完好的显示出实时变化的传感器曲线和各项计算结果,有助于传感器数据的理解与应用。

3.2.2通信程序

软件通过SerialPort实现异步串行通讯。

由于串口不知道数据何时到达,因此有线程实时读串口和事件触发方式两种串口数据的读取方法。实质事件方式也是在一个独立线程中处理的。

串口的初始化如下:

建立串口处理事件:

serialPort1.DataReceived +=

 new SerialDataReceivedEventHandler(this.serialPort1_DataReceived);

开启串口:

serialPort1.PortName = toolStripComboBox1.Text;

     serialPort1.BaudRate = 115200;

serialPort1.Open();

串口接收处理:通过接收中断处理数据,中断函数如下所示,其中数据处理也在其中。

   

private void serialPort1_DataReceived(object sender, SerialDataReceivedEventArgs e)

        {

            int i=0;

            if(portOpen)

            nbyte2rec = serialPort1.BytesToRead;



            while (nbyte2rec >= 18&&portOpen)

            {

                int res = serialPort1.ReadByte();

                if (res == 0xAA)

                {

                    nRecBuf++;

                    if (nBuf < 15) nBuf++; else nBuf = 0;

                    //recbuffer[0] = 0xAA;

                    serialPort1.Read(recbuffer, 1, 18);

                    // byte[] cheak = BytesCheck.GetCRC16ByPoly(recbuffer,0x0000, 0x8005, 0x0000,false,false,true, 1, 16);//0x8005

                    sum = recbuffer[1] + recbuffer[2];

                    for ( i = 4; i < 18; i++)

                    {

                        sum += recbuffer[i];

                    }

                    sum &= 0xFF;

                    if (sum != recbuffer[3])

                    {

                        nErrBuf++;



                    }

                    this.nGot = 10;

                    _nBuf = recbuffer[2] >> 4;

                    if (frist)

                    {

                        frist = false;

                        RecFirstTime = DateTime.Now;

                        nBuf = _nBuf;

                    }

                    else

                    {

                        if (nBuf != _nBuf)

                        {

                            if (_nBuf - nBuf < 0)

                            {

                                nLoseBuf += _nBuf - nBuf + 16;

                            }

                            else

                            {

                                nLoseBuf += _nBuf - nBuf;

                            }

                            nBuf = _nBuf;

                        }

                    }

                    this.DataLen = recbuffer[1];

                    nGroup = recbuffer[2] & 0x0F;

                    if (nGroup == 0)

                    {

                        //Sovalue[0] = BitConverter.ToUInt16(recbuffer, 4);

                        //Sovalue[1] = BitConverter.ToUInt16(recbuffer, 6);

                        //Sovalue[2] = BitConverter.ToUInt16(recbuffer, 8);

                        //Sovalue[3] = BitConverter.ToUInt16(recbuffer, 10);

                        RunTim=(DateTime.Now-StartTime).TotalSeconds;

                        for (i = 0; i < 4; i++)

                        {

                            Sovalue[i] =Math.Min(4095, (int)BitConverter.ToUInt16(recbuffer, 4+i*2));



                           



                        }

                        RDSoValues[0] = 0.05F * Kso[0] * (Sovalue[1] - D0so[0]) + 0.95F * RDSoValues[0];

                        RDSsum[0] = RDSoValues[0];

                        RDSoValues[1] = 0.05F * Kso[1] * (Sovalue[0] - D0so[1]) + 0.95F * RDSoValues[1];

                        RDSsum[1] = RDSoValues[1];

                        RDSoValues[2] = 0.05F * Kso[2] * (Sovalue[2] - D0so[2]) + 0.95F * RDSoValues[2];

                        RDSsum[2] = RDSoValues[2];

                        RDSoValues[3] = 0.05F * Kso[3] * (Sovalue[3] - D0so[3]) + 0.95F * RDSoValues[3];

                        RDSsum[3] = RDSoValues[3];

                        coudis(RDSoValues);

                        //dis

                        drawlinesControl1.Lines[0].Add(RDSoValues[0]);

                        drawlinesControl1.Lines[1].Add(vuVpp[0]);

                        drawlinesControl1.Lines[2].Add(dis[0]*1000);



                        drawlinesControl1.Lines[3].Add(RDSoValues[1]);

                        drawlinesControl1.Lines[4].Add(vuVpp[1]);

                        drawlinesControl1.Lines[5].Add(dis[1] * 1000);



                        drawlinesControl1.Lines[6].Add(RDSoValues[2]);

                        drawlinesControl1.Lines[7].Add(vuVpp[2]);

                        drawlinesControl1.Lines[8].Add(dis[2] * 1000);





                        drawlinesControl1.Lines[9].Add(RDSoValues[3]);

                        drawlinesControl1.Lines[10].Add(vuVpp[3]);

                        drawlinesControl1.Lines[11].Add(dis[3] * 1000);

                        //_list_V1.Add(RunTim, RDSoValues[1]);

                        //_list_V2.Add(RunTim, RDSoValues[0]);

                        //_list_V3.Add(RunTim, RDSoValues[2]);

                        //_list_V4.Add(RunTim, RDSoValues[3]);

                    }

                }

                nbyte2rec = serialPort1.BytesToRead;

            }

        }

3.2.3定时器与界面刷新

上位机与下位机一样,需要定时器定时刷新、更新界面显示。

初始化定时器时间,单位毫秒;

timer1.Interval = 100;

启动定时器

timer1.Start();

定时中断函数,函数内为界面刷新命令。

private void timer1_Tick(object sender, EventArgs e)

        {
            //数据显示刷新
            label_S1.Text = dis[0].ToString("F2")+" m";

            label_S2.Text = dis[1].ToString("F2") + " m";

            label_S3.Text = dis[2].ToString("F2") + " m";

            label_S4.Text = dis[3].ToString("F2") + " m";

            drawlinesControl1._Refresh();//绘图控件刷新

        }

附录I

电路设计原理图和PCB:https://download.csdn.net/download/w267309080/88298439

单片机软件源码:https://download.csdn.net/download/w267309080/88298418

上位机软件源码:https://download.csdn.net/download/w267309080/88298400

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

CCKS2023:基于企业数仓和大语言模型构建面向场景的智能应用

8月24日-27日&#xff0c;第十七届全国知识图谱与语义计算大会&#xff08;CCKS 2023&#xff09;在沈阳召开。大会以“知识图谱赋能通用AI”为主题&#xff0c;探讨知识图谱对通用AI技术的支撑能力&#xff0c;探索知识图谱在跨平台、跨领域等AI任务中的作用和应用途径。 作为…

MAC系统“无法验证开发者”问题

参考:https://blog.csdn.net/suxiang198/article/details/126550955 对于使用MAC电脑的同学而言&#xff0c;许多时候因为使用需要&#xff0c;从第三方源&#xff08;比如github等&#xff09;下载工具或软件&#xff0c;而在运行时会受到MAC系统的安全限制&#xff0c;老是弹…

【STM32】学习笔记-SPI通信

SPI通信 SPI通信&#xff08;Serial Peripheral Interface&#xff09;是一种同步的串行通信协议&#xff0c;用于在微控制器、传感器、存储器、数字信号处理器等之间进行通信。SPI通信协议需要使用4个线路进行通信&#xff1a;时钟线(SCLK)、主输入/主输出线(MISO)、主输出/主…

深入浅出AXI协议(5)——数据读写结构读写响应结构

目录 一、前言 二、写选通&#xff08;Write strobes&#xff09; 三、窄传输&#xff08;Narrow transfers&#xff09; 1、示例1 2、示例2 四、字节不变性&#xff08;Byte invariance&#xff09; 五、未对齐的传输&#xff08;Unaligned transfers&#xff09; 六…

网络版五子棋C++实现

目录 1.项目介绍 2.开发环境 3.核心技术 4.环境搭建 5.WebSocketpp介绍 5.1WebSocketpp是什么 5.2为什么使用WebSocketpp 5.3原理解析&#xff1a; 5.4WebSocketpp主要特性 6.WebSocketpp使用 7.JsonCpp使用 8.MySQL API 9.项目模块设计以及流程图 10.封装日志宏…

基于单片机的太阳能热水器控制器设计

一、项目介绍 随着环保意识的逐渐增强&#xff0c;太阳能热水器作为一种清洁能源应用得越来越广泛。然而&#xff0c;传统的太阳能热水器控制器通常采用机械式或电子式温控器&#xff0c;存在精度低、控制不稳定等问题。为了解决这些问题&#xff0c;本项目基于单片机技术设计…

Qt鼠标点击事件处理:按Escape键退出程序

创建项目 Qt 入门实战教程&#xff08;目录&#xff09; 首先&#xff0c;创建一个名称为QtKeyEscape的Qt默认的窗口程序。 参考 &#xff1a;Qt Creator 创建 Qt 默认窗口程序 Qt响应键盘Escape事件 打开Qt Creator >>编辑 >> 项目 >> Headers>> …

服务运营 | MS文章精读:基于强化学习和可穿戴设备的帕金森治疗方案

作者信息&#xff1a;庞硕&#xff0c;李舒湉 编者按 帕金森疾病的治疗是一个备受关注的医疗问题。本文通过患者的可穿戴传感器收集数据&#xff0c;提出了一个基于强化学习的帕金森药物治疗方案。这是第一篇关于可穿戴治疗设备在慢性疾病管理中的应用研究。原文于2023年4月发…

如何在你的Android工程中启用K2编译器?

如何在你的Android工程中启用K2编译器&#xff1f; K2编译器是用于Kotlin代码编译的最新、高效编译器&#xff0c;你现在可以尝试使用了。 Kotlin编译器正在为Kotlin 2.0进行重写&#xff0c;新的编译器实现&#xff08;代号K2&#xff09;带来了显著的构建速度改进&#xff…

K210-调用自定义py库

调用自定义py库 导入py库文件调用py库 用过Python的朋友应该知道&#xff0c;Python是支持将自定义py库&#xff08;或者第三方py库&#xff09;放到同一个目录下调用的&#xff0c;MicroPython也是支持调用自定义py库的。在调用自定义py库之前&#xff0c;需要提前将py库文件导…

期货基础知识

一、期货是什么&#xff1f;  期货是与现货相对应&#xff0c;并由现货衍生而来。期货通常指期货合约&#xff0c;期货与现货完全不同&#xff0c;现货是实实在在可以交易的货&#xff08;商品&#xff09;&#xff0c;期货主要不是货&#xff0c;而是以某种大众产品如棉花、大…

影响Windows 和 macOS平台,黑客利用 Adobe CF 漏洞部署恶意软件

FortiGuard 实验室的网络安全研究人员发现了几个影响 Windows 和 Mac 设备的 Adobe ColdFusion 漏洞。 远程攻击者可利用Adobe ColdFusion 2021中的验证前RCE漏洞&#xff0c;获取受影响系統的控制权力。Adobe 已发布安全补丁来解决这些漏洞&#xff0c;但攻击者仍在利用这些漏…

leetcode:1941. 检查是否所有字符出现次数相同(python3解法)

难度&#xff1a;简单 给你一个字符串 s &#xff0c;如果 s 是一个 好 字符串&#xff0c;请你返回 true &#xff0c;否则请返回 false 。 如果 s 中出现过的 所有 字符的出现次数 相同 &#xff0c;那么我们称字符串 s 是 好 字符串。 示例 1&#xff1a; 输入&#xff1a;s…

鼠标悬停阴影的效果被旁边div挡住的解决办法

出现的问题 需求要求鼠标悬停某个图片上有阴影效果&#xff0c;但阴影被旁边相邻的div挡住了&#xff0c;如图所示 解决方案 给悬停的这块div增加2个css属性 $(this).css(position, relative); $(this).css(z-index, 200);新的效果如图所示 一直写后端&#xff0c;前端的…

国际网页短信软件平台搭建定制接口说明|移讯云短信系统

国际网页短信软件平台搭建定制接口说明|移讯云短信系统 通道路由功能介绍 支持地区通道分流&#xff0c;支持关键字&#xff0c;关键词通道分流&#xff0c;支持白名单独立通道&#xff0c;支持全网通道分流&#xff0c;支持通道可发地区设置&#xff0c;通道路由分组&#x…

redis 数据结构(二)

整数集合 整数集合是 Set 对象的底层实现之一。当一个 Set 对象只包含整数值元素&#xff0c;并且元素数量不时&#xff0c;就会使用整数集这个数据结构作为底层实现。 整数集合结构设计 整数集合本质上是一块连续内存空间&#xff0c;它的结构定义如下&#xff1a; typed…

QT C++ 实现网络聊天室

一、基本原理及流程 1&#xff09;知识回顾&#xff08;C语言中的TCP流程&#xff09; 2&#xff09;QT中的服务器端/客户端的操作流程 二、代码实现 1&#xff09;服务器 .ui .pro 在pro文件中添加network库 .h #ifndef WIDGET_H #define WIDGET_H#include <QWidget>…

春秋云镜 CVE-2018-12530

春秋云镜 CVE-2018-12530 Metinfo 6.0.0任意文件删除 靶标介绍 Metinfo 6.0.0任意文件删除。后台密码&#xff1a;f2xWcke5KN6pfebu 启动场景 漏洞利用 /admin进入管理后台&#xff0c;admin/f2xWcke5KN6pfebu /admin/app/batch/csvup.php?fileFieldtest-1&fliename…

目标检测框架MMDetection训练自定义数据集实验记录

在上一篇博文中&#xff0c;博主完成了MMDetection框架的环境部署与推理过程&#xff0c;下面进行该框架的训练过程&#xff0c;训练的入口文件为tools/train.py&#xff0c;我们需要配置的内容如下&#xff1a; parser.add_argument(--config,default"/home/ubuntu/prog…

算法通关村16关 | 滑动窗口最长字串专题

1. 最长字串专题 1.1 无重复字符的最长字串 题目 LeetCode3 给定一个字符串s&#xff0c;请你找出其中不含有重复字符的最长字串的长度。 思路 找最长字串&#xff0c;需要知道所有无重复字串的首和尾&#xff0c;找出其中最长的&#xff0c;最少两个指针才可以完成&#xff…