STM32F4_DS18B20红外温度传感器

news2024/11/15 10:14:28

目录

前言

1. 单总线时序结构

2. DS18B20结构

2.1 DS18B20操作流程

2.2 DS18B20数据帧

3. 温度存储格式

4. 硬件分析

5. 实验程序详解

5.1 main.c

5.2 DS18B20.c

5.3 DS18B20.h


前言

        STM32F4内部集成了温度传感器。在之前的学习中,我们已经学习了使用AD进行温度采集,但是因为芯片温升较大,与实际的温度差别较大。所以本次我们学习使用STM32来读取开发板外部的温度传感器的温度开发板外部的温度传感器是DS18B20,该传感器和MCU实现通讯使用的是单总线协议。

1. 单总线时序结构

初始化:

        主机将总线拉低至少480us,然后释放总线,4.7K的上拉电阻将单总线拉高,等待15~60us后,存在的从机会拉低总线60~240us产生低电平以响应主机,之后从机将释放总线。

 

发送一位:

        主机将总线拉低60~120us,然后释放总线,表示发送0;主机将总线拉低1~15us,然后释放总线,表示发送1。

        从机将在总线拉低30us后(典型值)读取电平,整个时间片应大于60us。  

发送一个字节:

        连续调用8次发送一位的时序,依次发送一个字节的8位(低位在前

接收一位:

        主机将总线拉低1~15us,然后释放总线,并且在拉低后15us内读取总线电平(尽量贴近15us的末尾),读取为低电平则为接收0,读取为高电平则为接收1,整个时间片应大于60us。

接收一个字节:

        连续调用8次接收一位的时序,依次接收一个字节的8位(低位在前

正点原子官方提供的单总线时序:

1. 复位脉冲和应答脉冲

        单总线上的所有通信都是以初始化序列开始。主机输出低电平,保持低电平时间至少 480 us,以产生复位脉冲。接着主机释放总线,4.7K 的上拉电阻将单总线拉高,延时 15~60 us, 并进入接收模式(Rx)。接着 DS18B20 拉低总线 60~240 us,以产生低电平应答脉冲。

若为低电平,再延时 480 us。

2. 写时序

        写时序包括写 0 时序和写 1 时序。所有写时序至少需要 60us,且在 2 次独立的写时序之间 至少需要 1us 的恢复时间,两种写时序均起始于主机拉低总线。写 1 时序:主机输出低电平, 延时 2us,然后释放总线,延时 60us。写 0 时序:主机输出低电平,延时 60us,然后释放总线, 延时 2us。

3. 读时序

        单总线器件仅在主机发出读时序时,才向主机传输数据,所以 ,在主机发出读数据命令后, 必须马上产生读时序,以便从机能够传输数据。所有读时序至少需要 60us,且在 2 次独立的读 时序之间至少需要 1us 的恢复时间。每个读时序都由主机发起,至少拉低总线 1us。主机在读时序期间必须释放总线,并且在时序起始后的 15us 之内采样总线状态  

典型的读时序过程为: 主机输出低电平延时 2us,然后主机转入输入模式延时 12us,然后读取单总线当前的电平,然后延时50us

注:所有的这些信号,除了应答脉冲以外,都是由主机发出的同步信号。并且发送的所有命令和数据都是低位在前。在写程序时,需要注意设置谁输入,谁输出,根据信号是由谁发        

2. DS18B20结构

        DS18B20是由DALLAS半导体公司推出的一种 “一线总线” 接口的温度传感器。与传统的热敏电阻等测温元件相比,它是一种新型的体积小、适用电压宽、与微处理器接口简单的数字化温度传感器。它工作在 3~5.5V 的电压范围

ROM中的64位序列号是出厂前被定义好的,它可以看做是该DS18B20的地址序列码,每个DS18B20的64位序列号均不相同

64位ROM的排列是:

        前8位是产品家族码,接着48位是DS18B20的序列号,最后8位是前面56位的循环冗余校验码(CRC=X8+X5+X4+1)。

ROM的作用是:

        使每一个DS18B20都各不相同,以实现一根总线上挂接多个DS18B20。

2.1 DS18B20操作流程

初始化从机复位,主机判断从机是否响应

ROM操作ROM指令+本指令需要的读写操作

功能操作功能指令+本指令需要的读写操作

2.2 DS18B20数据帧

温度变换:

        初始化--->跳过ROM--->开始温度变换

温度读取:

        初始化--->跳过ROM--->读暂存器--->连续的读操作

DS18B20典型的温度读取过程:

        复位→发 SKIP ROM 命令(0XCC)→发开始转换命令(0X44)→延时→复 位→发送 SKIP ROM 命令(0XCC)→发读存储器命令(0XBE)→连续读出两个字节数据(即 温度)→结束。

3. 温度存储格式

温度存储的寄存器是16位寄存器,LSB为寄存器的低8位,MSB为寄存器的高8位;

位15~位11:温度的状态位,因为温度是有正有负的。高5位为0时,表示温度是正的;高5位是1时,表示温度是负的;

位3~位0:用来存储温度的小数部分。因为温度不一定都是整数,可能会有小数。例如位3表示0.5,位2表示0.25,位1表示0.125,位0表示0.0625

:DS18B20可以检测的温度范围是-55℃~+125℃;精度为±0.5℃。

有关程序中温度的相关问题:

        1. 为什么温度寄存器中的高8位的二进制数大于7,就认为温度是负的?

        因为温度存储的寄存器是16位,高5位是温度状态位,高5位为0时,表示温度是正的;高5位为1时,表示温度是负的;
7的八位二进制是:0000 0111 ,对应的高5位正好是0,如果大于7,那么对应的二进制就是1111 1111 因为高5位是状态位,要么全为0,要么全为1

        2. 温度从二进制数转换成十进制数,为什么乘以0.625?

        DS18B20的转换精度是9~12位,为了提高精度通常采用的都是12位,12位的最低位权是1/16=0.0625,所以说温度寄存器中的值都是以0.0625为步进的
        换言之就是:温度每波动一次都是要么+0.0625,要么-0.0625,而不会出现温度上升0.01,或者下降0.01的情况。
        所以温度寄存器中的值就是温度值的二进制乘以0.0625,得到的就是实际的十进制数;
        程序中之所以乘0.625是因为返回值返回的温度是-550~+1250,返回温度相对于实际的温度范围放大了十倍,所以转换的步进值也要放大10倍,即0.625

4. 硬件分析

温度传感器属于外部器件,所以做该实验时,需要购买DS18B20温度传感器模块接在开发板对应的位置。

GND/NC:接地

DQ:单总线输入/输出引脚,DQ引脚连接在STM32的PG9引脚上

VCC:供电电源,3V~5.5V

:1WIRE_DQ 和 DCMI_PWDN 是共用 PG9 的,所以他们不能同时使用。

5. 实验程序详解

实验现象:

        开机的时候先检测DS18B20是否存在,如果没有,则提示错误。只有在检测到DS18B20之后才开始读取温度并显示在LCD上,如果发现了DS18B20,则程序每隔100ms左右读取一次数据,把温度显示在LCD上。

5.1 main.c

#include "stm32f4xx.h"                 
#include "delay.h"
#include "usart.h"
#include "LED.h"
#include "lcd.h"
#include "Key.h"
#include "usmart.h"
#include "DS18B20.h"

//LCD状态设置函数
void led_set(u8 sta)//只要工程目录下有usmart调试函数,主函数就必须调用这两个函数
{
	LED1=sta;
}
//函数参数调用测试函数
void test_fun(void(*ledset)(u8),u8 sta)
{
	led_set(sta);
}

int main(void)
{
	u8 t=0;
	short temperature;
	delay_init(168);
	uart_init(115200);
	
	LED_Init();
	LCD_Init();
	POINT_COLOR=RED;
	LCD_ShowString(30,50,200,16,16,"Explorer STM32F4");
	LCD_ShowString(30,70,200,16,16,"DS18B20 Test");
	LCD_ShowString(30,90,200,16,16,"ATOM@ALIENTEK");
	LCD_ShowString(30,110,200,16,16,"2023/06/22");
	
	while(DS18B20_Init()) //初始化返回值是检验DS18B20能否被开发板检测到,返回1也就是未检测到DS18B20
	{
		LCD_ShowString(30,130,200,16,16,"DS18B20 ERROR");
		delay_ms(200);
		LCD_Fill(30,130,239,130+16,WHITE); //清屏,清屏的范围是:x 30~239;y 130~130+16,也就是左边130行往下清两行
		delay_ms(200);
	}
	LCD_ShowString(30,130,200,16,16,"DS18B20 OK");	
	POINT_COLOR=BLUE;
	LCD_ShowString(30,150,200,16,16,"Temp:   . C");
	while(1)
	{
		if(t%10==0) //每100ms读取一次
		{
			temperature=DS18B20_Get_Temperature(); //调用读取温度函数,将读到的十进制数赋值给temperature
			if(temperature<0) //温度为负
			{
				LCD_ShowChar(30+5*8,150,'-',16,0);  //显示负号
				temperature=-temperature;  //负数变正数
			}
			else
			{
				LCD_ShowChar(30+5*8,150,' ',16,0); //去掉负号
			}
			LCD_ShowNum(30+5*8+8,150,temperature/10,2,16); //显示整数位
			//30+5*8+8:30起始坐标,5*8表示Temp:占用的字节,8表示的是符号位占用的字节
			LCD_ShowNum(30+5*8+4*8,150,temperature%10,1,16); //显示小数部分
		}
		delay_ms(10);
		t++;
		if(t==20)
		{
			t=0;
			LED0=!LED0;
		}
	}
}



5.2 DS18B20.c

#include "stm32f4xx.h"           
#include "DS18B20.h"
#include "delay.h"

//复位DS18B20
void DS18B20_Reset(void)
{
	//复位的时序是:主机输出低电平,保持低电平至少480us,以产生复位脉冲。
	//接着主机释放总线,4.7K上拉电阻将单总线拉高,延迟15~60us。
	DS18B20_IO_OUT();  //整个单总线协议,除了应答信号是从机DS18B20发的,其余的信号都是主机发的,因此在发送这些信号时,都需要将主机的GPIO模式设置为输出模式
	DS18B20_DQ_OUT=0;  //主机输出低电平
	delay_us(750);     //保持低电平至少480us,以产生复位脉冲。这里设置750us
	DS18B20_DQ_OUT=1;  //主机释放总线,4.7K上拉电阻将单总线拉高.
	delay_us(15);      //延迟15~60us。这里设置为15us
}
//应答脉冲,也就是等待DS18B20的回应
//返回1:开发板上未检测到DS18B20的存在
//返回0:DS18B20存在
u8 DS18B20_CheckExist(void)
{
	//应答信号的时序是:在复位脉冲时序结束后,DS18B20 拉低总线 60~240 us,以产生低电平应答脉冲。
	u8 Existence=0;
	DS18B20_IO_IN();   //IO引脚设置为输入模式,以便MCU可以接收到DS18B20的返回应答
	while(DS18B20_DQ_IN && Existence<200)//按位与&&操作:两个条件都成立即可进入该while循环
	//应答信号的时序规定:DS18B20需要拉低总线 60~240 us,以产生低电平应答脉冲。
	//DS18B20_DQ_IN是DS18B20发送给主机的信号,如果为真,则意味着DS18B20没有拉低总线,也就没有产生低电平应答脉冲
	//Existence<200:等待从机响应的时间,主机给一个复位信号,从机返回应答需要有一个缓冲时间,这里我们设置200us;换言之,如果超过200us,DS18B20还没有返回应答,则认为开发板没有接DS18B20
	{
		Existence++;
		delay_us(1);
	}//离开while循环时,DS18B20_DQ_IN一定是等于0,处于低电平,或者Existence>200,所以接下来需要判断究竟是哪个条件成立了
	if(Existence>=200)//缓冲时间超过200us的情况
		return 1; //认为开发板上未检测到DS18B20的存在
	else             //DS18B20存在
		Existence=0;  //为总线延迟240us做准备
	while(!DS18B20_DQ_IN && Existence<240)
		//应答信号的时序规定:DS18B20需要拉低总线 60~240 us,以产生低电平应答脉冲。
		//该程序表示引脚收到低电平,并且通过循环延迟了240us
	{
		Existence++;
		delay_us(1);
	}
	if(Existence>=240) //单总线时序规定应答信号需要拉低总线60~240us,这里设置的是239;大于240,违反时序,一定是return 0
		return 1;
	return 0;
}
//从DS18B20读一个位
//返回值:1/0
u8 DS18B20_Read_Bit(void)
{
	//读一位的时序是:主机输出低电平延时2us,然后主机转入输入模式延时12us,然后读取单总线当前的电平,延时50us;读时序至少需要60us
	//主机在读时序期间必须释放总线,并且在时序起始后的15us之内采样总线的状态。
	u8 data;
	DS18B20_IO_OUT(); //主机读从机,IO引脚输出模式
	DS18B20_DQ_OUT=0; //主机输出低电平
	delay_us(2);      //主机输出低电平延时2us
	DS18B20_DQ_OUT=1; //主机在读时序期间必须释放总线
	DS18B20_IO_IN();  //主机转入输入模式
	delay_us(12);     //主机转入输入模式延时12us
	if(DS18B20_DQ_IN) //读取单总线当前的电平,读的值就是引脚输入的电平值
		data=1;
	else
		data=0;
	delay_us(50);     //延时50us
	return data;
}
//从DS18B20读一个字节
//返回值:读到的数据
u8 DS18B20_Read_Byte(void)
{
	u8 i,j,data;
	data=0;
	for(i=1;i<=8;i++)  //读一个字节就是在读一位的基础之上循环8次得到的,低位在前
	{
		j=DS18B20_Read_Bit(); //将读到的那一位给到j
		data=(j<<7)|(data>>1);
		//该代码这样理解:第一次data初始化为0,右移一位还是0;j<<7 会将读到的那一位给到最高位,1和0进行或运算,是1还是1,是0还是0
		//第二次循环的时候,data不再是0了,而是第一次得到的8位(最高位是第一次接收的值,其余位都是0);data>>1,表示第一次的最高位放到次高位上,
        //最高位通过本次循环的j<<7来存放最高位,这样或运算以后,第一次接收的放在次高位,第二次接收的放在最高位
		//每循环一次,上一次的8位数据就会整体右移一位,腾出的最高位给本次接收的那一位存放;循环八次,即可得到数据,并且还是低位在前的。
	}
	return data;
}
//写一个字节到DS18B20
//data:要写入的字节
void DS18B20_Write_Byte(u8 data)
{
	//写1时序:主机输出低电平,延时2us,然后释放总线,延时60us
	//写0时序:主机输出低电平,延时60us,然后释放总线,延时2us
	//所有写时序至少60us
	u8 j;
	u8 testb; //该变量用于记录要写的字节是逻辑1还是逻辑0
	DS18B20_IO_OUT(); //主机写字节到DS18B20,主机设置为输出模式
	for(j=1;j<=8;j++)
	{
		testb=data&0x01;  //单总线协议发送时是低位在前,所以先取出最低位进行发送
		data=data>>1;     //每取一次最低位,就将次低位右移到最低位,为下一次取最低位做准备
		//单总线协议下:逻辑1和逻辑0的写时序是不一样的,所以需要进行判断分开写
		if(testb)  //逻辑1
		{
			DS18B20_DQ_OUT=0;  //主机输出低电平
			delay_us(2);	   //延时2us
			DS18B20_DQ_OUT=1;  //释放总线
			delay_us(60);	   //延时60us
		}
		else	   //逻辑0
		{
			DS18B20_DQ_OUT=0;  //主机输出低电平
			delay_us(60);	   //延时60us
			DS18B20_DQ_OUT=1;  //释放总线
			delay_us(2);	   //延时2us
		}
	}
}
//温度转换
void DS18B20_StartConvert(void)
{
	//温度转化的时序是:初始化(复位),然后跳过ROM,最后发送开始温度转换的数据帧
	DS18B20_Reset();  //初始化(复位)
	DS18B20_CheckExist();  //DS18B20应答
	DS18B20_Write_Byte(DS18B20_SKIP_ROM); //写时序跳过ROM
	DS18B20_Write_Byte(DS18B20_CONVERT_T); //发送开始温度转换的数据帧
}
//初始化DS18B20的IO口、DQ,同时检测DS18B20的存在
//返回1:不存在
//返回0:存在 
u8 DS18B20_Init(void)
{
	RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOG,ENABLE);  //使能GPIOG时钟
	
	//GPIOG9
	GPIO_InitTypeDef GPIO_InitStructure;
	GPIO_InitStructure.GPIO_Mode=GPIO_Mode_OUT; //默认GPIO的模式是输出
	GPIO_InitStructure.GPIO_OType=GPIO_OType_PP;
	GPIO_InitStructure.GPIO_Pin=GPIO_Pin_9;
	GPIO_InitStructure.GPIO_PuPd=GPIO_PuPd_UP;
	GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
	GPIO_Init(GPIOG,&GPIO_InitStructure);
	
	DS18B20_Reset(); //复位时序
	return DS18B20_CheckExist(); //返回值是检测DS18B20是否存在
}
//从DS18B20得到温度值
//精度:0.1C
//返回值:温度值(-550~+1250)
//这里需要注意,精度是0.1C,并且测的的温度返回值是温度值(-550~+1250)
//根据DS18B20芯片手册记录:该传感器的测量范围是:-55~+125℃ ,所以相当于返回值放大了10倍
short DS18B20_Get_Temperature(void)
{
	//温度读取的时序是:最先进行温度转换,复位(初始化),然后跳过ROM,紧接着读暂存器,最后进行连续的读操作,分别读出低8位和高8位
	u8 temp;
	u8 TLSB,THSB;
	short temperature; //short短整型是16位
	DS18B20_StartConvert(); //进行温度转换
	DS18B20_Reset();   //复位(初始化)
	DS18B20_CheckExist(); //检查DS18B20是否存在
	DS18B20_Write_Byte(DS18B20_SKIP_ROM); //跳过ROM
	DS18B20_Write_Byte(DS18B20_READ_SCRATCHPAD); //读暂存器
	
	TLSB=DS18B20_Read_Byte(); //连续的读操作,读出低8位
	THSB=DS18B20_Read_Byte(); //连续的读操作,读出高8位
	
	if(THSB>7)
	{
		THSB=~THSB;
		TLSB=~TLSB;
		temp=0;  //表示温度为负
		//这里解释一下,为什么THSB>7,温度就是负的?
		//因为温度存储的寄存器是16位,高5位是温度状态位,高5位为0时,表示温度是正的;高5位为1时,表示温度是负的;
		//7的八位二进制是:0000 0111 ,对应的高5位正好是0,如果大于7,那么对应的二进制就是1111 1111 因为高5位是状态位,要么全为0,要么全为1
	}
	else
	{
		temp=1;  //表示温度为正
	}
	temperature=THSB;
	temperature=temperature<<8; //将低8位放到次低8位上
	temperature=temperature+TLSB; //获得低8位
	temperature=(double)temperature*0.625; //温度从二进制转换成十进制。我们表达温度不会说0000 0265摄氏度,我们只会说30摄氏度
	//这里解释一下,为什么乘以0.625就能实现温度从二进制转换到十进制数?
	//DS18B20的转换精度是9~12位,为了提高精度通常采用的都是12位,12位的最低位权是1/16=0.0625,所以说温度寄存器中的值都是以0.0625为步进的
	//换言之就是:温度每波动一次都是要么+0.0625,要么-0.0625,而不会出现温度上升0.01,或者下降0.01的情况。
	//所以温度寄存器中的值就是温度值的二进制乘以0.0625,得到的就是实际的十进制数;
	//程序中之所以乘0.625是因为返回值返回的温度是-550~+1250,返回温度相对于实际的温度范围放大了十倍,所以转换的步进值也要放大10倍,即0.625
	if(temp)
	{
		return temperature;
	}
	else
		return -temperature; //这里默认只输入正的温度值
}



5.3 DS18B20.h

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

//IO方向设置
//该宏定义方式是通过位段的方式来定义的,通过调用GPIO的模式寄存器来设置相关位,其中00:输入模式 01:输出模式
//位段操作分两步:第一步将所要操作位清空,使用与&操作符完成;第二步将清空的位设置为相应的值,按设置的值输出相应的模式
//GPIO状态寄存器是32位寄存器,每两个位控制一个GPIO引脚,所以总共控制15个引脚
//本次我们操作的对象是PG9引脚,也就对应于寄存器的18位、19位
#define DS18B20_IO_IN()  {GPIOG->MODER&=~(3<<(9*2));GPIOG->MODER|=0<<9*2;}	//PG9输入模式
//将18/19位清空,使用&操作符完成;2*9表示每两个位控制一个引脚,先找到PG9所在的两个位
//3的32位二进制是:			0000 0000 0000 0000 0000 0000 0000 0011
//左移18位得到的是:			0000 0000 0000 1100 0000 0000 0000 0000
//取反得到的是:    			1111 1111 1111 0011 1111 1111 1111 1111
//和最初的32位二进制按位与: 0000 0000 0000 0000 0000 0000 0000 0011 此时就设置了18 19位00,表示将这两位清空
//0的32位二进制是:          0000 0000 0000 0000 0000 0000 0000 0000
//0左移18位,|或操作符:     0000 0000 0000 0000 0000 0000 0000 0000 此时就将18位、19位设置成了00,表示输入模式
#define DS18B20_IO_OUT() {GPIOG->MODER&=~(3<<(9*2));GPIOG->MODER|=1<<9*2;} 	//PG9输出模式
//同理设置PG9输出模式,将第18 19位设置为01即可。

//IO操作函数
#define DS18B20_DQ_OUT PGout(9)  //PG9设置为输出模式
#define DS18B20_DQ_IN PGin(9)    //PG9设置为输入模式

//DS18B20数据帧
#define DS18B20_SKIP_ROM 0xCC
#define DS18B20_CONVERT_T 0x44
#define DS18B20_READ_SCRATCHPAD 0xBE


void DS18B20_Reset(void);
u8 DS18B20_CheckExist(void);
u8 DS18B20_Read_Bit(void);
u8 DS18B20_Read_Byte(void);
void DS18B20_Write_Byte(u8 data);
void DS18B20_StartConvert(void);
u8 DS18B20_Init(void);
short DS18B20_Get_Temperature(void);

#endif


该实验代码每一步都进行了详细的解释,如发现其中有错误的地方或者解释有误,欢迎指导改正!!!

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

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

相关文章

宁波天一永安杯初赛 wp-AGCTS战队

文章目录 MISCZipSimpleDocumentBeautifulImage WebDeserializationCodeCheck CryptoSecretRsa MobilePeacock pwnwingtip REPolenta MISC Zip ARCHPR 直接数字爆破&#xff0c;得到二进制密码&#xff0c;得 flag SimpleDocument Kali binwalk 发现里面有一 pdf 文件&#…

DRIFTINGBLUES: 3实战演练

文章目录 DRIFTINGBLUES: 3实战演练一、前期准备1、相关信息 二、信息收集1、端口扫描2、访问网站3、访问网页4、翻译内容5、访问网页6、翻译内容8、查看源码9、解密10、访问网页11、写入shell并登录12、连接shell13、查找nc14、反弹shell 三、后渗透1、进入家目录查找文件2、写…

分布式应用 ----- 点对点(p2p)网络

目录 1. 概述 1.1. P2P的概念 1.2. P2P产生的背景 1.3. P2P的优劣势 2. P2P分类 2.1. 根据中央化程度 2.2. 根据网络拓扑结构 3. NAT技术详解 3.1. 概述 3.2. NAT的优劣势 3.3. NAT穿透常见解决方案 3.4. 探针打洞基本原理 3.4.1. 基本原理 3.4.2. 同一个NAT网关内…

2023年企业云盘排行榜,这些产品值得尝试!

在当今信息技术高度发达的时代&#xff0c;企业对于信息的存储和管理需求越来越高。因此&#xff0c;企业云盘逐渐成为了企业存储与管理的重要组成部分。企业云盘能够实现多设备共享、远程控制、安全备份、合作办公等多种功能&#xff0c;方便高效地解决企业内部信息管理问题。…

【AIGC】17、MM-OVOD | 同时使用文本示例和图像示例来指导分类

文章目录 一、背景二、方法2.1 框架总览2.1.1 Text-based classifiers from language descriptions2.1.2 Vision-based Classifiers from Image Exemplars2.1.3 Constructing Classifiers via Multi-Modal Fusion 三、效果3.1 数据集3.2 实现细节3.3 开集目标检测结果 论文&…

双向交错CCM图腾柱无桥单相PFC学习仿真与实现(2)SOGI_PLL学习仿真总结

目录 前言 SOGI基本原理 锁相环基本原理 仿真实现及说明 总结 前言 前面总结了双向交错CCM图腾柱无桥单相PFC系统实现&#xff0c;后面把问题细分&#xff0c;关于SOGI锁相环的应用和学习在这里总结下。 双向交错CCM图腾柱无桥单相PFC学习仿真与实现&#xff08;1&#x…

Collection接口详细介绍(下)

前言&#xff1a; 本篇文章主要讲解Java中的Collection接口以及相关实现类的知识。该专栏比较适合刚入坑Java的小白以及准备秋招的大佬阅读。 如果文章有什么需要改进的地方欢迎大佬提出&#xff0c;对大佬有帮助希望可以支持下哦~ 小威在此先感谢各位小伙伴儿了&#x1f601…

CSDN 周赛 59 期

CSDN 周赛 59 期 前言判断题单选题题目1题目2填空题编程题1、题目名称:坏掉的打字机2、题目名称:布尔零点计数小结前言 由于最近,csdn 每日一练新增了两个题目,按照惯例,那么新增的题目,会就近出现在最近的 CSDN 周赛中,嗯,经常参加周赛,并关注每日一练社区的小伙伴应…

51单片机一个TIMER输出6个PWM

51单片机的timer很少&#xff0c;往往16bit的timer只有一个&#xff0c;可以硬件输出的channel也不多。如我手上这就是这个情况&#xff0c;timer1, 16bit, 只有三个通道。我想输出6个pwm&#xff0c;这个就无法硬件的方式了。只能使用软件模拟了。pwm是1-20ms一个周期&#xf…

Thinking in Java第四版2.8注释和嵌入式文档

文章目录 前言一、注释风格1.单行注释2.多行注释 二、语法三、标签总结 前言 Java8官方在线文档 文档描述对每个系统来说都是必备且重要的&#xff0c;这里将介绍一些javadoc标签&#xff0c;以便加深对文档的理解和编写等。 一、注释风格 1.单行注释 单行注释以一个//起头&a…

JavaWeb之tomcarHTTP

1 DOM4j Xml解析 1.1 JAXP  JDK内置&#xff0c;不需要导入第三方jar包&#xff0c;简单工具优先选择。  支持两种解析方式&#xff1a;DOM、SAX 1.1.1 JAXP—DOM 加载xml 生成一个DOM树。获得整个文档的描述对象Document 解析 api 获得工厂 DocumentBuilderFactory –》 …

【MySql】MySql的事务基础篇

文章目录 CURD加控制什么是事物为什么会出现事务事务的版本支持事务的提交方式 CURD加控制 模拟一个买票系统的场景如下所示&#xff1a; MySQL注定会被多个客户端进行访问的&#xff0c;这个是肯定的&#xff0c;存储的都是数据&#xff0c;数据在上层可能有一个线程在用&…

C++17

目录 基本语言特性结构化绑定if和switch初始化器 std::string_view属性[[nodiscard]][[maybe_unused]][[fallthrough]] 模板特性新的标准库组件std::optional<>std::variant<>std::anystd::bytestd::as_const 文件系统库零星新特性 基本语言特性 结构化绑定 概念…

ubuntu安装WPS2019以及解决缺少字体问题

环境&#xff1a;ubuntu22.04.2 LTS 步骤&#xff1a; 1.去官网下载最新的WPS&#xff0c;官网地址如下&#xff1a;WPS Office 2019 for Linux-支持多版本下载_WPS官方网站 2.sudo dpkg -i 安装包.deb 3.安装完成&#xff0c;首次用WPS打开某个文档&#xff0c;会出现如下报…

硬件入门之什么是三极管

硬件入门之什么是三极管 文章目录 硬件入门之什么是三极管一、三极管是什么&#xff1f;&#xff08;百度百科&#xff09;三极管的3种工作状态分别是截止状态、放大状态、饱和状态 二、实际应用场景1.放大电路 &#xff08;放大状态&#xff09;2、开关电路&#xff08;截至状…

【聚类算法】谱聚类spectral clustering

every blog every motto: You can do more than you think. https://blog.csdn.net/weixin_39190382?typeblog 0. 前言 说明&#xff1a; 后续增补 1. 正文 1.1 整体理解 谱聚类&#xff08;Spectral Clustering&#xff09;是一种基于图论的聚类方法&#xff0c;将带权无…

基于java,springboot的校园闲置物品租售系统设计与实现

背景 校园闲置物品租售系统应有的主要功能模块&#xff0c;本系统有管理员、卖家和用户&#xff0c;管理员&#xff1b;首页、个人中心、用户管理、卖家管理、商品种类管理、商品信息管理、商品租借管理、商品购买管理、闲置鱼塘、系统管理&#xff0c;用户&#xff1b;首页、…

Java并发中的原子性、可见性和有序性

基于JMM的内存模型&#xff0c;Java并发编程的核心问题&#xff1a;原子性、可见性、有序性 那么在此之前&#xff0c;我们有必要先说一下Java的JMM内存模型&#xff1a;java内存模型&#xff0c;是java虚拟机规范的一种工作模式&#xff0c;它将内存分为主内存和工作内存。线…

【机器学习】十大算法之一 “PCA”

作者主页&#xff1a;爱笑的男孩。的博客_CSDN博客-深度学习,活动,python领域博主爱笑的男孩。擅长深度学习,活动,python,等方面的知识,爱笑的男孩。关注算法,python,计算机视觉,图像处理,深度学习,pytorch,神经网络,opencv领域.https://blog.csdn.net/Code_and516?typeblog个…

高性能计算的意义是什么

高性能计算&#xff08;High-Performance Computing&#xff0c;HPC&#xff09;在现代科学、工程和商业领域中具有重要意义。以下是一些高性能计算的重要意义&#xff1a; 加速科学研究和创新&#xff1a;高性能计算可以提供大规模的计算能力和存储资源&#xff0c;使得科学家…