STM32应用开发——BH1750光照传感器详解

STM32应用开发——BH1750光照传感器详解

目录

  • STM32应用开发——BH1750光照传感器详解
    • 前言
    • 1 硬件介绍
      • 1.1 BH1750简介
      • 1.2 硬件接线
    • 2 软件编程
      • 2.1 软件原理
        • 2.1.1 IIC设备地址
        • 2.1.2 IIC读写
        • 2.1.3 BH1750指令集
        • 2.1.4 BH1750工作流程
        • 2.1.5 BH1750测量模式
      • 2.2 测试代码
      • 2.3 运行测试
    • 结束语

前言

几年前我发布了一篇关于STM32+BH1750光照传感器的博客,因为大学时期经验欠缺,无论是代码还是博客,都有很多不足之处,也收到了非常多同学的反馈。于是我重新整理了代码和文章,这是一个全新版本。

1 硬件介绍

1.1 BH1750简介

BH1750FVI 是一种用于两线式串行总线接口的数字型光强度传感器集成电路。这种集成电路可以根据收集的光线强度数据来调整液晶或者键盘背景灯的亮度。利用它的高分辨率可以探测较大范围的光强度变化。

注:这个模块只适用于室内环境或者学习使用,户外场景下会超量程。

BH1750的引脚如下:

引脚号名称功能
1VCC电源正
2ADDR地址端口
3GND电源负
4SDAIIC数据线
5DVIIIC端口参考电压
6SCLIIC时钟线

注:上述引脚指的是芯片的引脚,如果用的是某宝买的那种传感器模式,引出来的排针引脚排列是不同的。

参考外围电路如下:
在这里插入图片描述

1.2 硬件接线

本文使用STM32F103作为主控MCU,STM32和BH1750的引脚连接如下表:

STM32BH1750功能
VCCVCC电源正,3.3V供电
GNDGND电源负
PA4SCLIIC时钟线,必须外接上拉电阻
PA5SDAIIC数据线,必须外接上拉电阻
GNDADDR地址端口

注:BH1750用的是模块,模块上已经有接上拉电阻了,因此STM32这边就不需要再接了。另外,ADDR引脚默认有一个下拉电阻,因此不接地其实也是没关系的。

BH1750模块的电路图如下:
在这里插入图片描述

2 软件编程

2.1 软件原理

BH1750是一个IIC设备,通讯协议遵循标准IIC协议。只需要着重关注设备地址,发送命令,读取寄存器即可。

2.1.1 IIC设备地址

所有IIC设备都有一个专属的设备地址,BH1750也不例外,BH1750一共有2个设备地址,可以通过芯片的ADDR引脚切换。
数据手册原文如下:
在这里插入图片描述
翻译过来的话,设备地址的配置如下:

ADDR引脚电平7bit地址8bit地址
高电平0x230x46
低电平0x5C0xB8

注:这里解释一下7bit地址和8bit地址。
IIC设备的地址一般来说都只有7位,也就是7bit地址,BH1750数据手册上面写的也是7bit地址。
但是设备地址并不是单独使用的,在地址后面需要补1个读写位(不懂的先看下IIC通信协议),也就相当于把7bit的地址左移了1位,那么得到的值就是8bit地址。
所以,在IIC进行读写的时候,要用7bit地址还是8bit地址取决于你这个读写函数里面有没有对这个地址进行移位操作。

2.1.2 IIC读写

1、IIC写入流程。
在这里插入图片描述
时序解释:先发送设备地址+读写位,再发送指令数据。

题外话:
大多数IIC设备,在发送的这串数据中,往往会把第1个字节的数据作为1个寄存器地址(有些也叫偏移),随后才是真正的数据。这样一来,就可以通过1个字节或多个字节的寄存器地址,来实现数据和命令的扩展。
不过BH1750可能是因为功能比较简单,它没有采用这种方式,读写似乎都在同一个寄存器里面操作。

2、IIC读取流程。
在这里插入图片描述
时序解释:先发送设备地址+读写位,随后读取两个数据(其中高位数据在前,低位数据在后)。

题外话:
这个读取的流程跟绝大多数IIC设备的读取流程是一样的。

2.1.3 BH1750指令集

在初始化BH1750时,通过发送1个字节的指令即可配置BH1750的模式。

详细指令集如下表:
在这里插入图片描述

2.1.4 BH1750工作流程

根据数据手册的描述,配置流程如下图:

在这里插入图片描述
总结一下这个流程:
第1步:给BH1750供电。
第2步:BH1750上电后默认为断电模式(此断电模式不是说芯片没有电,而是芯片没有进入工作模式)。
第3步:通过发送指令,把BH1750配置为通电模式(此时芯片进入工作模式)。
第4步:发送测量指令(测量方式有多种,详细信息看上面2.1.3的指令集)。
第5步:读取测量结果并转换成光照值。

按照上面这个流程走,就可以使BH1750正常工作。

2.1.5 BH1750测量模式

BH1750有6种测量模式,每种模式有各自的特点,详见下表:

测量模式精度测量时间备注
一次H分辨率模式1 lx120ms该模式配置完成后会自动进行一次测量,测量完成后会切换到断电模式
一次H分辨率模式20.5 lx120ms该模式配置完成后会自动进行一次测量,测量完成后会切换到断电模式
一次L分辨率模式4 lx16ms该模式配置完成后会自动进行一次测量,测量完成后会切换到断电模式
连续H分辨率模式1 lx120ms该模式配置完成后会自动进行连续测量,无需重复配置
连续H分辨率模式20.5 lx120ms该模式配置完成后会自动进行连续测量,无需重复配置
连续L分辨率模式4 lx16ms该模式配置完成后会自动进行连续测量,无需重复配置

总结:
L分辨率模式采集时间短,但精度差,适用于采集光照变化大且变化非常快的场景。
H分辨率模式采集时间长,但精度高,适用于光照变化速度不快的场景。
一次采集模式适用于采集间隔时间长或者需要省电的场景。
连续采集模式适用于对设备节能没有要求的大多数场景。

2.2 测试代码

根据上述原理,编写测试代码,主要的代码清单如下:

文件名代码内容
iic_software.h定义了软件IIC所需的引脚定义和电平设置,方便修改IO或者移植
iic_software.c软件IIC代码主体
bh1750.h定义了BH1750的相关信息,如设备地址,命令等
bh1750.cBH1750驱动主体,底层调用软件IIC接口
uart.c串口主体,用来打印测量过程和结果
main.c主函数

注:除了串口的代码,其他代码全部都在下面贴出来了。串口的教程很多,这里就不细说了,本文主要介绍如何驱动BH1750,尝试了几种测量模式,结果都由串口打印出来,不需要使用串口的话注释掉即可,如果需要现在在LCD屏或者OLED屏,请自行增加这部分的代码。

测试示例代码如下:

iic_software.h :

#ifndef __IIC_SOFTWARE_H__
#define __IIC_SOFTWARE_H__

#include "stm32f10x.h"
#include "stm32f10x_gpio.h"

// IIC SCL引脚配置
#define IIC_SCL_CLOCK   RCC_APB2Periph_GPIOA     // 时钟
#define IIC_SCL_PORT    GPIOA                    // 端口
#define IIC_SCL_PIN     GPIO_Pin_4               // 引脚号
// IIC SCL电平设置
#define SET_IIC_SCL(s)  s > 0 ? GPIO_SetBits(IIC_SCL_PORT, IIC_SCL_PIN) : GPIO_ResetBits(IIC_SCL_PORT, IIC_SCL_PIN)

// IIC SDA引脚配置
#define IIC_SDA_CLOCK   RCC_APB2Periph_GPIOA     // 时钟
#define IIC_SDA_PORT    GPIOA                    // 端口
#define IIC_SDA_PIN     GPIO_Pin_5               // 引脚号
// IIC SDA电平设置
#define SET_IIC_SDA(s)  s > 0 ? GPIO_SetBits(IIC_SDA_PORT, IIC_SDA_PIN) : GPIO_ResetBits(IIC_SDA_PORT, IIC_SDA_PIN)  
#define READ_IIC_SDA    GPIO_ReadInputDataBit(IIC_SDA_PORT, IIC_SDA_PIN)

void iic_init(void);
uint8_t iic_write_bytes(uint8_t addr, uint8_t *buf, uint8_t buf_size);
uint8_t iic_receive_bytes(uint8_t addr, uint8_t *buf, uint8_t buf_size);

#endif

iic_software.c :

#include "iic_software.h"
#include "delay.h"
#include "stdio.h"

/* IIC软件模拟时序延时函数 */
void iic_delay(uint16_t us)
{
    delay_us(us);
}

/* IIC起始信号 */
void set_iic_sda_mode(uint8_t mode)
{
    GPIO_InitTypeDef GPIO_InitStruct;
    if(mode > 0)
    {// 设置为输出模式
        GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_OD; // 开漏或推挽,外部需要接上拉电阻
    }
    else
    {// 设置为输入模式
        GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IPU; // 浮空或上拉,外部需要接上拉电阻
    }
    GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitStruct.GPIO_Pin = IIC_SDA_PIN;
    GPIO_Init(IIC_SDA_PORT, &GPIO_InitStruct);
}

/* IIC起始信号 */
void iic_start(void)
{
    SET_IIC_SDA(1);
    SET_IIC_SCL(1);
    iic_delay(5);
    SET_IIC_SDA(0);     
    SET_IIC_SCL(0);          
    iic_delay(5);  
}

/* IIC停止信号 */
void iic_stop(void)
{
    SET_IIC_SCL(0);
    SET_IIC_SDA(0);                
    iic_delay(5);                    
    SET_IIC_SCL(1);           
    SET_IIC_SDA(1);                  
    iic_delay(5);
}

/* IIC发送应答信号 */
uint8_t iic_send_ack(int ack)
{
    set_iic_sda_mode(1);
    if(ack == 1)
    {// 发送ACk
        SET_IIC_SDA(1); 
    }
    else if(ack == 0)
    {// 发送NACK
        SET_IIC_SDA(0); 
    }
    else
    {
        return 0;  // 入参有误,发送失败
    }         
    SET_IIC_SCL(1);     
    iic_delay(5);     
    SET_IIC_SCL(0);     
    iic_delay(5);    

    return 1;  // 发送成功
}

/* IIC接收应答信号 */
uint8_t iic_wait_ack(void)
{
    uint8_t ack = 0;
    uint8_t timeout = 5;

    SET_IIC_SDA(1); 
    set_iic_sda_mode(0);  // SDA输入模式
    SET_IIC_SCL(1);           
    iic_delay(5);  
    while(timeout--)       
    {// 等待从设备发送ACK
        if(READ_IIC_SDA == 0)
        {// 读到应答信号
            ack = 1;  
        }
        else
        {// 没有读到应答信号,继续等待
            iic_delay(1);
            if(timeout == 0)
            {// 等待超时
                ack = 0; 
            }
        }
    }           
    SET_IIC_SCL(0);             
    iic_delay(5);        
    set_iic_sda_mode(1); // SDA输出模式
    
    return ack;
}

/* IIC总线发送1个字节数据 */
uint8_t iic_send_byte(uint8_t dat)
{
    uint8_t i;
    for (i = 0; i < 8; i++)
    {
        if(0x80 & dat)
        {
            SET_IIC_SDA(1); 
        }
        else
        {
            SET_IIC_SDA(0); 
        }
        dat <<= 1;
        SET_IIC_SCL(1);          
        iic_delay(5);             
        SET_IIC_SCL(0); 
        iic_delay(5);
    }

    return iic_wait_ack();  // 返回从设备应答信号
}

/* IIC总线接收1个字节数据 */
uint8_t iic_receive_byte(void)
{
    uint8_t i;
    uint8_t dat = 0;
    uint8_t bit;

    set_iic_sda_mode(0);  // SDA输入模式
    for (i = 0; i < 8; i++)
    {
        dat <<= 1;
        SET_IIC_SCL(1);
        iic_delay(5);
        if(READ_IIC_SDA == 1)
        {
            bit = 0X01;
        }
        else
        {
            bit = 0x00;  
        }
        dat |= bit;        //读数据    
        SET_IIC_SCL(0);
        iic_delay(5);
    }        
    set_iic_sda_mode(1); // SDA输出模式

    return dat;
}

/* IIC发送多个数据 */
uint8_t iic_write_bytes(uint8_t addr, uint8_t *buf, uint8_t buf_size)
{
    uint8_t i;
    uint8_t result = 0;

    iic_start();                   // 起始信号
    if(iic_send_byte(addr << 1))   // 发送设备地址(7bit地址)
    {// 收到应答,发送成功
        for (i = 0; i < buf_size; i++)  // 发送数据
        {
            if(iic_send_byte(buf[i]))
            {// 收到应答,发送成功
                result = 1;
            }
            else
            {// 没有收到应答,发送失败
                result = 0; 
            }
        }
    }
    iic_stop();                   // 发送停止信号

    return result;
}

/* IIC接收多个数据 */
uint8_t iic_receive_bytes(uint8_t addr, uint8_t *buf, uint8_t buf_size)
{
    uint8_t i;    
    uint8_t result = 0;

    iic_start();                        // 起始信号
    if(iic_send_byte((addr << 1) | 1))  // 发送设备地址(7bit地址)
    {
        for (i = 0; i < buf_size; i++)    // 连续读取数据
        {
            *buf++ = iic_receive_byte(); 
            if (i == buf_size - 1)
            {
                iic_send_ack(1);   // 最后一个数据需要回NACK
            }
            else
            {        
                iic_send_ack(0);   // 发送ACK
            }
        }
        result = 1;
    }
    iic_stop();                // 停止信号

	return result;
}

/* IIC初始化 */
void iic_init(void)
{
    GPIO_InitTypeDef GPIO_InitStruct;

    RCC_APB2PeriphClockCmd(IIC_SCL_CLOCK, ENABLE); 
    GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP;  
    GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitStruct.GPIO_Pin = IIC_SCL_PIN;
    GPIO_Init(IIC_SCL_PORT, &GPIO_InitStruct); 

    RCC_APB2PeriphClockCmd(IIC_SDA_CLOCK, ENABLE); 
    GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP;  
    GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitStruct.GPIO_Pin = IIC_SDA_PIN;
    GPIO_Init(IIC_SDA_PORT, &GPIO_InitStruct); 
}

bh1750.h :

#ifndef __BH1750_H__
#define __BH1750_H__

#include "stm32f10x.h"

#define BH1750_ADDRESS_LOW      0x23    // addr low  7bit:0x23 8bit:0x46
#define BH1750_ADDRESS_HIGH     0x5C    // addr high 7bit:0x5C 8bit:0xB8

/*bh1750 registers define */
#define BH1750_POWER_ON			0x01	// power on
#define BH1750_POWER_DOWN   	0x00	// power down
#define BH1750_RESET			0x07	// reset	
#define BH1750_CON_H_RES_MODE	0x10	// Continuously H-Resolution Mode
#define BH1750_CON_H_RES_MODE2	0x11	// Continuously H-Resolution Mode2 
#define BH1750_CON_L_RES_MODE	0x13	// Continuously L-Resolution Mode
#define BH1750_ONE_H_RES_MODE	0x20	// One Time H-Resolution Mode
#define BH1750_ONE_H_RES_MODE2	0x21	// One Time H-Resolution Mode2
#define BH1750_ONE_L_RES_MODE	0x23	// One Time L-Resolution Mode

uint8_t bh1750_init(void);
void bh1750_read_example(void);

#endif

bh1750.c :

#include "bh1750.h"
#include "iic_software.h"
#include "delay.h"

#define LOG_ENABLE

#ifdef LOG_ENABLE
    #include "stdio.h"
    #define LOG   printf
#else
    #define LOG(format, ...)    
#endif

uint8_t current_mode;    // BH1750的测量模式
float current_light;     // BH1750的测量光照值

// BH1750延时函数
void bh1750_delay(uint16_t ms)
{// ms级延时,BH1750每次测量都需要时间,该函数用于等待测量结果
    delay_ms(ms);
}

// 写命令
uint8_t bh1750_write_cmd(uint8_t cmd)
{
    return iic_write_bytes(BH1750_ADDRESS_LOW, &cmd, 1);
}

// 写寄存器
uint8_t bh1750_read_regs(uint8_t *buf, uint8_t buf_size)
{
    return iic_receive_bytes(BH1750_ADDRESS_LOW, buf, buf_size);
}

// 复位
uint8_t bh1750_reset(void)
{
    return bh1750_write_cmd(BH1750_RESET);
}
// 打开电源
uint8_t bh1750_power_on(void)
{
    return bh1750_write_cmd(BH1750_POWER_ON);
}

// 关闭电源
uint8_t bh1750_power_down(void)
{
    return bh1750_write_cmd(BH1750_POWER_DOWN);
}

// 设置测量模式
uint8_t bh1750_set_measure_mode(uint8_t mode)
{
    uint8_t result = 0;

    if(bh1750_write_cmd(mode))
    {
        result =  1;
    }
    return result;
}

// 单次读取光照值
uint8_t bh1750_single_read_light(uint8_t mode, float *light)
{// 单次测量模式在测量后会自动设置为断电模式   
    uint8_t temp[2];
    uint8_t result = 0;
    
    if(mode != BH1750_ONE_H_RES_MODE && mode != BH1750_ONE_H_RES_MODE2 && mode != BH1750_ONE_L_RES_MODE)
    {
        LOG("bh1750 single read measure mode error! mode:0x%02x\n", mode);
        return result;
    }
    if(bh1750_set_measure_mode(mode)) // 每次采集前先设置模式
    {
        LOG("bh1750 set measure mode success! mode:0x%02x\n", mode);
        current_mode = mode;
        switch (mode)
        {
        case BH1750_ONE_H_RES_MODE:  // 单次H分辨率模式(精度1lx,测量时间120ms)
            bh1750_delay(120);  // 等待采集完成
            break;
        case BH1750_ONE_H_RES_MODE2: // 单次H分辨率模式(精度0.5lx,测量时间120ms)
            bh1750_delay(120);  // 等待采集完成
            break;
        case BH1750_ONE_L_RES_MODE:  // 单次L分辨率模式(精度4lx,测量时间16ms)
            bh1750_delay(16);  // 等待采集完成
            break;
        default:
            break;
        }
        if(bh1750_read_regs(temp, 2))  // 读取测量结果
        {
            *light = ((float)((temp[0] << 8) + temp[1]) / 1.2); // 换算成光照值
            result = 1;
        }
        else
        {
            LOG("bh1750 read light failed!");
        }
    }
    else
    {
        LOG("bh1750 set measure mode failed! mode:0x%02x\n", mode);
        return result;
    }
    
    return result;
}

// 连续读取光照值
uint8_t bh1750_continuous_read_light(uint8_t mode, float *light)
{   
    uint8_t temp[2];
    uint8_t result = 0;
    
    if(mode != BH1750_CON_H_RES_MODE && mode != BH1750_CON_H_RES_MODE2 && mode != BH1750_CON_L_RES_MODE)
    {
        LOG("bh1750 continuous read measure mode error! mode:0x%02x\n", mode);
        return result;
    }

    if(mode != current_mode)
    {// 要使用的测量模式和BH1750当前的模式不同,则配置成相同模式
        if(bh1750_set_measure_mode(mode))
        {
            LOG("bh1750 set measure mode success! mode:0x%02x\n", mode);
            current_mode = mode;
        }
        else
        {// 模式设置失败
            LOG("bh1750 set measure mode failed! mode:0x%02x\n", mode);
            return result;
        }
        switch (mode)
        {
        case BH1750_CON_H_RES_MODE:  // 连续H分辨率模式(精度1lx,测量时间120ms)
            bh1750_delay(120);  // 等待采集完成
            break;
        case BH1750_CON_H_RES_MODE2: // 连续H分辨率模式(精度0.5lx,测量时间120ms)
            bh1750_delay(120);  // 等待采集完成
            break;
        case BH1750_CON_L_RES_MODE:  // 连续L分辨率模式(精度4lx,测量时间16ms)
            bh1750_delay(16);  // 等待采集完成
            break;
        default:
            break;
        }
    }
    if(bh1750_read_regs(temp, 2))  // 读取测量结果
    {
        *light = ((float)((temp[0] << 8) + temp[1]) / 1.2); // 换算成光照值
        result = 1;
    }
    else
    {
        LOG("bh1750 read light failed!");
    }
    
    return result;
}

// BH1750初始化
uint8_t bh1750_init(void)
{
    uint8_t result = 0;
    iic_init();        // IIC初始化
    result = bh1750_power_on(); // 打开BH1750电源
    current_mode = 0;
    return result;
}

// 参考例程:使用BH1750读取光照值
void bh1750_read_example(void)
{
#if 1
    // 单次采集模式
    if(bh1750_single_read_light(BH1750_ONE_H_RES_MODE2, &current_light))
    {
        LOG("bh1750 single read light: %0.1f\n", current_light);
    }
    bh1750_delay(100);
#else
    // 连续采集模式
    if(bh1750_continuous_read_light(BH1750_CON_H_RES_MODE2, &current_light))
    {
        LOG("bh1750 continuous read light: %0.1f\n", current_light);
    }
    bh1750_delay(120); // 注:因为连续读取函数里面没有做延迟等待处理,因此这里的等待时间如果小于测量时间,那么读取到的值有可能是上一轮测量的值
#endif
}

main.c :

#include "delay.h"
#include "sys.h"
#include "usart.h"
#include "bh1750.h"

int main(void)
{ 
    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
    delay_init();              
    uart_init(115200);      
    bh1750_init();
    while(1)
    {
        bh1750_read_example();
    }        
}    

2.3 运行测试

通过逻辑分析仪抓取IIC通讯的波形,分别测试了一次H分辨率模式2连续H分辨率模式2,结果如下:

1、一次H分辨率模式2时序测量
初始化设备:
先发送通电命令(0x01),再设置为单次 H 分辨率模式 2(0x21)。
请添加图片描述
读取光照值(设备地址为0x23):
在这里插入图片描述
串口打印结果:
在这里插入图片描述

2、连续H分辨率模式2时序测量
初始化设备:
先发送通电命令(0x01),再设置为连续 H 分辨率模式 2(0x11)。
在这里插入图片描述

读取光照值(设备地址为0x23):
在这里插入图片描述
串口打印结果:
在这里插入图片描述

3、其他测量
测量IIC时钟周期:
软件模拟的CLK周期约为13us,换算成频率约76.9kHz。
IIC参考时钟是100kHz,不过一般小于400kHz都是没什么问题的,需要调快的话可以修改上面模拟IIC收发函数的CLK延时时间来实现。
在这里插入图片描述
测试结果:IIC波形没有异常,串口结果没有异常,BH1750工作一切正常。

结束语

关于STM32如何驱动BH1750的讲解就到这里,如果还有什么问题,欢迎在评论区留言。

源码下载:
链接:https://pan.baidu.com/s/1aX2bYBAOgnkBlL2lzmGYjg
提取码:1234

如果这篇文章能够帮到你,就…你懂的。
在这里插入图片描述

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

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

相关文章

2024基于PHP开发的微信抖音小程序点餐系统开发源代码案例

最近新开发了一套小程序点餐系统&#xff0c;用户点餐之后可以选择堂食或者是外卖到家&#xff0c;这套系统主要功能有&#xff0c;产品展示&#xff0c;支付系统&#xff0c;外卖配送&#xff0c;用户系统&#xff0c;积分系统&#xff0c;商家管理系统&#xff0c;抽奖系统&a…

STM32 CAN过滤器细节

STM32 CAN过滤器细节 简介 每组筛选器包含2个32位的寄存器&#xff0c;分别为CAN_FxR1和CAN_FxR2&#xff0c;它们用来存储要筛选的ID或掩码 四种模式 模式说明32位掩码模式CAN_FxR1存储ID&#xff0c; CAN_FxR2存储哪个位必须要与CAN_FxR1中的ID一致 &#xff0c; 2个寄存器…

具有图形化衬底与空气腔反射镜混合结构的深紫外Micro-LED阵列芯片

具有倾斜侧壁结构的深紫外Micro-LED的侧壁反射率是影响器件光提取效率的重要因素。由于TM模式偏振光在发生全反射时&#xff0c;产生的倏逝波诱导的金属表面等离子激元降低了倾斜侧壁处的集成全向反射镜&#xff08;ODR&#xff09;的反射率&#xff0c;从而导致光提取效率降低…

【安全】查杀linux挖矿病毒 kswapd0

中毒现象 高cpu占用&#xff0c;使用top命令查看cpu使用率长时间50%以上&#xff0c;cpu占用异常的进程八成就是挖矿病毒进程 此病毒隐藏了自己&#xff0c;top命令无法查看到挖矿病毒进程&#xff0c;可通过sysdig命令找到隐藏进程 安装sysdig curl -s https://s3.amazonaw…

java大作业(9)--实现银行基本操作(第一遍)

一.题目&#xff1a; 二.代码&#xff1a; 实现代码&#xff1a; import java.util.Date; //银行账户类 class Account{public String accountid;public String name;public double balance;public Date creatTime;public Account(String accountid,String name, double bala…

虚拟天空解决方案,创造出令人惊叹的换天效果

在汽车视频领域&#xff0c;如何打破传统拍摄限制&#xff0c;呈现出更具创意和想象力的画面&#xff0c;成为众多企业和创作者追求的目标。美摄科技作为业界领先的视频技术提供商&#xff0c;凭借其强大的AI技术和三维渲染引擎&#xff0c;推出了全新的虚拟天空解决方案&#…

MediaStream使用webRtc多窗口传递

最近在做音视频通话&#xff0c;有个需求是把当前会话弄到另一个窗口单独展示&#xff0c;但是会话是属于主窗口的&#xff0c;多窗口通信目前不能直接传递对象&#xff0c;所以想着使用webRtc在主窗口和兄弟窗口建立连接&#xff0c;把主窗口建立会话得到的MediaStream传递给兄…

分布式搭载博客网站

一.运行环境&#xff1a; IP主机名系统服务192.168.118.128Server-WebLinuxWeb192.168.118.131Server-NFS-DNSLinuxNFS/DNS 二.基础配置 1. 配置主机名&#xff0c;hosts映射 [rootserver ~]# hostnamectl set-hostname Server-Web [rootserver ~]# hostname Server-Web [r…

大模型LLM架构--Decoder-Only、Encoder-Only、Encoder-Decoder

目录 1 LLM演变进化树 2 每种架构的优缺点 2.1 Decoder-Only 架构 2.2 Encoder-Only 2.3 Encoder-Decoder 参考文献&#xff1a; 1 LLM演变进化树 基于 Transformer 模型以非灰色显示&#xff1a;decoder-only 模型在右边的浅蓝色分支&#xff0c;encoder-only 模型在粉色…

【学习】测试新项目该如何高效的展开测试?需要做哪些规划?

当我们收到测试项目时&#xff0c;如何高效地展开测试是我们作为测试人员所要面临的一大挑战。测试是软件开发过程中不可或缺的一环&#xff0c;它确保了产品的质量&#xff0c;降低了出现问题的风险&#xff0c;提高了用户的满意度。因此&#xff0c;我们需要制定合理的测试计…

操作教程丨MaxKB+Ollama:快速构建基于大语言模型的本地知识库问答系统

2024年4月12日&#xff0c;1Panel开源项目组正式对外介绍了其官方出品的开源子项目——MaxKB&#xff08;github.com/1Panel-dev/MaxKB&#xff09;。MaxKB是一款基于LLM&#xff08;Large Language Model&#xff09;大语言模型的知识库问答系统。MaxKB的产品命名内涵为“Max …

java对接IPFS系统-以nft.storage为列

引言 之前我们已经说过了、NFT.Storage是一个基于IPFS的分布式存储服务&#xff0c;专门用于存储和管理非同质化代币&#xff08;NFT&#xff09;相关的数据和资产。它是由Protocol Labs和Pinata共同推出的服务。今天我们基于nft.storage为列、使用java对接打通这个ipfs分布式存…

成为程序员后的领悟与展望-ApiHug

&#x1f917; ApiHug {Postman|Swagger|Api...} 快↑ 准√ 省↓ GitHub - apihug/apihug.com: All abou the Apihug apihug.com: 有爱&#xff0c;有温度&#xff0c;有质量&#xff0c;有信任ApiHug - API design Copilot - IntelliJ IDEs Plugin | Marketplace 选择一个…

【代码】Python3|Requests 库怎么继承 Selenium 的 Headers (2024,Chrome)

本文使用的版本&#xff1a; Chrome 124Python 12Selenium 4.19.0 版本过旧可能会出现问题&#xff0c;但只要别差异太大&#xff0c;就可以看本文&#xff0c;因为本文对新老版本都有讲解。 文章目录 1 难点解析和具体思路2 注意事项2.1 PDF 资源获取时注意事项2.2 Capabiliti…

关于老iPad 能够重新使用经过的一些列折腾

背景 搞了一台IPad air一代给家里老人看戏曲或者电视用,芯片是A7处理器,目前IOS系统是IOS12,也就是能支持的最后一个版本。并且可能是之前刷机问题,IPad基带丢失,显示无法连接激活服务器,无法进入系统。 本人没有MAC设备,没有相关越狱经验,没有黑苹果经验,一切都是从头…

制冷铜管焊接介绍

铜管是制冷装置的重要原材料&#xff0c;它主要有两种用途&#xff1a;①制作换热器。②制作连接管道和管件。常用的焊料类型有铜磷焊料、银铜焊料、铜锌焊料等。在焊接时要根据管道材料的特点&#xff0c;正确的选择焊料及熟练的操作&#xff0c;以确保焊接的质量。 1.1对同类…

基于springboot实现图书进销存管理系统项目【项目源码+论文说明】计算机毕业设计

基于springboot实现图书进销存管理系统演示 摘要 随着信息技术在管理上越来越深入而广泛的应用&#xff0c;管理信息系统的实施在技术上已逐步成熟。本文介绍了图书进销存管理系统的开发全过程。通过分析图书进销存管理系统管理的不足&#xff0c;创建了一个计算机管理图书进销…

QML QtObject轻量级非可视化元素

QtObject 理论1. 父指针形式代指子类2. 自定义组件中定义一些私有属性 理论 QtObject类型是一个非常轻量级且非可视元素&#xff0c;它只包含objectName属性&#xff0c;其本质上是QObject。 用途一般是两个&#xff1a; 父指针形式代指子类&#xff1b;自定义组件中定义一些…

Java基于SpringBoot+Vue的蜗牛兼职网系统的研究与实现

博主介绍&#xff1a;✌程序员徐师兄、7年大厂程序员经历。全网粉丝12w、csdn博客专家、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ &#x1f345;文末获取源码联系&#x1f345; &#x1f447;&#x1f3fb; 精彩专栏推荐订阅&#x1f447;…

Python零基础从小白打怪升级中~~~~~~~多线程

线程安全和锁 一、全局解释器锁 首先需要明确的一点是GIL并不是Python的特性&#xff0c;它是在实现Python解析器(CPython)时所引入的一个概念。 GIL全称global interpreter lock&#xff0c;全局解释器锁。 每个线程在执行的时候都需要先获取GIL&#xff0c;保证同一时刻只…