当前位置: 首页 > news >正文

12【模块学习】DS18B20(二):高级使用

DS18B20

  • 1、改变采样分辨率
  • 2、总线上有多个设备的使用
    • 2.1、获取总线上单个设备的ROM码
    • 2.2、通过匹配ROM指令使用总线上多个设备
  • 3、项目:4路温度检测+LCD显示

1、改变采样分辨率

需要改变采样的分辨率,则需要向暂存器的配置寄存器中写入配置参数。在向寄存器写入数据之前需要发写寄存器指令
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
向暂存器中写入数据时,是从byte2开始向下写入,所以需要使用2个字节的无用数据来填充byte2和byte3.

改变采样分辨率的代码如下:

/*** 改变采集精度函数* accuracy:精度(9~12)*         9       0.5       0x1f*         10      0.25      0x3f*         11      0.125     0x5f*         12      0.0625    0x7f*/
void Change_Accuracy(unsigned char accuracy)
{DS18B20_Init();				//初始化(包括了ROM指令)OneWire_Write(WRITET_REG);	//发送写寄存器指令OneWire_Write(0xff);		//用于填充byte2寄存器OneWire_Write(0xff);		//用于填充byte3寄存器switch(accuracy){case 9:OneWire_Write(0x1f);//配置为9位精度,采样分辨率 = 0.5break;case 10:OneWire_Write(0x3f);//配置为10位精度,采样分辨率 = 0.25break;case 11:OneWire_Write(0x5f);//配置为11位精度,采样分辨率 = 0.125break;case 12:OneWire_Write(0x7f);//配置为12位精度,采样分辨率 = 0.0625break;default:break;}
}

main.c文件的代码如下:

#include "LCD1602.h"
#include "DS18B20.h"void main(void)
{float Num = 0;LCD_Init();	Change_Accuracy(9);		//采样分辨率 = 0.5while(1){Num = GET_Temp();LCD_ShowFloat(1, 1, Num, 3,3);}
}

在这里插入图片描述
如图:将采样分辨率变为0.5摄氏度时,温度变化0.25℃时就采样不出来。

2、总线上有多个设备的使用

在这里插入图片描述

如上图所示:在P2^4引脚上面连接这4个DS18B20设备。将这4个设备的ROM Number分别改为B8C530,B8C531,B8C532,B8C533

2.1、获取总线上单个设备的ROM码

需要获取总线上单个设备的ROM码,只要发送ROM指令中的0x33即可,如下图所示:

在这里插入图片描述

获取ROM码的代码如下:

/*** 读取从机的64位ROM码* 设备1ROM码:0x8E00000B8C53028* 设备2ROM码:0xB900000B8C53128* 设备3ROM码:0xE000000B8C53228* 设备4ROM码:0xD700000B8C53328*/
void ReadRomCode(unsigned char *RomCode)
{unsigned char i = 0;bit ACK;ACK = OneWire_Reset();		//初始化if(!ACK){OneWire_Write(RWAD_ROM);//发送ROM指令:读取ROM码for(i = 0; i<8; i++)	//ROM码为8个字节的数据{RomCode[i] = OneWire_Read();//读取一个字节,先读取低字节数据}}
}

main.c文件的代码如下:

#include "LCD1602.h"
#include "DS18B20.h"unsigned char Num[8] = {0};
void main(void)
{unsigned char i = 0;LCD_Init();	ReadRomCode(Num);for(i = 0; i<8; i++){LCD_ShowHexNum(1, 1+i*2, Num[i],2);	//显示ROM码}while(1){}
}

在这里插入图片描述

如图:读取第一个设备的ROM时,其他设备断开总线。
第一个DS18B20的ROM码为0x8E00000B8C53028,第二个DS18B20的ROM码为0xB900000B8C53128
因为读取ROM码时从最低字节开始读取,然后LCD显示也是从最低字节从左向右依次显示,所以显示是反着的。

2.2、通过匹配ROM指令使用总线上多个设备

匹配ROM码的代码如下:

#include "DS18B20.h"/* 使用二维数组将4个设备的ROM码存储起来 */
unsigned char code RomCode[][8]={{0x28, 0x30, 0xC5, 0xB8, 0x00, 0x00, 0x00, 0x8E},//设备1的ROM码{0x28, 0x31, 0xC5, 0xB8, 0x00, 0x00, 0x00, 0xB9},//设备2的ROM码{0x28, 0x32, 0xC5, 0xB8, 0x00, 0x00, 0x00, 0xE0},//设备3的ROM码{0x28, 0x33, 0xC5, 0xB8, 0x00, 0x00, 0x00, 0xD7} //设备4的ROM码
};/*** 单总线上有多个DS18B20设备的初始化* Routes:哪一个设备(1~4)*/
void DS18B20_Mul_Init(unsigned char Routes)
{unsigned char i = 0;bit ACK;ACK = OneWire_Reset();							//初始化if(!ACK){OneWire_Write(MATH_ROM);					//ROM指令:匹配ROM指令/* 发送匹配的ROM码 */switch(Routes){case 1:									//若想匹配第1个设备,则发送第1个设备的ROM码for(i = 0;i<8;i++){OneWire_Write(RomCode[0][i]);}break;case 2:									//若想匹配第2个设备,则发送第2个设备的ROM码for(i = 0;i<8;i++){OneWire_Write(RomCode[1][i]);}break;case 3:									//若想匹配第3个设备,则发送第3个设备的ROM码for(i = 0;i<8;i++){OneWire_Write(RomCode[2][i]);}break;case 4:									//若想匹配第4个设备,则发送第4个设备的ROM码for(i = 0;i<8;i++){OneWire_Write(RomCode[3][i]);}break;default:break;}}
}/*** 获取单总线上多个DS18B20中的某个设备的温度* Routes:哪个DS18B20设备(1~4)*/
float GET_MulTemp(unsigned char Routes)
{unsigned char LSB,MSB;int tempReg;float T;DS18B20_Mul_Init(Routes);	//匹配ROM初始化OneWire_Write(CONVERT_T);	//启动温度转换DS18B20_Mul_Init(Routes);	//匹配ROM初始化OneWire_Write(READ_REG);	//读取寄存器LSB = OneWire_Read();		//读取低字节MSB = OneWire_Read();		//读取高字节tempReg = ((int)MSB << 8) | LSB;T = tempReg / 16.0;return T;
}

main.c文件的代码如下:

#include "LCD1602.h"
#include "DS18B20.h"static float Num[4] = {0};
void main(void)
{unsigned char i = 0;LCD_Init();	while(1){/* 分别获取设备上采样的温度 */for(i = 0; i<4; i++){Num[i] = GET_MulTemp(i+1);}/* LCD上显示 */LCD_ShowFloat(1, 1, Num[0], 2,2);LCD_ShowFloat(1, 9, Num[1], 2,2);LCD_ShowFloat(2, 1, Num[2], 2,2);LCD_ShowFloat(2, 9, Num[3], 2,2);}
}

在这里插入图片描述

3、项目:4路温度检测+LCD显示

项目描述:
①单片机启动时,LCD1602显示启动界面 “TEMP MENU”
②显示1s后,自动跳转到显示温度数据。一次显示界面显示2路温度数据
③LCD1602显示温度分为自动模式和手动模式,在自动模式下:每隔1s跳转显示。
④使用按键KEY2切换自动模式和手动模式,切换时显示为“Automa”表示切换为自动模式,显示为“Manual”表示手动模式
⑤在手动模式下:按键KEY1用于切换温度显示
⑥按键KEY4用于切换为设置不同通道温度阈值模式,进入设置模式后,按键KEY1为增加温度阈值,KEY2为减小温度阈值,KEY3确定阈值并且退出设置模式

⑦当检测的温度高于设置的阈值温度时,在后面显示“W”字符进行报警

项目演示

QQ2025415-21326

①OneWire.c文件的代码如下:

/************************************/
/* 此文件为单总线通信协议底层驱动函数 */
/* 通信引脚:P2^4                    */
/************************************/
#include "OneWire.h"
#include "intrins.h"sbit WireBUS = P2^4;	//通信引脚:P2^4 
void Delay600us()		//@11.0592MHz
{unsigned char i, j;_nop_();i = 2;j = 15;do{while (--j);} while (--i);
}void Delay90us()		//@11.0592MHz
{unsigned char i;i = 25;while (--i);
}void Delay30us()		//@11.0592MHz
{unsigned char i;i = 11;while (--i);
}/*** 单总线设备复位与应答*/
bit OneWire_Reset(void)
{bit ACK = 0;unsigned char i = 0;/* 1、复位 */EA = 0;			//关闭中断WireBUS = 0;	//主机将总线拉低Delay600us();	//等待600usWireBUS = 1;	//主机将总线拉高,释放总线Delay90us();	//等待90us/* 2、获取应答 */ACK = WireBUS;		//读取从机应答while(!WireBUS);	//等待从机释放总线{i++;if(i > 150){return 1;//跳出循环}}EA = 1;			//开启中断return ACK;
}/*** 主机向从机写入一个字节的数据*/
void OneWire_Write(unsigned char Byte)
{unsigned tem = 0;unsigned char i = 0;EA = 0;						//关闭中断for(i = 0; i < 8; i++){tem = 0x01 << i;		//低位先行WireBUS = 0;			//主机将总线拉低_nop_();				//2us_nop_();				//2usWireBUS = Byte & tem;	//向总线上写入数据Delay30us();			//30us等待从机读取数据WireBUS = 1;			//释放总线_nop_();				//2us_nop_();				//2us}EA = 1;						//开启中断
}	/*** 主机向从机读取一个字节的数据*/
unsigned char OneWire_Read(void)
{unsigned char Temp = 0x00;unsigned char i = 0;EA = 0;						//关闭中断for(i = 0; i < 8; i++){WireBUS = 0;			//主机将总线拉低_nop_();				//2us等待_nop_();				//2us等待WireBUS = 1;			//主机释放总线_nop_();				//2us等待从机向总线上写入数据_nop_();				//2usif(WireBUS == 1)		//主机读取总线上的数据{Temp |= (0x01 << i);}Delay30us();			Delay30us();			//60us等待从机释放总线}EA = 1;						//开启中断return Temp;
}

②OneWire.h文件的代码如下:

#ifndef __OneWire_H
#define __OneWire_H
#include <REGX52.H>	//包含51头文件,里面全是寄存器地址bit OneWire_Reset(void);
void OneWire_Write(unsigned char Byte);
unsigned char OneWire_Read(void);#endif

③DS18B20.c文件的代码如下:

#include "DS18B20.h"unsigned char code RomCode[][8]={{0x28, 0x30, 0xC5, 0xB8, 0x00, 0x00, 0x00, 0x8E},//设备1的ROM码{0x28, 0x31, 0xC5, 0xB8, 0x00, 0x00, 0x00, 0xB9},//设备2的ROM码{0x28, 0x32, 0xC5, 0xB8, 0x00, 0x00, 0x00, 0xE0},//设备3的ROM码{0x28, 0x33, 0xC5, 0xB8, 0x00, 0x00, 0x00, 0xD7} //设备4的ROM码
};/*** 单总线上只有一个DS18B20设备的初始化*/
void DS18B20_Single_Init(void)
{bit ACK;ACK = OneWire_Reset();if(!ACK){OneWire_Write(SKIP_ROM);//跳过ROM}
}/*** 单总线上有多个DS18B20设备的初始化* Routes:哪一个设备(1~4)*/
void DS18B20_Mul_Init(unsigned char Routes)
{unsigned char i = 0;bit ACK;ACK = OneWire_Reset();if(!ACK){OneWire_Write(MATH_ROM);//匹配ROM指令/* 发送匹配的ROM码 */switch(Routes){case 1:for(i = 0;i<8;i++){OneWire_Write(RomCode[0][i]);}break;case 2:for(i = 0;i<8;i++){OneWire_Write(RomCode[1][i]);}break;case 3:for(i = 0;i<8;i++){OneWire_Write(RomCode[2][i]);}break;case 4:for(i = 0;i<8;i++){OneWire_Write(RomCode[3][i]);}break;default:break;}}
}/*** 获取单总线上只有一个DS18B20设备的温度数据*/
float GET_Temp(void)
{unsigned char LSB,MSB;int tempReg;float T;DS18B20_Single_Init();		//初始化OneWire_Write(CONVERT_T);	//启动温度转换DS18B20_Single_Init();		//初始化OneWire_Write(READ_REG);	//读取寄存器LSB = OneWire_Read();		//读取低字节MSB = OneWire_Read();		//读取高字节tempReg = ((int)MSB << 8) | LSB;T = tempReg / 16.0;return T;
}/*** 读取从机的64位ROM码* 设备1:0x8E00000B8C53028* 设备2:0xB900000B8C53128* 设备3:0xE000000B8C53228* 设备4:0xD700000B8C53328*/
void ReadRomCode(unsigned char *RomCode)
{unsigned char i = 0;bit ACK;ACK = OneWire_Reset();if(!ACK){OneWire_Write(RWAD_ROM);//读取ROM指令for(i = 0; i<8; i++){RomCode[i] = OneWire_Read();//读取一个字节,先读取低字节数据}}
}/*** 获取单总线上多个DS18B20中的某个设备的温度* Routes:哪个DS18B20设备(1~4)*/
float GET_MulTemp(unsigned char Routes)
{unsigned char LSB,MSB;int tempReg;float T;DS18B20_Mul_Init(Routes);	//匹配ROM初始化OneWire_Write(CONVERT_T);	//启动温度转换DS18B20_Mul_Init(Routes);	//匹配ROM初始化OneWire_Write(READ_REG);	//读取寄存器LSB = OneWire_Read();		//读取低字节MSB = OneWire_Read();		//读取高字节tempReg = ((int)MSB << 8) | LSB;T = tempReg / 16.0;return T;
}

④DS18B20.h文件的代码如下:

#ifndef __DS18B20_H
#define __DS18B20_H
#include "OneWire.h"/* DS18B20的指令合集 */
//ROM指令
#define SEAECH_ROM 			0xf0	//搜索ROM
#define RWAD_ROM 			0x33	//读取ROM
#define MATH_ROM 			0x55	//匹配ROM
#define SKIP_ROM 			0xcc	//跳过ROM
#define ALARM_SEARCH 		0xec	//搜索报警//寄存器指令
#define CONVERT_T 			0x44	//温度转换
#define WRITET_REG 			0x4e	//写寄存器
#define READ_REG			0xbe	//读取寄存器
#define COPY_REG			0x48	//复制寄存器
#define CALL_E2				0xb8	//粘贴到E2
#define READ_POWR			0xb4	//读取电源模式void DS18B20_Single_Init(void);
void DS18B20_Mul_Init(unsigned char Routes);/* 用户调用的函数 */
float GET_Temp(void);
void ReadRomCode(unsigned char *RomCode);
float GET_MulTemp(unsigned char Routes);#endif

⑤TempMenu.c文件的代码如下:

#include "TempMenu.h"/* 定义6路 CH1~CH4 温度缓存区 */
float TempBuffer[4] = {0};/* 定义通道温度阈值缓存区 */			
char ThreTemp[4] = {10, 10, 10, 10};/*** 温度菜单开机显示*/
void Temp_StartMenu(void)
{LCD_ShowString(1,1,"    TEMP MENU     ");LCD_ShowString(2,1,"      V1.0        ");
}/*** 显示℃字符函数*/
void SHOW_C(unsigned char Hang, unsigned char Lie)
{LCD_ShowChar(Hang, Lie, 0xdf);		//显示°LCD_ShowChar(Hang, Lie + 1, 0x43);	//显示C
}/*** 显示CH1 CH2通道的温度*/
void SHOW_CH1_CH2(void)
{/* 显示CH1通道的温度 */LCD_ShowString(1,1,"CH1:");LCD_ShowFloat(1,6,TempBuffer[0],2,2);SHOW_C(1,12);if(TempBuffer[0] > ThreTemp[0]){LCD_ShowString(1,16,"W");}else{LCD_ShowString(1,16," ");}/* 显示CH2通道的温度 */LCD_ShowString(2,1,"CH2:");LCD_ShowFloat(2,6,TempBuffer[1],2,2);SHOW_C(2,12);if(TempBuffer[1] > ThreTemp[1]){LCD_ShowString(2,16,"W");}else{LCD_ShowString(2,16," ");}
}/*** 显示CH3 CH4通道的温度*/
void SHOW_CH3_CH4(void)
{/* 显示CH3通道的温度 */LCD_ShowString(1,1,"CH3:");LCD_ShowFloat(1,6,TempBuffer[2],2,2);SHOW_C(1,12);if(TempBuffer[2] > ThreTemp[2]){LCD_ShowString(1,16,"W");}else{LCD_ShowString(1,16," ");}/* 显示CH4通道的温度 */LCD_ShowString(2,1,"CH4:");LCD_ShowFloat(2,6,TempBuffer[3],2,2);SHOW_C(2,12);if(TempBuffer[3] > ThreTemp[3]){LCD_ShowString(2,16,"W");}else{LCD_ShowString(2,16," ");}
}/*** 显示设置CH1通道阈值界面*/
void SHOW_SetCH1Temp(void)
{LCD_ShowString(1,1,"     SETING     ");/* 显示被设置CH1通道的温度 */LCD_ShowString(2,1,"CH1:");LCD_ShowFloat(2,6,ThreTemp[0],2,2);SHOW_C(2,12);LCD_ShowString(2,15,"    ");
}/*** 显示设置CH2通道阈值界面*/
void SHOW_SetCH2Temp(void)
{LCD_ShowString(1,1,"     SETING     ");/* 显示被设置CH2通道的温度 */LCD_ShowString(2,1,"CH2:");LCD_ShowFloat(2,6,ThreTemp[1],2,2);SHOW_C(2,12);LCD_ShowString(2,15,"    ");
}/*** 显示设置CH3通道阈值界面*/
void SHOW_SetCH3Temp(void)
{LCD_ShowString(1,1,"     SETING     ");/* 显示被设置CH3通道的温度 */LCD_ShowString(2,1,"CH3:");LCD_ShowFloat(2,6,ThreTemp[2],2,2);SHOW_C(2,12);LCD_ShowString(2,15,"    ");
}/*** 显示设置CH4通道阈值界面*/
void SHOW_SetCH4Temp(void)
{LCD_ShowString(1,1,"     SETING     ");/* 显示被设置CH4通道的温度 */LCD_ShowString(2,1,"CH4:");LCD_ShowFloat(2,6,ThreTemp[3],2,2);SHOW_C(2,12);LCD_ShowString(2,15,"    ");
}

⑥TempMenu.h文件的代码如下:

#ifndef __TempMen_H
#define __TempMen_H
#include "LCD1602.h"void Temp_StartMenu(void);
void SHOW_C(unsigned char Hang, unsigned char Lie);
void SHOW_CH1_CH2(void);
void SHOW_CH3_CH4(void);void SHOW_SetCH1Temp(void);
void SHOW_SetCH2Temp(void);
void SHOW_SetCH3Temp(void);
void SHOW_SetCH4Temp(void);#endif

⑦main.c文件的代码如下:

#include "LCD1602.h"
#include "DS18B20.h"
#include "TempMenu.h"
#include "Key.h"
#include "Delay.h"
#include "Timer.h"static unsigned char Seting_Flag  = 0;	//进入设置模式标志位
static unsigned char SET_Channel  = 0;	//设置模式下通道切换变量
unsigned char Menu_Status = 0;			//状态变量
bit Mode = 0;							//0表示自动模式,1表示手动模式extern float TempBuffer[4];				//温度数据缓存区
extern char ThreTemp[4];				//温度阈值缓存区void KEY_ChangeMenu(void);
void SHOW_TempMenu(void);void main(void)
{unsigned char i = 0;	LCD_Init();	Time0_Intrrupt_Init();Temp_StartMenu();		//显示开机界面Delay_s(2);LCD_WriteCommand(0x01);	//清屏while(1){for(i = 0;i<4;i++){TempBuffer[i] = GET_MulTemp(1+i);	//将每个DS18B20的温度保存到缓存区}KEY_ChangeMenu();SHOW_TempMenu();}
}/*** 按键切换菜单函数*/
void KEY_ChangeMenu(void)
{switch(Key_Scanf()){case 1:									//按键1按下if(!Seting_Flag)					//没有进入设置模式{Menu_Status++;					//按下KEY1改变Menu_Statusif(Menu_Status >= 2 ){Menu_Status = 0;}}else								//进入设置模式,KEY1增加温度阈值{switch(SET_Channel){case 1:ThreTemp[0]++;break;	//增加CH1的温度阈值case 2:ThreTemp[1]++;break;	//增加CH2的温度阈值case 3:ThreTemp[2]++;break;	//增加CH3的温度阈值case 4:ThreTemp[3]++;break;	//增加CH4的温度阈值default:break;}}break;case 2:									//按键2按下if(!Seting_Flag)					//没有进入设置模式{Mode = !Mode;					//切换模式LCD_WriteCommand(0x01);			//清屏if(!Mode)						//Mode = 0,表示自动模式{LCD_ShowString(1, 1, "    Automatic  ");LCD_ShowString(2, 1, "    Automatic  ");}else							//Mode = 1,表示手动模式{LCD_ShowString(1, 1, "     Manual     ");LCD_ShowString(2, 1, "     Manual     ");}Delay_s(1);LCD_WriteCommand(0x01);			//清屏}else								//在设置模式下{switch(SET_Channel)				//按下KEY1减小温度阈值{case 1:ThreTemp[0]--;break;	//减小CH1的温度阈值case 2:ThreTemp[1]--;break;	//减小CH2的温度阈值case 3:ThreTemp[2]--;break;	//减小CH3的温度阈值case 4:ThreTemp[3]--;break;	//减小CH4的温度阈值default:break;}}break;case 3:		if(!Seting_Flag)					//没有进入设置模式{Menu_Status = 0;				//复位显示}else								//在设置模式下{Seting_Flag = 0;				//退出设置模式Mode = 0;						//退出手动模式LCD_WriteCommand(0x01);			//清屏LCD_ShowString(1, 1, "     SET OK     ");LCD_ShowString(2, 1, "     SET OK     ");Delay_s(1);LCD_WriteCommand(0x01);			//清屏}break;case 4:									//按键4按下,切换到设置界面Seting_Flag = 1;					//进入设置模式Mode = 1;							//进入手动模式Menu_Status = 2;	SET_Channel++;if(SET_Channel >= 5){SET_Channel = 1;}break;default:break;}
}/*** 在不同的Menu_Status下的显示不同的界面*/
void SHOW_TempMenu(void)
{switch(Menu_Status){case 0:SHOW_CH1_CH2();break;//显示CH1-CH2通道的温度case 1:SHOW_CH3_CH4();break;//显示CH1-CH2通道的温度case 2:						//显示设置通道的界面switch(SET_Channel){case 1:SHOW_SetCH1Temp();break;//显示设置CH1通道的界面case 2:SHOW_SetCH2Temp();break;//显示设置CH2通道的界面case 3:SHOW_SetCH3Temp();break;//显示设置CH3通道的界面case 4:SHOW_SetCH4Temp();break;//显示设置CH4通道的界面default:break;}break;default:break;}
}

⑧Timer.c文件的代码如下:

#include "Timer.h"/*** 定时器T0的初始化*/
void Time0_Intrrupt_Init(void)
{/* 设置T0的计数器为16,且时钟来源为晶振 TMOD = xxxx 0001 */TMOD &= 0xF0;			//将低4位置0TMOD |= 0x01;			//最低位置1/* 设置定时计数器的初始值,定时1ms */TH0 = ((65535 - (1000 - 1)) >> 8);TL0 = (65535 - (1000 - 1)) & 0x00FF;/* 启动T0 */TF0 = 0;				//清除标志位TR0 = 1;				//启动定时器0/* 开启中断 */PT0 = 1;				//优先级较高ET0 = 1;				//使能定时器溢出中断EA = 1;					//开启总开关
}/********中断服务函数*******/
/*** T0的中断服务函数(每隔1ms对TimeCount加1)*/
static unsigned long TimeCount = 0;
static unsigned long GettimeCon = 0;
static unsigned char TimeSatus = 0;
extern unsigned char Menu_Status;
extern bit Mode;
void Time0_Rountine(void) interrupt 1
{//这里不用清除标志位,硬件会自动清除/* 设置定时计数器的初始值,定时1ms */TH0 = ((65535 - (1000 - 1)) >> 8);TL0 = (65535 - (1000 - 1)) & 0x00FF;TimeCount++;/* 每隔1s改变Menu_Status的值 */switch(TimeSatus){case 0:GettimeCon = TimeCount;TimeSatus = 1;case 1:if(TimeCount - GettimeCon == 1000){GettimeCon = TimeCount;if(!Mode){Menu_Status++;if(Menu_Status >= 2){Menu_Status = 0;}}}break;default:break;}
}/*** 对外暴露TimeCount的值*/
unsigned long Get_TimeCount(void)
{return TimeCount;
}

相关文章:

12【模块学习】DS18B20(二):高级使用

DS18B20 1、改变采样分辨率2、总线上有多个设备的使用2.1、获取总线上单个设备的ROM码2.2、通过匹配ROM指令使用总线上多个设备 3、项目&#xff1a;4路温度检测LCD显示 1、改变采样分辨率 需要改变采样的分辨率&#xff0c;则需要向暂存器的配置寄存器中写入配置参数。在向寄…...

NLP高频面试题(四十三)——什么是人类偏好对齐中的「对齐税」(Alignment Tax)?如何缓解?

一、什么是「对齐税」(Alignment Tax)? 所谓「对齐税」(Alignment Tax),指的是在使人工智能系统符合人类偏好的过程中,所不可避免付出的性能损失或代价。换句话说,当我们迫使AI遵循人类价值观和规范时,AI系统往往无法达到其最大理论性能。这种性能上的妥协和折衷,就…...

线代第二章矩阵第一课:矩阵的概念

一、矩阵的概念 矩阵 i还是表示的是行&#xff0c;j表示的是列&#xff1b;行数未必等于列数 同型矩阵&#xff1a; A,B行数相等&#xff0c;列数相等 矩阵相等&#xff1a; 同型矩阵&#xff0c;且对应元素相等 零矩阵&#xff1a; 所有元素均为0 二、特殊矩阵 方阵 行数…...

如何获取Google Chrome的官方最新下载链接【获取教程】

一、为什么选择官方下载链接 安装谷歌浏览器的最安全方式始终是通过其官方网站。非官方渠道可能存在版本落后、功能缺失&#xff0c;甚至潜藏恶意插件等风险。因此&#xff0c;获取Google Chrome的官方最新下载链接&#xff0c;是保障浏览器安全与性能的重要前提。 此外&…...

软件测试——BUG概念

一、软件测试生命周期 软件测试贯穿于软件的整个生命周期 软件测试的生命周期指测试流程&#xff0c;每个阶段有不同的目标和交付产物 需求分析 从用户角度考虑软件需求是否合理 从技术角度考虑技术上是否可行&#xff0c;是否有优化空间 从测试角度考虑是否存在业务逻辑错误…...

Docker安装 (centos)

1.安装依赖包&#xff1a; sudo yum install -y yum-utils device-mapper-persistent-data lvm2 2.删除已有的 Docker 仓库文件&#xff08;如果有&#xff09;&#xff1a; sudo rm -f /etc/yum.repos.d/docker-ce.repo 3.添加阿里云的 Docker 仓库&#xff1a; sudo yum…...

MySQL数据库 - 存储引擎

存储引擎 此笔记参考黑马教程&#xff0c;仅学习使用&#xff0c;如有侵权&#xff0c;联系必删 文章目录 存储引擎1. MySQL 体系结构2. 存储引擎简介2.1 语法代码演示 3. 存储引擎特点InnoDB介绍特点文件逻辑存储结构 MyISAM介绍特点文件 Memory介绍特点文件 总结 4. 存储引擎…...

【网络篇】UDP协议的封装分用全过程

大家好呀 我是浪前 今天讲解的是网络篇的第二章&#xff1a;UDP协议的封装分用 我们的协议最开始是OSI七层网络协议 这个OSI 七层网络协议 是计算机的大佬写的&#xff0c;但是这个协议一共有七层&#xff0c;太多了太麻烦了&#xff0c;于是我们就把这个七层网络协议就简化为…...

数据结构——布隆过滤器

目录 一、什么是布隆过滤器&#xff1f; 二、布隆过滤器的原理 三、布隆过滤器的特点 一、什么是布隆过滤器&#xff1f; 布隆过滤器是一种空间效率高、适合快速检索的数据结构&#xff0c;用于判断一个元素是否可能存在于一个集合中。它通过使用多个哈希函数和一个位数组来…...

pytorch实现逻辑回归

pytorch实现逻辑回归 数据准备&#xff0c;参数初始化前向计算计算损失计算梯度更新参数 在官网上找到线性函数的公式表达式 import torch from sklearn.datasets import load_iris # from sklearn.model_selection import train_test_split #train_test_split是sklearn中的…...

03-Spring Cloud Gateway 深度解析:从核心原理到生产级网关实践

Spring Cloud Gateway 深度解析&#xff1a;从核心原理到生产级网关实践 一、网关技术演进与 Spring Cloud Gateway 定位 1. 微服务网关的核心价值 作为微服务架构的流量入口&#xff0c;网关承担着 路由转发、流量治理、安全防护 三大核心职能&#xff1a; 统一接入&#…...

Spark-sql编程

创建子模块并添加依赖‌ 在IDEA中创建一个名为Spark-SQL的子模块。 在该子模块的pom.xml文件中添加Spark-SQL的依赖&#xff0c;具体依赖为org.apache.spark:spark-sql_2.12:3.0.0。 编写Spark-SQL测试代码‌ 定义一个User case class&#xff0c;用于表示用户信息&#xf…...

K8s 生产落地

深夜收到报警短信&#xff0c;集群突然宕机——这可能是每个运维人最不愿面对的噩梦。生产级Kubernetes集群的部署&#xff0c;远不是几条命令就能搞定的事情。本文将结合真实踩坑经验&#xff0c;从零拆解一个高可用、高安全、可自愈的Kubernetes生产环境该如何落地。 一、架…...

SnailJob:分布式环境设计的任务调度与重试平台!

背景 近日挖掘到一款名为“SnailJob”的分布式重试开源项目,它旨在解决微服务架构中常见的重试问题。在微服务大行其道的今天&#xff0c;我们经常需要对某个数据请求进行多次尝试。然而&#xff0c;当遇到网络不稳定、外部服务更新或下游服务负载过高等情况时&#xff0c;请求…...

通过WebRTC源码入门OpenGL ES

文章目录 基本概念Vertex和Fragment着色器程序 准备工作getUniformLocation/getAttribLocationglVertexAttribPointer 开始绘制Demo实现 OpenGL SE是一套适用于嵌入式设备的图形API&#xff0c;本文主要介绍如何通过OpenGL SE在Android设备上进行图形绘制&#xff0c;同时我会通…...

面试题:请描述一下你在项目中是如何进行性能优化的?针对哪些方面进行了优化,采取了哪些具体的措施?

目录 1.算法和数据结构优化 2.内存管理优化 3.并发编程优化 4.数据库优化 5.网络优化 6.持续优化与监控 7.总结 现在是企业招聘和求职者的金三银四&#xff0c;每每问到这个主观性问题的时候&#xff0c;都不知道怎么回答&#xff0c;下面就我知道的一些总结一下&#x…...

从零实现富文本编辑器#2-基于MVC模式的编辑器架构设计

在先前的规划中我们是需要实现MVC架构的编辑器&#xff0c;将应用程序分为控制器、模型、视图三个核心组件&#xff0c;通过控制器执行命令时会修改当前的数据模型&#xff0c;进而表现到视图的渲染上。简单来说就是构建一个描述文档结构与内容的数据模型&#xff0c;并且使用自…...

SAP S4HANA embedded analytics

SAP S4HANA embedded analytics...

linux多线(进)程编程——(7)消息队列

前言 现在修真界大家的沟通手段已经越来越丰富了&#xff0c;有了匿名管道&#xff0c;命名管道&#xff0c;共享内存等多种方式。但是随着深入使用人们逐渐发现了这些传音术的局限性。 匿名管道&#xff1a;只能在有血缘关系的修真者&#xff08;进程&#xff09;间使用&…...

STM32 HAL库 实现485通信

一、引言 在工业自动化、智能家居等众多领域中&#xff0c;RS - 485 通信因其长距离、高抗干扰能力等优点被广泛应用。STM32F407 是一款性能强大的微控制器&#xff0c;其丰富的外设资源为实现 RS - 485 通信提供了良好的硬件基础。本文将详细介绍基于 STM32F407 HAL 库实现 R…...

用 Vue 3 + OpenAI API 实现一个智能对话助手(支持上下文、多角色)

文章目录 一、项目背景与功能介绍二、技术选型与准备工作环境准备 三、智能对话助手的实现第一节&#xff1a;封装 OpenAI 接口请求第二节&#xff1a;构建消息上下文结构第三节&#xff1a;构建对话 UI 组件第四节&#xff1a;滚动自动到底部&#xff08;可选优化&#xff09;…...

ollama修改配置使用多GPU,使用EvalScope进行模型压力测试,查看使用负载均衡前后的性能区别

文章目录 省流结论机器配置不同量化模型占用显存1. 创建虚拟环境2. 创建测试jsonl文件3. 新建测试脚本3. 默认加载方式&#xff0c;单卡运行模型3.1 7b模型输出213 tok/s3.1 32b模型输出81 tok/s3.1 70b模型输出43tok/s 4. 使用负载均衡&#xff0c;多卡运行4.1 7b模型输出217t…...

vue3 setup vite 配置跨域了proxy,部署正式环境的替换

在开发环境中使用 Vite 的 proxy 配置来解决跨域问题是一种常见的做法。然而&#xff0c;在部署到正式环境时&#xff0c;通常需要对接口地址进行调整&#xff0c;具体是否需要更改接口名称取决于你的部署环境和后端服务的配置。以下是几种常见的情况和建议&#xff1a; 1. 正…...

目标检测:YOLOv11(Ultralytics)环境配置

1、前言 YOLO11是Ultralytics公司YOLO系列实时目标检测器的最新迭代版本&#xff0c;它以尖端的准确性、速度和效率重新定义了可能实现的性能。在之前YOLO版本取得的显著进步基础上&#xff0c;YOLO11在架构和训练方法上进行了重大改进&#xff0c;使其成为各种计算机视觉任务中…...

如何高效压缩GIF动图?

GIF动图因其兼容性强、易于传播的特点&#xff0c;成为网络交流的热门选择。然而&#xff0c;过大的文件体积常常导致加载缓慢、分享困难等问题。本文将为您详细介绍几种实用的GIF压缩技巧&#xff0c;帮助您在保持画面质量的同时显著减小文件大小。 压缩方法 1. 在线压缩工具…...

视频融合平台EasyCVR可视化AI+视频管理系统,打造轧钢厂智慧安全管理体系

一、背景分析 在轧钢厂&#xff0c;打包机负责线材打包&#xff0c;操作人员需频繁进入内部添加护垫、整理包装、检修调试等。例如&#xff0c;每班产线超过300件&#xff0c;12小时内人员进出打包机区域超过300次。若员工安全意识薄弱、违规操作&#xff0c;未落实安全措施就…...

通过命令行操作把 本地IDE 项目上传到 GitHub(小白快速版)

通过命令行操作把 本地IDE 项目上传到 GitHub&#xff08;小白版&#xff09; 你是不是在用 本地IDE 做项目&#xff0c;但不知道怎么把自己的代码上传到 GitHub&#xff1f;今天我们用最简单的命令行方式&#xff08;不用 SSH、不用复杂配置&#xff09;教你一步一步把本地项…...

【c语言基础学习】qsort快速排序函数介绍与使用

在C语言中&#xff0c;qsort 函数用于对数组进行快速排序。以下是详细的使用方法及示例&#xff1a; 一、函数原型 #include <stdlib.h>void qsort(void *base, size_t nmemb, size_t size, int (*compar)(const void *, const void *) );二、参数说明 参数说明base指向…...

​​​​​​​今日github AI科技工具汇总(20250415更新)

以下是2025年4月15日GitHub上值得关注的AI科技工具汇总及趋势分析,结合最新开源动态与开发者社区热点整理: 一、AI编程工具重大更新 GitHub Copilot Agent Mode 全量发布 核心功能:在VS Code中启用后,可自主完成多文件代码重构、测试驱动开发(TDD)及自修复编译错误,支持…...

程序化广告行业(88/89):广告创意审核的法律红线与平台规则

程序化广告行业&#xff08;88/89&#xff09;&#xff1a;广告创意审核的法律红线与平台规则 在程序化广告的广阔领域中&#xff0c;不断学习和掌握行业规范是我们稳步前行的基石。一直以来&#xff0c;我都期望与大家携手共进&#xff0c;深入探索这个行业的奥秘。今天&…...

前端VUE框架理论与应用(4)

一、计算属性 模板内的表达式非常便利,但是设计它们的初衷是用于简单运算的。在模板中放入太多的逻辑会让模板过重且难以维护。例如: <div id="example">{{ message.split().reverse().join() }}</div> 在这个地方,模板不再是简单的声明式逻辑。你…...

【经验分享】基于Calcite+MyBatis实现多数据库SQL自动适配:从原理到生产实践

基于CalciteMyBatis实现多数据库SQL自动适配&#xff1a;从原理到生产实践 一、引言&#xff1a;多数据库适配的行业痛点 在当今企业IT环境中&#xff0c;数据库异构性已成为常态。根据DB-Engines最新调研&#xff0c;超过78%的企业同时使用两种以上数据库系统。这种多样性带…...

通信算法之265: 无人机系统中的C2链路

在无人机系统设计中&#xff0c;我们经常听到C2链路这个名词&#xff0c;到底什么是C2链路呢&#xff1f;为什么说C2链路是无人机系统中非常重要的环节。 转载&#xff1a; 无人机技术是各种科技技术水平综合发展的结果&#xff0c;包括空气动力&#xff0c;机械设计&#xf…...

浙江大学:DeepSeek如何引领智慧医疗的革新之路?|48页PPT下载方法

导 读INTRODUCTION 随着人工智能技术的飞速发展&#xff0c;DeepSeek等大模型正在引领医疗行业进入一个全新的智慧医疗时代。这些先进的技术不仅正在改变医疗服务的提供方式&#xff0c;还在提高医疗质量和效率方面展现出巨大潜力。 想象一下&#xff0c;当你走进医院&#xff…...

Codeforces Round 1017 (Div. 4)

Codeforces Round 1017 (Div. 4) A. Trippi Troppi AC code: void solve() { string a, b, c; cin >> a >> b >> c;cout << a[0] << b[0] << c[0] << endl; } B. Bobritto Bandito 思路&#xff1a; 倒推模拟即可&#xff0c…...

bash的特性-bash中的引号

在Linux或Unix系统中&#xff0c;Bash&#xff08;Bourne Again SHell&#xff09;作为最常用的命令行解释器之一&#xff0c;提供了强大的功能来处理各种任务。正确使用引号是掌握Bash脚本编写的基础技能之一&#xff0c;它决定了如何解析字符串、变量替换以及特殊字符的行为。…...

ubuntu上SSH防止暴力破解帐号密码

在知道设备ip的情况下&#xff0c;使用 Fail2Ban防止暴力破解 sudo apt install fail2ban 配置 SSH 防护规则 sudo gedit /etc/fail2ban/jail.local jail.local内容如下&#xff1a; [sshd] enabled true port ssh logpath /var/log/auth.log # Ubuntu/Debian maxret…...

【Bluedroid】A2DP Sink播放流程源码分析(二)

接上一篇继续分析&#xff1a;【Bluedroid】A2DP Sink播放流程源码分析(一)_安卓a2dp sink播放流程-CSDN博客 AVDTP接收端&#xff08;Sink&#xff09;流事件处理 bta_av_sink_data_cback 是 Bluedroid 中 A2DP Sink 角色的 AVDTP 数据回调函数&#xff0c;负责处理接收端的…...

【Code】《代码整洁之道》笔记-Chapter16-重构SerialDate

第16章 重构SerialDate 如果你找到JCommon类库&#xff0c;深入该类库&#xff0c;其中有个名为org.jfree.date的程序包。在该程序包中&#xff0c;有个名为SerialDate的类&#xff0c;我们即将剖析这个类。 SerialDate的作者是David Gilbert。David显然是一位经验丰富、能力…...

redis 内存中放哪些数据?

在 Java 开发中,Redis 作为高性能内存数据库,通常用于存储高频访问、低延迟要求、短期有效或需要原子操作的数据。以下是 Redis 内存中常见的数据类型及对应的使用场景,适合面试回答: 1. 缓存数据(高频访问,降低数据库压力) 用户会话(Session):存储用户登录状态、临时…...

【Python使用】嘿马云课堂web完整实战项目第4篇:封装异常处理,封装JSON返回值【附代码文档】

教程总体简介&#xff1a;项目概述 项目背景 项目的功能构架 项目的技术架构 CMS 什么是CMS CMS需求分析与工程搭建 静态门户工程搭建 SSI服务端包含技术 页面预览开发 4 添加“页面预览”链接 页面发布 需求分析 技术方案 测试 环境搭建 数据字典 服务端 前端 数据模型 页面原…...

「数据可视化 D3系列」入门第三章:深入理解 Update-Enter-Exit 模式

深入理解 Update-Enter-Exit 模式 一、数据绑定三态&#xff1a;Update、Enter、Exit三种状态的直观理解 二、基础概念1. Update 选区 - 处理已有元素2. Enter 选区 - 处理新增数据3. Exit 选区 - 处理多余元素 三、完整工作流程四、三种状态的底层原理数据绑定过程解析键函数&…...

中间件--ClickHouse-5--架构设计(分布式架构,列式压缩存储、并行计算)

1、整体架构设计 ClickHouse 采用MPP&#xff08;大规模并行处理&#xff09;架构&#xff0c;支持分布式计算和存储&#xff0c;其核心设计目标是高性能列式分析。 &#xff08;1&#xff09;、存储层 列式存储&#xff1a; 数据按列存储&#xff08;而非传统行式存储&#…...

AgentGPT 在浏览器中组装、配置和部署自主 AI 代理 入门介绍

AI MCP 系列 AgentGPT-01-入门介绍 Browser-use 是连接你的AI代理与浏览器的最简单方式 AI MCP(大模型上下文)-01-入门介绍 AI MCP(大模型上下文)-02-awesome-mcp-servers 精选的 MCP 服务器 AI MCP(大模型上下文)-03-open webui 介绍 是一个可扩展、功能丰富且用户友好的…...

【开源项目】Excel手撕AI算法深入理解(三):Backpropagation、mamba、RNN

项目源码地址&#xff1a;https://github.com/ImagineAILab/ai-by-hand-excel.git 一、Backpropagation 1. 反向传播的本质 反向传播是通过链式法则计算损失函数对网络参数的梯度的高效算法&#xff0c;目的是用梯度下降优化参数。其核心思想是&#xff1a; 前向传播&#xf…...

uniapp的通用页面及组件基本封装

1.基本布局页面 适用于自定义Navbar头部 <template><view class"bar" :style"{height : systemInfo.statusBarHeight px, background: param.barBgColor }"></view><view class"headBox" :style"{ height: param.h…...

Ubuntu和Debian 操作系统的同与异

首先需要说明&#xff1a;Ubuntu 是基于 Debian 操作系统开发的。它们之间的关系如下 起源与发展&#xff1a;Debian 是一个社区驱动的开源 Linux 发行版&#xff0c;始于 1993 年&#xff0c;是最早的 Linux 发行版之一&#xff0c;以其稳定性和自由软件政策著称。Ubuntu 是基…...

【android bluetooth 协议分析 21】【ble 介绍 1】【什么是RPA】

通俗易懂地讲解一下 BLE&#xff08;低功耗蓝牙&#xff09;中的 Resolvable Private Address&#xff08;RPA&#xff0c;可解析私有地址&#xff09;。 1. 一句话理解 RPA 是一种“临时的、隐私保护的蓝牙设备地址”&#xff0c;别人无法随便追踪你&#xff0c;但“授权的设…...

狂神SQL学习笔记九:MyISAM 和 lnnoDB 区别

show create database school –查看创建数据库的语句 show create table student – 查看student数据表的定义语句 desc student –显示表的结构 MYISAMINNODB事务支持不支持支持数据行锁定不支持支持行锁定外键不支持支持全文索引支持不支持表空间的大小较小较大&#x…...

深度学习--神经网络的构造

在当今数字化时代&#xff0c;深度学习已然成为人工智能领域中最为耀眼的明星。而神经网络作为深度学习的核心架构&#xff0c;其构造方式决定了模型的性能与应用效果。本文将深入探讨深度学习神经网络的构造&#xff0c;带您领略这一前沿技术的奥秘。​ 一、神经网络基础概念…...