nRF52832——内部温度传感器与随机数产生

nRF52832——内部温度传感器与随机数产生

  • 内部温度传感器
    • 温度传感寄存器
    • 温度传感器电气特征
    • 温度传感器库函数编程
  • 随机数产生器
    • 随机数发生器寄存器
    • 随机数发生器库函数编程
      • 库函数使用流程
      • RNG 工程搭建使用


内部温度传感器

在 nrf52xx 系列芯片内部,包含一个内部温度传感器。在一些恶劣的应用环境下面,可以通过检测芯片内部温度而感知设备的工作环境温度,如果温度过高或者过低了则马上睡眠或者停止运转。 可以保证您的设备工作的可靠性。

内部温度传感器的主要功能是测量芯片温度,但是如果外部应用需要测量温度也可以使用。因为芯片外接负载一定的情况下,那么芯片的发热也基本稳定,相对于外界的温度而言,这个偏差值也是基本稳定的,这时可以通过线性补偿来实现应用。

这里列出的是温度传感器的主要功能:

  • 温度范围大于或等于设备的工作温度
  • 分辨率为 0.25 度

通过触发 START 任务启动 TEMP 温度传感器。温度测量完成后,将生成 DATARDY 事件,并可从 TEMP 寄存器读取测量结果。要达到电气规范中规定的测量精度,必须选择外部晶体振荡器作为HFCLK 源。 温度测量完成后,TEMP 这部分模拟电子设备掉电以节省电力。TEMP 仅支持一次性操作,这意味着必须使用 START 任务显式启动每个 TEMP 测量。

温度传感寄存器

内部温度传感器作为外部设备,基础地址为 0x4000C000,其寄存器描述如表
在这里插入图片描述
在这里插入图片描述
对应上面的寄存器,具体介绍以下几个寄存器,说明如下:

INTENSET 寄存器,1 - 使能 DATARDY 事件中断
在这里插入图片描述
INTENCLR 寄存器,1- 禁止 DATARDY 事件中断
在这里插入图片描述
TEMP 寄存器,温度单位:摄氏度,0.25 一个进位
在这里插入图片描述
A[n[ n = 0~5 寄存器,线性函数的斜率
在这里插入图片描述
B[n] n= 0~5 寄存器,段线性函数的 y 轴截距
在这里插入图片描述
T[n] n = 0~4 寄存器,分段线性函数的端点
在这里插入图片描述

温度传感器电气特征

任何的温度传感器都有其电气特性,也就是说有采集温度的范围和转换时间、精度等参数。不是说任何温度都可以进行采集的。nRF52 处理器的内部温度传感器的电气特性如下表所示,表中标注了温度采集的转换时间、温度测量范围、传感器精度、传感器分辨率、稳定性、偏移量等参数,这些参数在测量温度以及参数效正的时候需要参考的。
在这里插入图片描述

温度传感器库函数编程

对应温读采集的工程搭建,我们可以采用前面的串口组件库的工程例子进行修改。由于组件 库中提供了一个 nrf_temp.h 驱动文件,因此我们需要关注在工程配置 Options for Target 中的 C/C++ 选项卡下:Include Paths中添加\\modules\nrfx\hal路径,因为nrf_temp.h驱动文件位于modules\nrfx\hal 文件夹内,具体如下图

在这里插入图片描述
主函数中,需要在 main.c 文件最开头的文件包含中添加 nrf_temp.h 头文件。

  1. 初始化温度采集,有初始化函数
    在这里插入图片描述
  2. 启动温度采集,等待采集过程完成。温湿度采集提供了寄存器 TASKS_START 来启动采集,当置位该寄存器,就可以启动内部温度采集模块进行温度采集了。
NRF_TEMP->TASKS_START = 1

采集需要时间,这个过程并不能立即打断,因此需要等待 EVENTS_DATARDY 事件是否被置位,如果置位了,表面临时缓冲区中温度数据已经采集存储就绪。或者在 INTENSET 寄存器中使能 DATARDY 事件的中断,采用中断方式进行判断。

  1. 读出采集温度的数值,并且停止温度采集。当临时缓冲中温度数据已经准备就绪后,就可以读出数据。读出数据的函数如下:
    在这里插入图片描述
    该函数从 TEMP 寄存器中读取 10 位 2 的补码值并将其转换为 32 位 2 的补码值,注意 TEMP 寄存器中存储的值是以 0.25°C 一个进位级,如果要转换为°C 为单位,则实际的温度值应该是*0.25 或者除以 4。 当温度读取成功后,对寄存器 TASKS_STOP 置位以停止温度采集。

采集步骤如下图所示:
在这里插入图片描述

具体程序代码如下:


#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include "app_uart.h"
#include "app_error.h"
#include "nrf_delay.h"
#include "nrf.h"
#include "bsp.h"
#if defined (UART_PRESENT)
#include "nrf_uart.h"
#endif
#if defined (UARTE_PRESENT)
#include "nrf_uarte.h"
#endif
#include "nrf_temp.h"//添加内部温度库头文件#define MAX_TEST_DATA_BYTES     (15U)                /**< max number of test bytes to be used for tx and rx. */
#define UART_TX_BUF_SIZE 256                         /**< UART TX buffer size. */
#define UART_RX_BUF_SIZE 256                         /**< UART RX buffer size. */void uart_error_handle(app_uart_evt_t * p_event)
{if (p_event->evt_type == APP_UART_COMMUNICATION_ERROR){APP_ERROR_HANDLER(p_event->data.error_communication);}else if (p_event->evt_type == APP_UART_FIFO_ERROR){APP_ERROR_HANDLER(p_event->data.error_code);}
}//串口初始化函数
void uart_init()
{uint32_t err_code;const app_uart_comm_params_t comm_params ={RX_PIN_NUMBER,TX_PIN_NUMBER,RTS_PIN_NUMBER,CTS_PIN_NUMBER,APP_UART_FLOW_CONTROL_DISABLED,false,UART_BAUDRATE_BAUDRATE_Baud115200};APP_UART_FIFO_INIT(&comm_params,UART_RX_BUF_SIZE,UART_TX_BUF_SIZE,uart_error_handle,APP_IRQ_PRIORITY_LOW,err_code);APP_ERROR_CHECK(err_code);
}//主函数,主要实现了测试内部温度,通过串口输出int main(void)
{int32_t volatile temp;//初始化LED灯LEDS_CONFIGURE(LEDS_MASK);LEDS_OFF(LEDS_MASK);//初始化串口uart_init();//初始化内部温度传感器nrf_temp_init();  printf("Temperature example started.");//循环测试内部温度while (true){   //开始温度测量NRF_TEMP->TASKS_START = 1;/*当温度测量尚未完成时,如果为DATARDY事件启用中断并在中断中读取结果,则可以跳过等待。 */while (NRF_TEMP->EVENTS_DATARDY == 0){//不做任何事}NRF_TEMP->EVENTS_DATARDY = 0;//停止任务清除临时寄存器。temp = (nrf_temp_read() / 4);/*TEMP:当DATARDY事件发生时,Temp模块模拟前端不断电。*/NRF_TEMP->TASKS_STOP = 1; /** 停止温度测量。 */printf("温度采样: %u\n\r", (uint8_t)(temp));nrf_gpio_pin_toggle(LED_1);nrf_delay_ms(800);}
}

随机数产生器

这里的随机数产生器并不是通常 C 语言中常用的 random() 随机数生成,而是基于内部热噪声产生的真实非确定性的随机数。通常可以用于通讯加密等场合使用。

该随机数发生器 RNG 通过触发 START 任务进行启动;通过触发 STOP 任务停止运行。在启动时,新的随机数连续产生,并在准备好时写入 VALUE 寄存器中。随着每次新的随机数写入到 VALUE 寄存器,都会触发一个 VALRDY 事件。这意味着生成 VALRDY 事件后,直到下一个 VALRDY 事件之前这段时间,CPU 有足够的时间在新的随机数覆盖旧的随机数之前,从 VALUE 寄存器中读出的旧随机数的值。

随机数发生器的应用场合

随机数发生器常用于处理器和设备之间的通讯中进行信息加密和身份认证,其应用场合如下:

  • 某设备发送操作请求给 MCU,MCU 利用随机数发生器产生一段随机序列(明文),MCU 采用加密方式对明文进行加密产生一段密文(明文 + 用户密码 = 密文)。然后 MCU 发送密文给 某设备。
  • 某设备利用用户密码,同时采用相同的解密方式对密文进行解密,还原出明文,并发送给 MCU。MCU 在 100ms 内等待设备端解密出来的明文,并与随机数发生器随机产生的明文做比较。 若比较正确则认为设备端输入了正确的密码,如果错误则终止通讯。 整个通信过程都中,明文都是随机序列。如果设备端无正确的密码,通讯过程是无法正确进行 的。因此实现了安全的密码验证授权!这种方式比较常见的如应用于 AES 加密算法。

偏差矫正

在内部比特流上采用偏差校正算法以消除对“1”或“0”的任何偏差。然后将这些位排队到一 个 8 位寄存器,以便从 VALUE 寄存器进行并行读出。可以在 CONFIG 寄存器中启用偏差校正。这将导致较慢的值生成,但将确保随机值的统计均匀分布。 生成速度:生成一个随机字节数据所需的时间是不可预测的,并且可能在一个字节到下一个字节之间变化。启用偏差校正时尤其如此。

随机数发生器寄存器

内部温度传感器作为外部设备,基础地址为 0x4000D000 ,其寄存器描述如下:
在这里插入图片描述
以上寄存器详细介绍几个经常用到的:

  • SHORTS 快捷寄存器:用于快速通过 AVLRDY 事件触发 STOP 任务
    在这里插入图片描述
  • INTENSET 启用中断寄存器:使能随机数中断
位数复位值FieldValue IDValue描述:可读可写寄存器
第 0 位0x00000000VALRDYSet写入 1 为启用 VALRDY 事件中断,使能中断
  • INTENCLR 关闭中断寄存器:禁止随机数中断
    在这里插入图片描述
  • CONFIG 配置寄存器:配置是否开启偏差校正
    在这里插入图片描述
  • VALUE 输出随机数寄存器:随机数的存储寄存器
    在这里插入图片描述

随机数发生器库函数编程

库函数使用流程

随机数发生器采用组件库编程会大大降低编程难度,优化数据处理过程。下面详细讲解组件库 编写随机数发生器的过程,并且进入到库函数内部,探讨整个随机数产生以及读取的过程。

  1. 使用 RNG 模块之前,首先初始化 RNG 发生器模块,在 SDK 的组件库中,提供了 nrf_drv_rng.c 这样一个库文件,该文件中提供了一个 nrf_drv_rng_init() 函数,用于初始化 RNG 模块功能。nrf_drv_rng_init 函数介绍如下:
    在这里插入图片描述
    这里参数 nrf_drv_mg_config_t const *p_config 也是提供了一个结构体对初始化参数进行定义,这个结构体如下:
/*** @brief Struct for RNG configuration.*/
typedef struct
{bool     error_correction : 1;  /**< Error correction flag. 误差修正的帧*/uint8_t  interrupt_priority;    /**< interrupt priority 中断优先级*/
} nrfx_rng_config_t;

这个结构体配置了两个参数,一个帧标注是否有数据修正,一个设置了优先级。我们可以进入 nrf_drv_mg_init() 函数内部看一下具体的操作。

/*默认配置 */
#define NRFX_RNG_DEFAULT_CONFIG                                 \{                                                           \.error_correction   = NRFX_RNG_CONFIG_ERROR_CORRECTION, \.interrupt_priority = NRFX_RNG_CONFIG_IRQ_PRIORITY,     \}
#define NRF_DRV_RNG_DEFAULT_CONFIG  NRFX_RNG_DEFAULT_CONFIG
static const nrf_drv_rng_config_t m_default_config = NRF_DRV_RNG_DEFAULT_CONFIG;ret_code_t nrf_drv_rng_init(nrf_drv_rng_config_t const * p_config)
{ret_code_t err_code = NRF_SUCCESS;if (m_rng_cb.state != NRFX_DRV_STATE_UNINITIALIZED)//如果没有初始化{return NRF_ERROR_MODULE_ALREADY_INITIALIZED;//返回已经初始化的状态}if (p_config == NULL)//如果配置为NULL,{p_config = &m_default_config;//设置为默认配置}m_rng_cb.config = *p_config;NRF_DRV_RNG_LOCK();//RNG锁定if (!NRF_DRV_RNG_SD_IS_ENABLED()){err_code = nrfx_rng_init(&m_rng_cb.config, nrfx_rng_handler);//触发RNG,并且触发RNG事件if (err_code != NRF_SUCCESS){return err_code;}nrfx_rng_start();//开始RNG}m_rng_cb.state = NRFX_DRV_STATE_INITIALIZED;NRF_DRV_RNG_RELEASE();//释放return err_code;
}

默认配置参数在 sdk_config.h 文件中,具体配置如下:

// <e> NRFX_RNG_ENABLED - nrfx_rng - RNG peripheral driver
//==========================================================
#ifndef NRFX_RNG_ENABLED
#define NRFX_RNG_ENABLED 0
#endif
// <q> NRFX_RNG_CONFIG_ERROR_CORRECTION  - Error correction#ifndef NRFX_RNG_CONFIG_ERROR_CORRECTION
#define NRFX_RNG_CONFIG_ERROR_CORRECTION 1
#endif// <o> NRFX_RNG_CONFIG_IRQ_PRIORITY  - Interrupt priority// <0=> 0 (highest) 
// <1=> 1 
// <2=> 2 
// <3=> 3 
// <4=> 4 
// <5=> 5 
// <6=> 6 
// <7=> 7 #ifndef NRFX_RNG_CONFIG_IRQ_PRIORITY
#define NRFX_RNG_CONFIG_IRQ_PRIORITY 7
#endif

nrfx_rng_init() 是初始化 RNC 配置,首先开始错误修正功能,然后配置 RNC 中断优先级,开启 RNC 中断。中断执行后会触发 nrfx_rng_evt_handler 的回调事件。

nrfx_err_t nrfx_rng_init(nrfx_rng_config_t const * p_config, nrfx_rng_evt_handler_t handler)
{NRFX_ASSERT(p_config);NRFX_ASSERT(handler);if (m_rng_state != NRFX_DRV_STATE_UNINITIALIZED){return NRFX_ERROR_ALREADY_INITIALIZED;}m_rng_hndl = handler;/* 开启错误修正 */if (p_config->error_correction){nrf_rng_error_correction_enable();}/* 设置中断优先级,并且开启中断 */nrf_rng_shorts_disable(NRF_RNG_SHORT_VALRDY_STOP_MASK);NRFX_IRQ_PRIORITY_SET(RNG_IRQn, p_config->interrupt_priority);NRFX_IRQ_ENABLE(RNG_IRQn);m_rng_state = NRFX_DRV_STATE_INITIALIZED;return NRFX_SUCCESS;
}

之后调用 nrfx_rng_start() 开始 RNC 随机数发生器运行。一旦开始运行,新的随机数便会产生,并在准备好时写入 VALUE 寄存器中。随着新的随机数写入会触发一个 VALRDY 中断事件。

void nrfx_rng_start(void)
{NRFX_ASSERT(m_rng_state == NRFX_DRV_STATE_INITIALIZED);nrf_rng_event_clear(NRF_RNG_EVENT_VALRDY);nrf_rng_int_enable(NRF_RNG_INT_VALRDY_MASK);nrf_rng_task_trigger(NRF_RNG_TASK_START);
}

中断函数在 nrfx_rng.c 进行了定义,前面已经使能了中断,当中断事件发生后,我们进入中断。中断中首先清除 VALRDY 事件标志,然后通过 nrf_rng_random_value_get 函数读取出 VALUE 寄存器的值,最后去执行 nrfx_rng_evt_handler 的回调事件。


void nrfx_rng_irq_handler(void)
{nrf_rng_event_clear(NRF_RNG_EVENT_VALRDY);//清除中断标志uint8_t rng_value = nrf_rng_random_value_get();//读取VALUE寄存器值m_rng_hndl(rng_value);//执行回调事件NRFX_LOG_DEBUG("Event: NRF_RNG_EVENT_VALRDY.");
}

nrfx_rng_evt_handler 回调事件主要是需要把 VALUE 寄存器中读出的值放入到队列文件中声明的一个专用放置随机数的 m_rand_pool 池中,如果池子满了,避免溢出会停止 RNC 模块的运行。

static void nrfx_rng_handler(uint8_t rng_val)
{NRF_DRV_RNG_LOCK();if (!NRF_DRV_RNG_SD_IS_ENABLED()){UNUSED_RETURN_VALUE(nrf_queue_push(&m_rand_pool, &rng_val));//把VALUE读取的随机数放入pool池子中if (nrf_queue_is_full(&m_rand_pool))//如果队列满了{nrfx_rng_stop();//停止RNG}NRF_LOG_DEBUG("Event: NRF_RNG_EVENT_VALRDY.");}NRF_DRV_RNG_RELEASE();}

执行完回调后,m_rand_pool 中就会有 RNC 模块参数的随机数了。
关于这个 m_rand_pool 池的说明: 在 SDK 中提供了一个 nrf_queue.c 文件,专门来提供类似堆栈的缓冲区,相当一个存储池。随 机数这个工程中需要调用这个函数,并且在 nrf_drv_rng.c 库文件中,调用了这个队列的定义,声明 了一个 m_rand_pool 池,代码如下所示:

#define RNG_CONFIG_POOL_SIZE 64
/**@brief Supported queue modes. */
typedef enum
{NRF_QUEUE_MODE_OVERFLOW,        //覆盖模式:!< If the queue is full, new element will overwrite the oldest.NRF_QUEUE_MODE_NO_OVERFLOW,     //溢出模式:!< If the queue is full, new element will not be accepted.
} nrf_queue_mode_t;// nrf_drv_rng.c 中声明
NRF_QUEUE_DEF(uint8_t, m_rand_pool, RNG_CONFIG_POOL_SIZE, NRF_QUEUE_MODE_OVERFLOW);

默认配置为覆盖模式,新的数据过来就会覆盖老的数据。因此前面我们会判断 pool 池子是否满 了,如果满了就停止 RNG 产生新的随机数,避免数据被覆盖。

  1. 第二步从 pool 池中读出对应字节的随机数,并且把读出的随机数放入一个缓冲向量中,然后 通过串口在 PC 机上打印进行观察。这时候我们可以调用两个库函数 nrf_drv_rng_bytes_availablenrf_drv_rng_rand,这两个函数介绍如下:
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    使用如下代码获取 pool 池中随机数的大小,比较设置的 BUFF 大小,选择最小值作为存入 BUFF 的长度,避免数据丢失。
/** 函数功能是用于获取随机数,把随机数放入缓冲向量。** 参数 p_buff       指向unit8_t缓冲区的指针,用于存储随机数。* 参数 length       从pool池中取出并放入p_buff中的字节数。** 返回值     实际放置在p_buff中的字节数。*/
static uint8_t random_vector_generate(uint8_t * p_buff, uint8_t size)
{uint32_t err_code;uint8_t  available;nrf_drv_rng_bytes_available(&available);//获取可用的随机数uint8_t length = MIN(size, available);err_code = nrf_drv_rng_rand(p_buff, length);//随机数放入缓冲APP_ERROR_CHECK(err_code);return length;
}

那么整个随机数的获取,以及随机数读出过程。可以总结如下图所示的流程。主程序和 中断程序相互独立。如果使能了 RNG 中断,当然 RNG 启动后,CPU 就会把新产生的随机数放入到 VALUE 寄存器中就会触发对应中断,在中断中完成把 VALUE 寄存器中的随机数放入到 pool 队列 池的过程。当 pool 队列池满了后,会停止 RNG 模块,退出中断。主函数则是以循环扫描的方式读 取 pool 队列池中的随机数,放入到缓冲数组中,通过串口打印输出进行观察。
在这里插入图片描述

RNG 工程搭建使用

搭建 RNC 工程目录,随机数发生器的演示工程可以在串口例程上进行修改,如下图所示。需要添加是三个驱动库函数,分别为:nrfx_rng.cnrf_drv_rng.cnrf_queue.c 函数。
在这里插入图片描述
添加驱动文件库后,这些文件库的路径也需要进行链接,路径如下图所示。在工程配置 Options for Target 中的 C/C++选项卡下:Include Paths 中添加:
在这里插入图片描述
在这里插入图片描述
由于 nrf_queue.h 的头文件是在 nrf_drv_rng.c 文件中被引用、nrfx_rng.h 的头文件在 nrf_drv_rng.h 文件中被引用。所以主函数中只需要引用一个头文件 nrf_drv_rng.h 就可以了对这三个函数进行调用。

同时需要在 sdk_config.h 文件中,添加配置 RNG 相关的配置,注意串口的 sdk_config.h 文件中 是没有 RNG 相关的配置的,需要自己手动添加的,具体添加内容请例程参考代码。如果添加成功, 切换到配置导航选项卡 configuarton wizard 上,会出现对应配置被勾选,如下图所示的。
在这里插入图片描述
完成后编写 main.c 文件,详细内容如下:

#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include "app_uart.h"
#include "app_error.h"
#include "nrf_delay.h"
#include "nrf.h"
#include "bsp.h"
#if defined (UART_PRESENT)
#include "nrf_uart.h"
#endif
#if defined (UARTE_PRESENT)
#include "nrf_uarte.h"
#endif#include "nrf_drv_rng.h"#define MAX_TEST_DATA_BYTES     (15U)                /*发送和接收的最大测试字节. */
#define UART_TX_BUF_SIZE 256                         /*发送缓冲的大小 */
#define UART_RX_BUF_SIZE 256                         /*接收缓冲的大小 */#define RANDOM_BUFF_SIZE    16      /**< Random numbers buffer size. *//** 函数功能是用于获取随机数,把随机数放入缓冲向量。** 参数 p_buff       指向unit8_t缓冲区的指针,用于存储随机数。* 参数 length       从pool池中取出并放入p_buff中的字节数。** 返回值     实际放置在p_buff中的字节数。*/
static uint8_t random_vector_generate(uint8_t * p_buff, uint8_t size)
{uint32_t err_code;uint8_t  available;nrf_drv_rng_bytes_available(&available);//获取可用的随机数uint8_t length = MIN(size, available);err_code = nrf_drv_rng_rand(p_buff, length);//随机数放入缓冲APP_ERROR_CHECK(err_code);return length;
}/*串口中断回调*/
void uart_Interrupt_handle(app_uart_evt_t * p_event)
{if (p_event->evt_type == APP_UART_COMMUNICATION_ERROR){APP_ERROR_HANDLER(p_event->data.error_communication);}}/***主函数:循环输出随机数*/
int main(void)
{LEDS_CONFIGURE(LEDS_MASK);LEDS_OFF(LEDS_MASK);uint32_t err_code;const app_uart_comm_params_t comm_params ={RX_PIN_NUMBER,TX_PIN_NUMBER,RTS_PIN_NUMBER,CTS_PIN_NUMBER,APP_UART_FLOW_CONTROL_DISABLED,false,UART_BAUDRATE_BAUDRATE_Baud115200};APP_UART_FIFO_INIT(&comm_params,UART_RX_BUF_SIZE,UART_TX_BUF_SIZE,uart_Interrupt_handle,APP_IRQ_PRIORITY_LOW,err_code);APP_ERROR_CHECK(err_code);//内部随机数模块初始化err_code = nrf_drv_rng_init(NULL);APP_ERROR_CHECK(err_code);printf("RNG example started.");while (true){uint8_t p_buff[RANDOM_BUFF_SIZE];//计算随机数长度uint8_t length = random_vector_generate(p_buff,RANDOM_BUFF_SIZE);printf("Random Vector:");//输出随机数for(uint8_t i = 0; i < length; i++)  {printf(" %2x",(int)p_buff[i]);}printf("\n\r");nrf_delay_ms(1000);}
}

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

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

相关文章

IDEA创建Sping项目只能勾选17和21,没有Java8?

解决办法: 替换创建项目的源 我们只知道IDEA页面创建Spring项目&#xff0c;其实是访问spring initializr去创建项目。故我们可以通过阿里云国服去间接创建Spring项目。将https://start.spring.io/或者http://start.springboot.io/替换为 https://start.aliyun.com/

使用 Python 编写程序保护您的眼睛

眼睛&#xff0c;是心灵的窗户&#xff0c;生活在数字时代的我们&#xff0c;眼睛首当其冲地承受冲击。盯着电脑屏幕成为我们日常工作和学习的一部分&#xff0c;导致用眼过度。那如何减少对眼睛的伤害&#xff0c;应该如何保护眼睛&#xff1f; 用眼应控制时间&#xff0c;自…

C语言字符函数和字符串函数详解

Hello, 大家好&#xff0c;我是一代&#xff0c;今天给大家带来有关字符函数和字符串函数的有关知识 所属专栏&#xff1a;C语言 创作不易&#xff0c;望得到各位佬们的互三呦 一.字符函数 在C语言中有一些函数是专门为字符设计的&#xff0c;这些函数的使用都需要包含一个头文…

如何用人工智能实现客户服务营销?实用指南与关键技巧一网打尽

在不断发展的营销领域&#xff0c;创意是成功营销活动的生命线。火花点燃兴趣&#xff0c;吸引受众&#xff0c;推动参与。但是&#xff0c;如果有一种方法可以利用技术来提升创意&#xff0c;那会怎样呢&#xff1f;生成式人工智能&#xff08;Generative AI&#xff09;是一种…

数据结构与算法----复习Part 16 (并查集)

本系列是算法通关手册LeeCode的学习笔记 算法通关手册&#xff08;LeetCode&#xff09; | 算法通关手册&#xff08;LeetCode&#xff09; (itcharge.cn) 目录 并查集&#xff08;Union Find&#xff09; 基于数组实现的快速查询并查集 基于森林实现的快速合并并查集 路径…

51单片机-AT24C02(I2C总线)

目录 一&#xff0c;介绍及元件工作原理 7.时序结构&#xff08;重要&#xff09; 8.i2C总线数据帧&#xff08;重要&#xff09; 二&#xff0c;应用 一&#xff0c;介绍及元件工作原理 1.元件介绍 2.存储器 3.地址总线和数据总线 地址总线只能一次选中一行 4.引脚及应用…

三次握手seq和ack的流程 TCP协议栈seq和ack深层理解

☆ 大家可以把想了解的问题在评论发给我?我会根据问题补充到后面 ☆ 三次握手seq和ack的流程 是的,在TCP/IP协议中,三次握手过程确实涉及到序列号(Sequence Number, 简称Seq)和确认号(Acknowledgment Number, 简称Ack)的交换。这个过程是为了建立可靠的连接,确保数据能…

Python基础(七)之数值类型字典

Python基础&#xff08;七&#xff09;之数值类型字典 1、简介 字典&#xff08;dict&#xff09;&#xff0c;Dictionary:是一种可变类型&#xff0c;可以存储任意类型的元素&#xff0c;如列表、字符串、元组等。 字典是无序的&#xff0c;所以不支持索引和切片。字典以键值…

CSS中如何设置单行或多行内容超出后,显示省略号

1. 设置超出显示省略号 css设置超出显示省略号可分两种情况&#xff1a; 单行文本溢出显示省略号…多行文本溢出显示省略号… 但使用的核心代码是一样的&#xff1a;需要先使用 overflow:hidden;来把超出的部分隐藏&#xff0c;然后使用text-overflow:ellipsis;当文本超出时…

软考 系统架构设计师之回归及知识点回顾(7)

接前一篇文章&#xff1a;软考 系统架构设计师之回归及知识点回顾&#xff08;6&#xff09; 11. 云计算 背景 大数据和云计算已成为IT领域的两种主流技术。“数据是重要资产”这一概念已成为大家的共识&#xff0c;众多公司争相分析、挖掘大数据背后的重要财富。同时学术界、…

哔哩哔哩后端Java一面

前言 作者&#xff1a;晓宜 个人简介&#xff1a;互联网大厂Java准入职&#xff0c;阿里云专家博主&#xff0c;csdn后端优质创作者&#xff0c;算法爱好者 最近各大公司的春招和实习招聘都开始了&#xff0c;这里分享下去年面试B站的的一些问题&#xff0c;希望对大家有所帮助…

第十二届蓝桥杯EDA省赛真题分析

前言&#xff1a; 第十二届蓝桥杯EDA比赛用的是AD软件&#xff0c;从第十四届起都是使用嘉立创EDA专业版&#xff0c;所以在这里我用嘉立创EDA专业版实现题目要求。 一、省赛第一套真题题目 主观题整套题目如下&#xff1a; 试题一&#xff1a;库文件设计&#xff08;5分&am…

VS Code 配置类似浏览器中的垂直标签页功能

参考&#xff1a;Dominik Weber - 2022.06.25 (注&#xff1a;原文中的配置有些过时了&#xff0c;所以根据 VS Code 的最新版本进行了调整。) 原作者非常喜欢垂直标签页&#xff0c;只要有可能&#xff0c;就都会使用它们。他主要在浏览器&#xff08;Firefox&#xff09;和…

Python之Web开发中级教程----ubuntu中下载安装Postman

Python之Web开发中级教程----ubuntu中下载安装Postman PostMan 是一款功能强大的网页调试与发送网页 HTTP 请求的 Chrome 插件&#xff0c;可以直接去对我们写出来的路由和视图函数进行调试&#xff0c;作为后端程序员是必须要知道的一个工具。 查看ubuntu系统中是否已经安装了…

VsCode 配置go开发环境之下载go tools

ctrl shift P 选择 go install/update tools&#xff0c;下载go tools 报错&#xff0c; 提升dial err。 将GOPROXY 和 GOSUMDB 按照如下配置&#xff0c;重启IDE即可成功下载 set GOPROXYhttps://goproxy.cn set GOSUMDBoff

程序人生——Java多线程和并发的使用建议

目录 引出多线程和并发建议118&#xff1a;不推荐覆写start方法建议119&#xff1a;启动线程前stop方法是不可靠的建议120&#xff1a;不适用stop方法停止线程 建议121&#xff1a;线程优先级只使用三个等级建议122&#xff1a;使用线程异常处理器提升系统可靠性建议123&#x…

【递归专题】【蓝桥杯备考训练】:有序分数、正则问题、带分数、约数之和、分形之城【已更新完成】

目录 1、有序分数&#xff08;usaco training 2.1&#xff09; 2、正则问题&#xff08;第八届蓝桥杯省赛C A组 & Java A组&#xff09; 3、带分数&#xff08;第四届蓝桥杯省赛Java A组/B组 & C B组/C组&#xff09; 4、约数之和&#xff08;《算法竞赛进阶指南》…

jvm的垃圾回收器以及触发full gc的场景

JVM&#xff08;Java虚拟机&#xff09;的垃圾回收器有很多种&#xff0c;主要包括以下几种&#xff1a; Serial收集器&#xff1a;串行收集器是最古老、最稳定的收集器。它使用单个线程进行垃圾收集工作&#xff0c;在进行垃圾回收时会暂停所有用户线程。 ParNew收集器&#…

ViT如何支持变长序列输入?

当增加输入图像的分辨率时&#xff0c;例如DeiT 从 224 到 384&#xff0c;一般来说会保持 patch size&#xff08;例如9&#xff09;&#xff0c;因此 patch 的数量 N 会发生了变化。那么视觉transformer是如何处理变长序列输入的? DEiT中如何处理mask数据的&#xff1f; 例…

智慧公厕对于智慧城市管理的意义

近年来&#xff0c;智慧城市的概念不断被提及&#xff0c;而智慧公厕作为智慧城市管理的重要组成部分&#xff0c;其在监测、管理和养护方面发挥着重要的作用。智慧公厕不仅是城市市容提升的重要保障&#xff0c;还能提升城市环境卫生管理的质量&#xff0c;并有效助力创造清洁…