STM32_HAL_看门狗

news2024/11/26 5:57:16

介绍

STM32的"看门狗"(Watchdog)是一种硬件安全特性,用于监控STM32微控制器的正常操作。当系统出现故障或异常时,看门狗能够检测到这些情况,并采取相应的措施,通常是重置微控制器,以防止系统陷入无效状态。

看门狗的基本工作原理是这样的:

  1. 定时器:看门狗内置了一个定时器,当看门狗被启用时,这个定时器开始计数。

  2. 喂狗:在程序运行过程中,必须定期地“喂狗”,即重置看门狗的定时器。这通常通过写入特定的寄存器来完成。

  3. 超时和复位:如果在设定的时间间隔内没有喂狗,看门狗会认为程序可能出现了异常,无法正常执行。这时,看门狗将引发一个超时事件,默认情况下,这个事件会导致微控制器复位,从而让系统有机会重新启动并恢复正常操作。

STM32微控制器通常包含两个看门狗:

  • 独立看门狗(IWDG)

独立看门狗(Independent Watchdog)是一个由独立时钟源供电的看门狗,它的时钟源通常是内置的低速时钟(LSI)振荡器。由于它不依赖于主时钟系统,即使在主时钟发生故障的情况下,独立看门狗也能正常工作。这使得它在需要极高可靠性的应用中非常有用,例如那些对系统故障容忍度很低的环境。

独立看门狗的操作相对简单,它通常有一个可编程的计数器,当计数器减到0时,如果没有重新加载计数器(即“喂狗”),看门狗就会触发系统复位。由于它的独立性,独立看门狗通常用于监控那些对系统稳定性至关重要的任务。

  • 窗口看门狗(WWDG)

窗口看门狗(Window Watchdog)提供了一个时间窗口,喂狗操作必须在这个窗口内进行。这种设计可以防止由于喂狗操作过早或过晚而导致的系统问题。窗口看门狗通常用于需要精确监控的应用,它可以在看门狗超时之前提供一个预警窗口,允许系统有机会采取一些预防措施。

窗口看门狗的时钟来源通常是主时钟,这使得它在主时钟正常工作时非常有效。窗口看门狗的超时时间较短,这意味着它可以在系统出现问题时快速响应。

区别

  1. 时钟源

    • IWDG:使用独立的时钟源,通常是内置的低速内部时钟(LSI)振荡器。这意味着即使主时钟发生故障,IWDG仍然可以独立运行,确保系统的可靠性。
    • WWDG:通常使用主时钟(如HCLK)的分频值作为时钟源。因此,WWDG的精度和稳定性与主时钟系统相关联。
  2. 灵活性

    • IWDG:提供固定的超时时间,用户可以通过编程设置不同的超时周期,但相对于WWDG来说,灵活性较低。
    • WWDG:提供一个可编程的时间窗口,允许在一定的范围内调整超时时间。这可以在看门狗超时之前提供一个预警窗口,让系统有机会采取预防措施。
  3. 用途

    • IWDG:由于其独立性和简单的操作,通常用于监控那些对系统稳定性至关重要的任务,特别是在那些对系统故障容忍度很低的环境。
    • WWDG:由于其窗口特性,可以用于需要精确监控的应用,确保系统在规定的时间内正常运行,防止由于喂狗操作过早或过晚而导致的系统问题。
  4. 喂狗操作

    • IWDG:当计数器减到0时,如果没有重新加载计数器(即“喂狗”),看门狗就会触发系统复位。
    • WWDG:喂狗操作必须在窗口期内进行,如果过早或过晚,看门狗会认为系统没有正确运行,并触发系统复位。
  5. 响应时间

    • IWDG:由于使用的是低速时钟,其响应时间相对较长。
    • WWDG:使用主时钟的分频值,响应时间相对较短,适合快速检测和响应系统异常。

应用

独立看门狗(IWDG)的应用举例:

  1. 远程监控系统:在远程监控系统中,特别是在那些维护困难或成本高昂的环境中,如海底监控、远程气象站等,IWDG可以确保系统在极端条件下也能稳定运行。
  2. 医疗设备:在生命支持系统中,如心脏起搏器或呼吸机,系统的可靠性至关重要。IWDG可以保证即使在主时钟故障的情况下,设备也能安全地重置并继续工作。
  3. 无人驾驶车辆:在自动驾驶汽车或无人机中,IWDG可以作为一个最后的安全防线,确保控制系统在出现任何问题时都能恢复到已知的安全状态。

窗口看门狗(WWDG)的应用举例:

  1. 实时操作系统(RTOS):在实时操作系统中,任务的执行必须在严格的时间约束下进行。WWDG可以确保任务在规定的时间内完成,防止系统因为任务延迟而出现性能问题。
  2. 电机控制:在电机控制应用中,精确的时间控制对于防止电机过热或损坏非常重要。WWDG可以帮助监控控制循环,确保及时更新电机的控制信号。
  3. 通信系统:在需要高精度时间同步的通信系统中,如无线基站或网络设备,WWDG可以确保数据包在规定的时间内发送和接收,维护通信的稳定性和可靠性。

总结

  1. 监控CPU(或微控制器核心):(独立)

    • 看门狗可以监控CPU是否能够定期“喂狗”,即更新看门狗的计数器。如果CPU由于硬件故障、电磁干扰、软件错误等原因无法正常工作,它可能无法在规定的时间内更新看门狗,导致看门狗超时并触发系统复位。这样,看门狗确保了即使CPU出现问题,系统也能重启并尝试恢复正常运行。
  2. 监控程序的执行:(窗口)

    • 看门狗也用于确保程序能够按预期运行。在正常情况下,程序会在执行过程中定期喂狗。如果程序由于软件错误、死锁、无限循环或其他原因而无法继续执行,它可能无法及时喂狗,从而导致看门狗超时并重置系统。通过这种方式,看门狗可以帮助检测和恢复由于软件问题导致的系统故障。

实例

独立看门狗

步骤

使用独立看门狗的一般步骤如下:

  1. 初始化独立看门狗,设置合适的时钟和预分频器。
  2. 启动独立看门狗。
  3. 在主循环或其他适当的时机,定期调用HAL_IWDG_Refresh()函数刷新看门狗计数器。

函数

常用函数包括:

  1. HAL_IWDG_Init() - 初始化独立看门狗,设置其时钟和预分频器。
  2. HAL_IWDG_Refresh() - 刷新独立看门狗的计数器,防止看门狗超时导致系统复位。(喂狗)

stm32cude MX

main.h源码

/* USER CODE BEGIN Header */
/**
  ******************************************************************************
  * @file           : main.c
  * @brief          : Main program body
  ******************************************************************************
  * @attention
  *
  * Copyright (c) 2024 STMicroelectronics.
  * All rights reserved.
  *
  * This software is licensed under terms that can be found in the LICENSE file
  * in the root directory of this software component.
  * If no LICENSE file comes with this software, it is provided AS-IS.
  *
  ******************************************************************************
  */
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "iwdg.h"
#include "usart.h"
#include "gpio.h"

/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */

/* USER CODE END Includes */

/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */

/* USER CODE END PTD */

/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */

/* USER CODE END PD */

/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */

/* USER CODE END PM */

/* Private variables ---------------------------------------------------------*/

/* USER CODE BEGIN PV */

/* USER CODE END PV */

/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
/* USER CODE BEGIN PFP */

/* USER CODE END PFP */

/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */

/* USER CODE END 0 */

/**
  * @brief  The application entry point.
  * @retval int
  */
int main(void)
{

  /* USER CODE BEGIN 1 */

  /* USER CODE END 1 */

  /* MCU Configuration--------------------------------------------------------*/

  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();

  /* USER CODE BEGIN Init */

  /* USER CODE END Init */

  /* Configure the system clock */
  SystemClock_Config();

  /* USER CODE BEGIN SysInit */

  /* USER CODE END SysInit */

  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_IWDG_Init();
  MX_USART1_UART_Init();
  /* USER CODE BEGIN 2 */

	//HAL_Delay(1000);//开启将卡在循环延迟中//超出看门狗的时间
  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
		HAL_IWDG_Refresh(&hiwdg);//喂狗
		char a[]={"已喂狗"};
		HAL_UART_Transmit(&huart1,(uint8_t*)a,6,20);
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
  }
  /* USER CODE END 3 */
}

/**
  * @brief System Clock Configuration
  * @retval None
  */
void SystemClock_Config(void)
{
  RCC_OscInitTypeDef RCC_OscInitStruct = {0};
  RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};

  /** Initializes the RCC Oscillators according to the specified parameters
  * in the RCC_OscInitTypeDef structure.
  */
  RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_LSI|RCC_OSCILLATORTYPE_HSE;
  RCC_OscInitStruct.HSEState = RCC_HSE_ON;
  RCC_OscInitStruct.HSEPredivValue = RCC_HSE_PREDIV_DIV1;
  RCC_OscInitStruct.HSIState = RCC_HSI_ON;
  RCC_OscInitStruct.LSIState = RCC_LSI_ON;
  RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
  RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
  RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL9;
  if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
  {
    Error_Handler();
  }

  /** Initializes the CPU, AHB and APB buses clocks
  */
  RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
                              |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
  RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
  RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
  RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2;
  RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;

  if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK)
  {
    Error_Handler();
  }
}

/* USER CODE BEGIN 4 */

/* USER CODE END 4 */

/**
  * @brief  This function is executed in case of error occurrence.
  * @retval None
  */
void Error_Handler(void)
{
  /* USER CODE BEGIN Error_Handler_Debug */
  /* User can add his own implementation to report the HAL error return state */
  __disable_irq();
  while (1)
  {
  }
  /* USER CODE END Error_Handler_Debug */
}

#ifdef  USE_FULL_ASSERT
/**
  * @brief  Reports the name of the source file and the source line number
  *         where the assert_param error has occurred.
  * @param  file: pointer to the source file name
  * @param  line: assert_param error line source number
  * @retval None
  */
void assert_failed(uint8_t *file, uint32_t line)
{
  /* USER CODE BEGIN 6 */
  /* User can add his own implementation to report the file name and line number,
     ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
  /* USER CODE END 6 */
}
#endif /* USE_FULL_ASSERT */

窗口看门狗

步骤如下:

  1. 配置WWDG时钟: 在使用WWDG之前,需要先使能其时钟。这通常通过调用__HAL_RCC_WWDG_CLK_ENABLE()宏来实现。

  2. 初始化WWDG句柄: 创建一个WWDG_HandleTypeDef类型的结构体变量,用于配置WWDG的参数。

  3. 配置WWDG参数: 在WWDG_HandleTypeDef结构体中设置WWDG的参数,包括预分频器(Prescaler)、窗口值(Window)、计数器值(Counter)和早期中断(EWI)模式。

  4. 初始化WWDG: 调用HAL_WWDG_Init()函数,传入步骤2中创建的WWDG句柄作为参数,以初始化WWDG。

  5. 实现MspInit回调函数(如果需要): 如果需要在WWDG初始化过程中执行特定的硬件配置,可以重写HAL_WWDG_MspInit()函数。

  6. 在主循环中刷新WWDG: 在主循环中,定期调用HAL_WWDG_Refresh()函数来刷新WWDG的计数器,以防止WWDG复位。

  7. 处理错误情况: 如果HAL_WWDG_Init()HAL_WWDG_Refresh()函数返回错误码(非HAL_OK),应该有相应的错误处理机制。

  8. 可选:实现中断回调函数: 如果启用了早期中断(EWI),则需要实现HAL_WWDG_EarlyWakeupCallback()函数来处理中断。

窗口看门狗HAL库函数:

  1. HAL_WWDG_Init: 初始化窗口看门狗,设置预分频器、窗口值和计数器值。
  2. HAL_WWDG_Refresh: 更新窗口看门狗的计数器,以防止看门狗复位。
  3. HAL_WWDG_IRQHandler: 窗口看门狗中断处理函数。
  4. HAL_WWDG_MspInit: 窗口看门狗底层硬件初始化函数。
  5. HAL_WWDG_EarlyWakeupCallback:回调函数,它在窗口看门狗的早期唤醒中断发生时被调用

  6. HAL_WWDG_MODULE_ENABLED 是一个宏,用于在HAL库的配置文件 stm32fXxx_hal_conf.h 中启用或禁用窗口看门狗模块。

WWDG会触发以下动作:

  1. 系统复位:WWDG会生成一个系统复位信号,将微控制器重置到其初始状态。这是WWDG的主要功能,用于确保系统在出现软件故障或硬件故障时能够自动恢复。

  2. 早期中断(EWI):如果在WWDG的配置中启用了早期中断(EWI)功能,那么在计数器接近0之前,WWDG会生成一个中断。这个中断可以用来执行一些清理操作或日志记录,以便在系统复位之前保存重要的信息。

STM32cude MX (要设置一下值和分频值我下面设置的太快了)

在STM32微控制器中,窗口看门狗(WWDG)的时间计算依赖于内部低速时钟(LSI)和预分频器设置。以下是计算WWDG超时时间的基本步骤

源码

/* USER CODE BEGIN Header */
/**
  ******************************************************************************
  * @file           : main.c
  * @brief          : Main program body
  ******************************************************************************
  * @attention
  *
  * Copyright (c) 2024 STMicroelectronics.
  * All rights reserved.
  *
  * This software is licensed under terms that can be found in the LICENSE file
  * in the root directory of this software component.
  * If no LICENSE file comes with this software, it is provided AS-IS.
  *
  ******************************************************************************
  */
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "usart.h"
#include "wwdg.h"
#include "gpio.h"

/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */

/* USER CODE END Includes */

/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */

/* USER CODE END PTD */

/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */

/* USER CODE END PD */

/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */

/* USER CODE END PM */

/* Private variables ---------------------------------------------------------*/

/* USER CODE BEGIN PV */

/* USER CODE END PV */

/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
/* USER CODE BEGIN PFP */

/* USER CODE END PFP */

/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */

/* USER CODE END 0 */

/**
  * @brief  The application entry point.
  * @retval int
  */
int main(void)
{

  /* USER CODE BEGIN 1 */

  /* USER CODE END 1 */

  /* MCU Configuration--------------------------------------------------------*/

  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();

  /* USER CODE BEGIN Init */

  /* USER CODE END Init */

  /* Configure the system clock */
  SystemClock_Config();

  /* USER CODE BEGIN SysInit */

  /* USER CODE END SysInit */

  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_USART1_UART_Init();
  MX_WWDG_Init();
  /* USER CODE BEGIN 2 */
//HAL_Delay(1000);//

  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
		HAL_WWDG_Refresh(&hwwdg);
		char a[]={"已喂狗"};
		HAL_UART_Transmit(&huart1,(uint8_t*)a,6,20);
		//HAL_WWDG_Refresh(&hwwdg);
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
  }
  /* USER CODE END 3 */
}

/**
  * @brief System Clock Configuration
  * @retval None
  */
void SystemClock_Config(void)
{
  RCC_OscInitTypeDef RCC_OscInitStruct = {0};
  RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};

  /** Initializes the RCC Oscillators according to the specified parameters
  * in the RCC_OscInitTypeDef structure.
  */
  RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
  RCC_OscInitStruct.HSEState = RCC_HSE_ON;
  RCC_OscInitStruct.HSEPredivValue = RCC_HSE_PREDIV_DIV1;
  RCC_OscInitStruct.HSIState = RCC_HSI_ON;
  RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
  RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
  RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL9;
  if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
  {
    Error_Handler();
  }

  /** Initializes the CPU, AHB and APB buses clocks
  */
  RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
                              |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
  RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
  RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
  RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2;
  RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;

  if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK)
  {
    Error_Handler();
  }
}

/* USER CODE BEGIN 4 */

/* USER CODE END 4 */

/**
  * @brief  This function is executed in case of error occurrence.
  * @retval None
  */
void Error_Handler(void)
{
  /* USER CODE BEGIN Error_Handler_Debug */
  /* User can add his own implementation to report the HAL error return state */
  __disable_irq();
  while (1)
  {
  }
  /* USER CODE END Error_Handler_Debug */
}

#ifdef  USE_FULL_ASSERT
/**
  * @brief  Reports the name of the source file and the source line number
  *         where the assert_param error has occurred.
  * @param  file: pointer to the source file name
  * @param  line: assert_param error line source number
  * @retval None
  */
void assert_failed(uint8_t *file, uint32_t line)
{
  /* USER CODE BEGIN 6 */
  /* User can add his own implementation to report the file name and line number,
     ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
  /* USER CODE END 6 */
}
#endif /* USE_FULL_ASSERT */

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

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

相关文章

关系数据库:关系模式

文章目录 基本概述关系的相关名词术语笛卡儿积与关系关系的类型 关系模式总结 基本概述 关系的相关名词术语 关系:简单来说,就是一张二维表格。属性(Attribute):也称字段或列,在现实世界中,要描述一个事务常常取若干…

私域加持业务 快消门店运营新玩法

两个月前,某快消品企业的李总急切地联系了纷享销客,希望能找到解决终端门店运营难题的有效方法。 Step1、连接终端门店,导入私域进行深度维系与运营 一、与终端门店建立联系 为了与众多门店老板建立紧密的联系,并将他们转化为企…

ERV-Net:一种用于脑肿瘤分割的高效3D残差神经网络| 文献速递-深度学习肿瘤自动分割

Title 题目 ERV-Net: An efficient 3D residual neural network for brain tumor segmentation ERV-Net:一种用于脑肿瘤分割的高效3D残差神经网络 01 文献速递介绍 脑肿瘤在全球范围内是致命的,与其他类型的肿瘤相比。胶质瘤是最具侵略性的脑肿瘤类…

pyinstaller将py文件打包成exe

pyinstaller将py文件打包成exe 一、为什么需要将python文件打包成exe文件?二、具体操作步骤一、为什么需要将python文件打包成exe文件? python文件需要在python环境中运行,也就是需要安装python解释器。有时我们自己写的python程序需要分享给自己的朋友、同事或者合作伙伴,…

两数之和 II - 输入有序数组,三数之和

题目一&#xff1a; 代码如下&#xff1a; vector<int> twoSum(vector<int>& numbers, int target) {int left 0;int right numbers.size() - 1;vector<int> ret;while (left < right){int tmp numbers[left] numbers[right];if (tmp target){r…

flink 操作mongodb的例子

简述 该例子为从一个Collection获取数据然后插入到另外一个Collection中。 Flink的基本处理过程可以清晰地分为以下几个阶段&#xff1a; 数据源&#xff08;Source&#xff09;&#xff1a; Flink可以从多种数据源中读取数据&#xff0c;如Kafka、RabbitMQ、HDFS等。Flink会…

SpringBoot案例,通关版

项目目录 此项目为了伙伴们可以快速入手SpringBoot项目,全网最详细的版本,每个伙伴都可以学会,这个项目每一步都会带大家做,学完后可以保证熟悉SpringBoot的开发流程项目介绍:项目使用springboot mybatis进行开发带你一起写小项目先把初始环境给你们第一步新建springboot项目返…

HTTP协议介绍与TCP协议的区别

1、HTTP介绍 HTTP&#xff08;超文本传输协议&#xff0c;Hypertext Transfer Protocol&#xff09;是一种用于从网络传输超文本到本地浏览器的传输协议。它定义了客户端与服务器之间请求和响应的格式。HTTP 是基于TCP/IP 进行数据的通信&#xff0c;通常使用端口 80/8080。HTT…

项目纪实 | 版本升级操作get!GreatDB分布式升级过程详解

某客户项目现场&#xff0c;因其业务系统要用到数据库新版本中的功能特性&#xff0c;因此考虑升级现有数据库版本。在升级之前&#xff0c;万里数据库项目团队帮助客户在本地测试环境构造了相同的基础版本&#xff0c;导入部分生产数据&#xff0c;尽量复刻生产环境进行升级&a…

机器学习笔记(1):sklearn是个啥?

sklearn 简介 Sklearn是一个基于Python语言的开源机器学习库。全称Scikit-Learn&#xff0c;是建立在诸如NumPy、SciPy和matplotlib等其他Python库之上&#xff0c;为用户提供了一系列高质量的机器学习算法&#xff0c;其典型特点有&#xff1a; 简单有效的工具进行预测数据分…

GEYA格亚GRT8-S1S2间歇性双时间循环继电器时间可调交流220V 24v

品牌 GEYA 型号 GRT8-S2 AC/DC12-240V 产地 中国大陆 颜色分类 GRT8-S1 A220,GRT8-S1 AC/DC12-240V,GRT8-S2 A220,GRT8-S2 AC/DC12-240V GRT8-S&#xff0c;循环延时&#xff0c;时间继电器&#xff1a;LED指示灯&#xff0c;触头容量大&#xff0c;电压超宽&#xff0…

构建树结构的几种方式

表结构 CREATE TABLE sys_dept (dept_id bigint(20) NOT NULL AUTO_INCREMENT COMMENT ID,pid bigint(20) DEFAULT NULL COMMENT 上级部门,sub_count int(5) DEFAULT 0 COMMENT 子部门数目,name varchar(255) NOT NULL COMMENT 名称,dept_sort int(5) DEFAULT 999 COMMENT 排…

【C#】类和对象的区别

1.区别概述 结构体和类的最大区别是在存储空间上&#xff0c;前者是值类型&#xff0c;后者是引用类型&#xff0c;它们在赋值上有很大的区别&#xff0c;在类中指向同一块空间的两个类的值会随一个类的改变而改变另一个&#xff0c;请看如下代码所示&#xff1a; namespace …

020.有效的括号,用栈来解决的 Java 版 LeetCode 刷题笔记

题意 给定一个只包括 (&#xff0c;)&#xff0c;{&#xff0c;}&#xff0c;[&#xff0c;] 的字符串 s &#xff0c;判断字符串是否有效。 有效字符串需满足&#xff1a; 左括号必须用相同类型的右括号闭合。左括号必须以正确的顺序闭合。每个右括号都有一个对应的相同类型…

FreeRTOS【12】队列集使用

1.开发背景 基于以上的章节&#xff0c;了解了 FreeRTOS 多线程间的信号量、队列的使用&#xff0c;已经满足了日常使用场景。这个篇章要介绍的是队列集&#xff0c;实际上队列的升级版&#xff0c;存储信号量和队列等的触发事件。 队列集在实际的开发项目中应用相对比较少&…

linux同步搭建多台服务器

前言&#xff1a; 如果在安装服务器的过程中&#xff0c;需要安装多台服务器&#xff0c;同样的配置&#xff0c;同样的步骤就可以使用此方法&#xff0c;搭建集群同步安装 1.配置网卡 想要两台机器进行同步的话&#xff0c;必须网段是同样的&#xff0c;保持在同一网段并且能…

科技智慧园区解决方案

随着科技创新的推动和城市化进程的加速&#xff0c;城市面临着诸多挑战和机遇。如何提升城市的竞争力和可持续性&#xff0c;是一个亟待解决的问题。在这个背景下&#xff0c;科技智慧园区作为一种新型的城市发展模式&#xff0c;引起了越来越多的关注和探索。 什么是科技智慧园…

Jmeter的线程组之间传递参数

使用jemter做接口测试&#xff0c;有时候需要会遇到不同线程组之间调用相同变量的情况&#xff0c;最多见的就是token的传递&#xff0c;网上有很多处理方法&#xff0c;这里只记录setProperty的办法&#xff0c;一招鲜走遍天&#xff01; 首先我有两个线程组&#xff1a; 线程…

Servlet搭建博客系统

现在我们可以使用Servlet来搭建一个动态(前后端可以交互)的博客系统了(使用Hexo只能实现一个纯静态的网页,即只能在后台自己上传博客)。有一种"多年媳妇熬成婆"的感觉。 一、准备工作 首先创建好项目,引入相关依赖。具体过程在"Servlet的创建"中介绍了。…

WiFi蓝牙模块促进传统零售数字化转型:智能零售体验再升级

随着科技的不断发展&#xff0c;数字化转型已经成为了各行各业的必然趋势。在传统零售业中&#xff0c;WiFi蓝牙模块的应用正逐渐推动着行业的数字化转型&#xff0c;为消费者带来更加智能化、便捷化的零售体验。本文MesoonRF美迅物联网将从以下几个方面阐述WiFi蓝牙模块在传统…