8、nRF52xx蓝牙学习(boards.h文件学习)
boards.h文件的代码如下:
#ifndef BOARDS_H
#define BOARDS_H#include "nrf_gpio.h"
#include "nordic_common.h"#if defined(BOARD_NRF6310)#include "nrf6310.h"
#elif defined(BOARD_PCA10000)#include "pca10000.h"
#elif defined(BOARD_PCA10001)#include "pca10001.h"
#elif defined(BOARD_PCA10002)#include "pca10000.h"
#elif defined(BOARD_PCA10003)#include "pca10003.h"
#elif defined(BOARD_PCA20006)#include "pca20006.h"
#elif defined(BOARD_PCA10028)#include "pca10028.h"
#elif defined(BOARD_PCA10031)#include "pca10031.h"
#elif defined(BOARD_PCA10036)#include "pca10036.h"
#elif defined(BOARD_PCA10040)#include "pca10040.h"
#elif defined(BOARD_PCA10056)#include "pca10056.h"
#elif defined(BOARD_PCA10100)#include "pca10100.h"
#elif defined(BOARD_PCA10112)#include "pca10112.h"
#elif defined(BOARD_PCA20020)#include "pca20020.h"
#elif defined(BOARD_PCA10059)#include "pca10059.h"
#elif defined(BOARD_WT51822)#include "wt51822.h"
#elif defined(BOARD_N5DK1)#include "n5_starterkit.h"
#elif defined (BOARD_D52DK1)#include "d52_starterkit.h"
#elif defined (BOARD_ARDUINO_PRIMO)#include "arduino_primo.h"
#elif defined (CUSTOM_BOARD_INC)#include STRINGIFY(CUSTOM_BOARD_INC.h)
#elif defined(BOARD_CUSTOM)#include "custom_board.h"
#else
#error "Board is not defined"#endif#if defined (SHIELD_BSP_INC)#include STRINGIFY(SHIELD_BSP_INC.h)
#endif#ifdef __cplusplus
extern "C" {
#endif/**@defgroup BSP_BOARD_INIT_FLAGS Board initialization flags.* @{ */
#define BSP_INIT_NONE 0 /**< No initialization of LEDs or buttons (@ref bsp_board_init).*/
#define BSP_INIT_LEDS (1 << 0) /**< Enable LEDs during initialization (@ref bsp_board_init).*/
#define BSP_INIT_BUTTONS (1 << 1) /**< Enable buttons during initialization (@ref bsp_board_init).*/
/**@} *//*** Function for returning the state of an LED.** @param led_idx LED index (starting from 0), as defined in the board-specific header.** @return True if the LED is turned on.*/
bool bsp_board_led_state_get(uint32_t led_idx);/*** Function for turning on an LED.** @param led_idx LED index (starting from 0), as defined in the board-specific header.*/
void bsp_board_led_on(uint32_t led_idx);/*** Function for turning off an LED.** @param led_idx LED index (starting from 0), as defined in the board-specific header.*/
void bsp_board_led_off(uint32_t led_idx);/*** Function for inverting the state of an LED.** @param led_idx LED index (starting from 0), as defined in the board-specific header.*/
void bsp_board_led_invert(uint32_t led_idx);
/*** Function for turning off all LEDs.*/
void bsp_board_leds_off(void);/*** Function for turning on all LEDs.*/
void bsp_board_leds_on(void);/*** Function for initializing the BSP handling for the board.** @note This also initializes the USB DFU trigger library if @ref BOARDS_WITH_USB_DFU_TRIGGER is 1.** @param[in] init_flags Flags specifying what to initialize (LEDs/buttons).* See @ref BSP_BOARD_INIT_FLAGS.*/
void bsp_board_init(uint32_t init_flags);/*** Function for converting pin number to LED index.** @param pin_number Pin number.** @return LED index of the given pin or 0xFFFFFFFF if invalid pin provided.*/
uint32_t bsp_board_pin_to_led_idx(uint32_t pin_number);/*** Function for converting LED index to pin number.** @param led_idx LED index.** @return Pin number.*/
uint32_t bsp_board_led_idx_to_pin(uint32_t led_idx);/*** Function for returning the state of a button.** @param button_idx Button index (starting from 0), as defined in the board-specific header.** @return True if the button is pressed.*/
bool bsp_board_button_state_get(uint32_t button_idx);/*** Function for converting pin number to button index.** @param pin_number Pin number.** @return Button index of the given pin or 0xFFFFFFFF if invalid pin provided.*/
uint32_t bsp_board_pin_to_button_idx(uint32_t pin_number);/*** Function for converting button index to pin number.** @param button_idx Button index.** @return Pin number.*/
uint32_t bsp_board_button_idx_to_pin(uint32_t button_idx);#define BSP_BOARD_LED_0 0
#define BSP_BOARD_LED_1 1
#define BSP_BOARD_LED_2 2
#define BSP_BOARD_LED_3 3
#define BSP_BOARD_LED_4 4
#define BSP_BOARD_LED_5 5
#define BSP_BOARD_LED_6 6
#define BSP_BOARD_LED_7 7#define PIN_MASK(_pin) /*lint -save -e504 */ \(1u << (uint32_t)((_pin) & (~P0_PIN_NUM))) \/*lint -restore */#define PIN_PORT(_pin) (((_pin) >= P0_PIN_NUM) ? NRF_P1 : NRF_GPIO)#ifdef BSP_LED_0
#define BSP_LED_0_MASK PIN_MASK(BSP_LED_0)
#define BSP_LED_0_PORT PIN_PORT(BSP_LED_0)
#else
#define BSP_LED_0_MASK 0
#define BSP_LED_0_PORT 0
#endif
#ifdef BSP_LED_1
#define BSP_LED_1_MASK PIN_MASK(BSP_LED_1)
#define BSP_LED_1_PORT PIN_PORT(BSP_LED_1)
#else
#define BSP_LED_1_MASK 0
#define BSP_LED_1_PORT 0
#endif
#ifdef BSP_LED_2
#define BSP_LED_2_MASK PIN_MASK(BSP_LED_2)
#define BSP_LED_2_PORT PIN_PORT(BSP_LED_2)
#else
#define BSP_LED_2_MASK 0
#define BSP_LED_2_PORT 0
#endif
#ifdef BSP_LED_3
#define BSP_LED_3_MASK PIN_MASK(BSP_LED_3)
#define BSP_LED_3_PORT PIN_PORT(BSP_LED_3)
#else
#define BSP_LED_3_MASK 0
#define BSP_LED_3_PORT 0
#endif
#ifdef BSP_LED_4
#define BSP_LED_4_MASK PIN_MASK(BSP_LED_4)
#define BSP_LED_4_PORT PIN_PORT(BSP_LED_4)
#else
#define BSP_LED_4_MASK 0
#define BSP_LED_4_PORT 0
#endif
#ifdef BSP_LED_5
#define BSP_LED_5_MASK PIN_MASK(BSP_LED_5)
#define BSP_LED_5_PORT PIN_PORT(BSP_LED_5)
#else
#define BSP_LED_5_MASK 0
#define BSP_LED_5_PORT 0
#endif
#ifdef BSP_LED_6
#define BSP_LED_6_MASK PIN_MASK(BSP_LED_6)
#define BSP_LED_6_PORT PIN_PORT(BSP_LED_6)
#else
#define BSP_LED_6_MASK 0
#define BSP_LED_6_PORT 0
#endif
#ifdef BSP_LED_7
#define BSP_LED_7_MASK PIN_MASK(BSP_LED_7)
#define BSP_LED_7_PORT PIN_PORT(BSP_LED_7)
#else
#define BSP_LED_7_MASK 0
#define BSP_LED_7_PORT 0
#endif#define LEDS_MASK (BSP_LED_0_MASK | BSP_LED_1_MASK | \BSP_LED_2_MASK | BSP_LED_3_MASK | \BSP_LED_4_MASK | BSP_LED_5_MASK | \BSP_LED_6_MASK | BSP_LED_7_MASK)#define BSP_BOARD_BUTTON_0 0
#define BSP_BOARD_BUTTON_1 1
#define BSP_BOARD_BUTTON_2 2
#define BSP_BOARD_BUTTON_3 3
#define BSP_BOARD_BUTTON_4 4
#define BSP_BOARD_BUTTON_5 5
#define BSP_BOARD_BUTTON_6 6
#define BSP_BOARD_BUTTON_7 7#ifdef BSP_BUTTON_0
#define BSP_BUTTON_0_MASK (1<<BSP_BUTTON_0)
#else
#define BSP_BUTTON_0_MASK 0
#endif
#ifdef BSP_BUTTON_1
#define BSP_BUTTON_1_MASK (1<<BSP_BUTTON_1)
#else
#define BSP_BUTTON_1_MASK 0
#endif
#ifdef BSP_BUTTON_2
#define BSP_BUTTON_2_MASK (1<<BSP_BUTTON_2)
#else
#define BSP_BUTTON_2_MASK 0
#endif
#ifdef BSP_BUTTON_3
#define BSP_BUTTON_3_MASK (1<<BSP_BUTTON_3)
#else
#define BSP_BUTTON_3_MASK 0
#endif
#ifdef BSP_BUTTON_4
#define BSP_BUTTON_4_MASK (1<<BSP_BUTTON_4)
#else
#define BSP_BUTTON_4_MASK 0
#endif
#ifdef BSP_BUTTON_5
#define BSP_BUTTON_5_MASK (1<<BSP_BUTTON_5)
#else
#define BSP_BUTTON_5_MASK 0
#endif
#ifdef BSP_BUTTON_6
#define BSP_BUTTON_6_MASK (1<<BSP_BUTTON_6)
#else
#define BSP_BUTTON_6_MASK 0
#endif
#ifdef BSP_BUTTON_7
#define BSP_BUTTON_7_MASK (1<<BSP_BUTTON_7)
#else
#define BSP_BUTTON_7_MASK 0
#endif#define BUTTONS_MASK (BSP_BUTTON_0_MASK | BSP_BUTTON_1_MASK | \BSP_BUTTON_2_MASK | BSP_BUTTON_3_MASK | \BSP_BUTTON_4_MASK | BSP_BUTTON_5_MASK | \BSP_BUTTON_6_MASK | BSP_BUTTON_7_MASK)/* This macro is supporting only P0 and should not be used if LEDs are on other ports. */
#define LEDS_OFF(leds_mask) do { ASSERT(sizeof(leds_mask) == 4); \NRF_GPIO->OUTSET = (leds_mask) & (LEDS_MASK & LEDS_INV_MASK); \NRF_GPIO->OUTCLR = (leds_mask) & (LEDS_MASK & ~LEDS_INV_MASK); } while (0)/* This macro is supporting only P0 and should not be used if LEDs are on other ports. */
#define LEDS_ON(leds_mask) do { ASSERT(sizeof(leds_mask) == 4); \NRF_GPIO->OUTCLR = (leds_mask) & (LEDS_MASK & LEDS_INV_MASK); \NRF_GPIO->OUTSET = (leds_mask) & (LEDS_MASK & ~LEDS_INV_MASK); } while (0)/* This macro is supporting only P0 and should not be used if LEDs are on other ports. */
#define LED_IS_ON(leds_mask) ((leds_mask) & (NRF_GPIO->OUT ^ LEDS_INV_MASK) )/* This macro is supporting only P0 and should not be used if LEDs are on other ports. */
#define LEDS_INVERT(leds_mask) do { uint32_t gpio_state = NRF_GPIO->OUT; \ASSERT(sizeof(leds_mask) == 4); \NRF_GPIO->OUTSET = ((leds_mask) & ~gpio_state); \NRF_GPIO->OUTCLR = ((leds_mask) & gpio_state); } while (0)/* This macro is supporting only P0 and should not be used if LEDs are on other ports. */
#define LEDS_CONFIGURE(leds_mask) do { uint32_t pin; \ASSERT(sizeof(leds_mask) == 4); \for (pin = 0; pin < 32; pin++) \if ( (leds_mask) & (1 << pin) ) \nrf_gpio_cfg_output(pin); } while (0)#ifdef __cplusplus
}
#endif#endif
代码理解如下:
这是一个名为 BOARDS_H 的头文件代码,主要用于定义与开发板相关的配置、引脚操作函数声明以及一些常用的宏定义。
下面对其进行详细解释:
1. 头文件保护
#ifndef BOARDS_H
#define BOARDS_H
这是头文件保护宏,防止该头文件被重复包含,确保头文件中的内容在一个编译单元中只被处理一次。
2. 包含其他头文件
#include "nrf_gpio.h"
#include "nordic_common.h"
包含了 nrf_gpio.h 和 nordic_common.h 头文件,前者可能提供了与 Nordic 芯片 GPIO 操作相关的定义和函数声明,后者可能包含了 Nordic 相关的通用定义和工具函数。
3. 根据不同开发板包含对应头文件
#if defined(BOARD_NRF6310)
#include "nrf6310.h"
#elif defined(BOARD_PCA10000)
#include "pca10000.h"
#elif defined(BOARD_PCA10001)
#include "pca10001.h"
#elif defined(BOARD_PCA10002)
#include "pca10000.h"
#elif defined(BOARD_PCA10003)
#include "pca10003.h"
#elif defined(BOARD_PCA20006)
#include "pca20006.h"
#elif defined(BOARD_PCA10028)
#include "pca10028.h"
#elif defined(BOARD_PCA10031)
#include "pca10031.h"
#elif defined(BOARD_PCA10036)
#include "pca10036.h"
#elif defined(BOARD_PCA10040)
#include "pca10040.h"
#elif defined(BOARD_PCA10056)
#include "pca10056.h"
#elif defined(BOARD_PCA10100)
#include "pca10100.h"
#elif defined(BOARD_PCA10112)
#include "pca10112.h"
#elif defined(BOARD_PCA20020)
#include "pca20020.h"
#elif defined(BOARD_PCA10059)
#include "pca10059.h"
#elif defined(BOARD_WT51822)
#include "wt51822.h"
#elif defined(BOARD_N5DK1)
#include "n5_starterkit.h"
#elif defined (BOARD_D52DK1)
#include "d52_starterkit.h"
#elif defined (BOARD_ARDUINO_PRIMO)
#include "arduino_primo.h"
#elif defined (CUSTOM_BOARD_INC)
#include STRINGIFY(CUSTOM_BOARD_INC.h)
#elif defined(BOARD_CUSTOM)
#include "custom_board.h"
#else
#error "Board is not defined"
#endif
根据不同的 BOARD_* 宏定义,包含相应开发板的特定头文件。如果没有定义任何一个已知的开发板宏,则会产生编译错误,提示 Board is not defined。
4. 包含扩展板相关头文件
#if defined (SHIELD_BSP_INC)
#include STRINGIFY(SHIELD_BSP_INC.h)
#endif
如果定义了 SHIELD_BSP_INC 宏,则包含相应的扩展板头文件。
5. C++ 兼容声明
#ifdef __cplusplus
extern "C" {
#endif
如果是 C++ 编译环境,使用 extern "C" 声明,确保 C 语言风格的函数声明在 C++ 中具有正确的链接属性,以便 C++ 代码可以调用这些函数。
6. 开发板初始化标志宏定义
#define BSP_INIT_NONE 0 /**< No initialization of LEDs or buttons (@ref bsp_board_init).*/
#define BSP_INIT_LEDS (1 << 0) /**< Enable LEDs during initialization (@ref bsp_board_init).*/
#define BSP_INIT_BUTTONS (1 << 1) /**< Enable buttons during initialization (@ref bsp_board_init).*/
定义了三个宏,用于表示开发板初始化时的不同标志:
• BSP_INIT_NONE:表示不初始化 LED 和按键。
• BSP_INIT_LEDS:表示初始化时启用 LED。
• BSP_INIT_BUTTONS:表示初始化时启用按键。
7. LED 操作函数声明
bool bsp_board_led_state_get(uint32_t led_idx);
void bsp_board_led_on(uint32_t led_idx);
void bsp_board_led_off(uint32_t led_idx);
void bsp_board_led_invert(uint32_t led_idx);
void bsp_board_leds_off(void);
void bsp_board_leds_on(void);
声明了一系列与 LED 操作相关的函数:
• bsp_board_led_state_get:获取指定 LED 的状态(是否点亮)。
• bsp_board_led_on:点亮指定的 LED。
• bsp_board_led_off:熄灭指定的 LED。
• bsp_board_led_invert:反转指定 LED 的状态。
• bsp_board_leds_off:熄灭所有 LED。
• bsp_board_leds_on:点亮所有 LED。
8. 开发板初始化函数声明
void bsp_board_init(uint32_t init_flags);
声明了开发板初始化函数 bsp_board_init,接受一个 init_flags 参数,根据传入的标志决定初始化哪些部分(如 LED 和按键)。
9. 引脚与 LED 索引转换函数声明
uint32_t bsp_board_pin_to_led_idx(uint32_t pin_number);
uint32_t bsp_board_led_idx_to_pin(uint32_t led_idx);
声明了两个函数用于在引脚编号和 LED 索引之间进行转换:
• bsp_board_pin_to_led_idx:将引脚编号转换为 LED 索引。
• bsp_board_led_idx_to_pin:将 LED 索引转换为引脚编号。
10. 按键操作函数声明
bool bsp_board_button_state_get(uint32_t button_idx);
uint32_t bsp_board_pin_to_button_idx(uint32_t pin_number);
uint32_t bsp_board_button_idx_to_pin(uint32_t button_idx);
声明了一系列与按键操作相关的函数:
• bsp_board_button_state_get:获取指定按键的状态(是否按下)。 • bsp_board_pin_to_button_idx:将引脚编号转换为按键索引。
• bsp_board_button_idx_to_pin:将按键索引转换为引脚编号。
11. LED 和按键编号宏定义
#define BSP_BOARD_LED_0 0
#define BSP_BOARD_LED_1 1
#define BSP_BOARD_LED_2 2
#define BSP_BOARD_LED_3 3
#define BSP_BOARD_LED_4 4
#define BSP_BOARD_LED_5 5
#define BSP_BOARD_LED_6 6
#define BSP_BOARD_LED_7 7
#define BSP_BOARD_BUTTON_0 0
#define BSP_BOARD_BUTTON_1 1
#define BSP_BOARD_BUTTON_2 2
#define BSP_BOARD_BUTTON_3 3
#define BSP_BOARD_BUTTON_4 4
#define BSP_BOARD_BUTTON_5 5
#define BSP_BOARD_BUTTON_6 6
#define BSP_BOARD_BUTTON_7 7
定义了 LED 和按键的编号宏,从 0 到 7,用于标识不同的 LED 和按键。
12. 引脚掩码和端口宏定义
#define PIN_MASK(_pin) /*lint -save -e504 */ \
(1u << (uint32_t)((_pin) & (~P0_PIN_NUM))) \
/*lint -restore */
#define PIN_PORT(_pin) (((_pin) >= P0_PIN_NUM) ? NRF_P1 : NRF_GPIO)
• PIN_MASK:根据引脚编号生成引脚掩码,用于后续对引脚的操作。
• PIN_PORT:根据引脚编号判断引脚所属的端口(NRF_P1 或 NRF_GPIO)。
13. 每个 LED 的掩码和端口定义
#ifdef BSP_LED_0
#define BSP_LED_0_MASK PIN_MASK(BSP_LED_0)
#define BSP_LED_0_PORT PIN_PORT(BSP_LED_0)
#else
#define BSP_LED_0_MASK 0
#define BSP_LED_0_PORT 0
#endif
// 其他 LED 类似
根据是否定义了相应的 BSP_LED_X 宏,为每个 LED 生成掩码和端口定义。如果未定义,则掩码和端口都设为 0。
14. 所有 LED 和按键的总掩码宏定义
#define LEDS_MASK (BSP_LED_0_MASK | BSP_LED_1_MASK | \
BSP_LED_2_MASK | BSP_LED_3_MASK | \
BSP_LED_4_MASK | BSP_LED_5_MASK | \
BSP_LED_6_MASK | BSP_LED_7_MASK)
#define BUTTONS_MASK (BSP_BUTTON_0_MASK | BSP_BUTTON_1_MASK | \
BSP_BUTTON_2_MASK | BSP_BUTTON_3_MASK | \
BSP_BUTTON_4_MASK | BSP_BUTTON_5_MASK | \
BSP_BUTTON_6_MASK | BSP_BUTTON_7_MASK)
分别将所有 LED 和按键的掩码进行按位或操作,得到所有 LED 和按键的总掩码。
15. LED 控制宏定义
#define LEDS_OFF(leds_mask) do { ASSERT(sizeof(leds_mask) == 4); \
NRF_GPIO->OUTSET = (leds_mask) & (LEDS_MASK & LEDS_INV_MASK); \
NRF_GPIO->OUTCLR = (leds_mask) & (LEDS_MASK & ~LEDS_INV_MASK); } while (0)
#define LEDS_ON(leds_mask) do { ASSERT(sizeof(leds_mask) == 4); \
NRF_GPIO->OUTCLR = (leds_mask) & (LEDS_MASK & LEDS_INV_MASK); \
NRF_GPIO->OUTSET = (leds_mask) & (LEDS_MASK & ~LEDS_INV_MASK); } while (0)
#define LED_IS_ON(leds_mask) ((leds_mask) & (NRF_GPIO->OUT ^ LEDS_INV_MASK) )
#define LEDS_INVERT(leds_mask) do { uint32_t gpio_state = NRF_GPIO->OUT; \
ASSERT(sizeof(leds_mask) == 4); \
NRF_GPIO->OUTSET = ((leds_mask) & ~gpio_state); \
NRF_GPIO->OUTCLR = ((leds_mask) & gpio_state); } while (0)
#define LEDS_CONFIGURE(leds_mask) do { uint32_t pin; \
ASSERT(sizeof(leds_mask) == 4); \
for (pin = 0; pin < 32; pin++) \
if ( (leds_mask) & (1 << pin) ) \
nrf_gpio_cfg_output(pin); } while (0)
定义了一系列用于控制 LED 的宏:
• LEDS_OFF:熄灭指定的 LED。
• LEDS_ON:点亮指定的 LED。
• LED_IS_ON:判断指定的 LED 是否点亮。
• LEDS_INVERT:反转指定 LED 的状态。
• LEDS_CONFIGURE:将指定的引脚配置为输出模式,用于控制 LED。
16. C++ 兼容结束声明
#ifdef __cplusplus
}
#endif
如果是 C++ 编译环境,结束 extern "C" 声明。
17. 头文件保护宏结束
#endif
结束头文件保护宏,确保头文件内容只被包含一次。 总的来说,这个头文件为开发板的 GPIO 操作,特别是 LED 和按键的控制,提供了统一的接口和配置方式,方便在不同的开发板上进行应用开发。
以下是对 BOARDS_H 头文件中定义的函数和宏的功能详细说明:
函数 1. LED 操作函数
• bool bsp_board_led_state_get(uint32_t led_idx); ◦
功能:获取指定索引的 LED 当前状态。若 LED 处于点亮状态则返回 true,反之返回 false。 ◦ 参数:led_idx 是 LED 的索引,从 0 开始计数。
• void bsp_board_led_on(uint32_t led_idx); ◦
功能:点亮指定索引的 LED。 ◦ 参数:led_idx 是 LED 的索引,从 0 开始计数。
• void bsp_board_led_off(uint32_t led_idx); ◦
功能:熄灭指定索引的 LED。 ◦ 参数:led_idx 是 LED 的索引,从 0 开始计数。
• void bsp_board_led_invert(uint32_t led_idx); ◦
功能:反转指定索引 LED 的状态,即若 LED 点亮则熄灭,若熄灭则点亮。 ◦
参数:led_idx 是 LED 的索引,从 0 开始计数。
• void bsp_board_leds_off(void); ◦
功能:熄灭开发板上的所有 LED。
• void bsp_board_leds_on(void); ◦
功能:点亮开发板上的所有 LED。
2. 开发板初始化函数
• void bsp_board_init(uint32_t init_flags); ◦
功能:对开发板进行初始化操作,依据传入的 init_flags 参数来决定初始化哪些部分(如 LED 和按键)。
参数:init_flags 是初始化标志,可通过 BSP_INIT_NONE、BSP_INIT_LEDS、BSP_INIT_BUTTONS 等宏进行组合。
3. 引脚与 LED 索引转换函数
• uint32_t bsp_board_pin_to_led_idx(uint32_t pin_number); ◦
功能:把引脚编号转换为对应的 LED 索引。若传入的引脚编号无效,则返回 0xFFFFFFFF。 ◦
参数:pin_number 是引脚编号。
• uint32_t bsp_board_led_idx_to_pin(uint32_t led_idx); ◦
功能:将 LED 索引转换为对应的引脚编号。 ◦
参数:led_idx 是 LED 的索引,从 0 开始计数。
4. 按键操作函数
• bool bsp_board_button_state_get(uint32_t button_idx); ◦
功能:获取指定索引的按键当前状态。若按键被按下则返回 true,反之返回 false。 ◦
参数:button_idx 是按键的索引,从 0 开始计数。
• uint32_t bsp_board_pin_to_button_idx(uint32_t pin_number); ◦
功能:把引脚编号转换为对应的按键索引。若传入的引脚编号无效,则返回 0xFFFFFFFF。 ◦
参数:pin_number 是引脚编号。
• uint32_t bsp_board_button_idx_to_pin(uint32_t button_idx); ◦
功能:将按键索引转换为对应的引脚编号。 ◦
参数:button_idx 是按键的索引,从 0 开始计数。
宏 1. 开发板初始化标志宏
• #define BSP_INIT_NONE 0 ◦
功能:表示在初始化时不初始化 LED 和按键。
• #define BSP_INIT_LEDS (1 << 0) ◦
功能:表示在初始化时启用 LED。
• #define BSP_INIT_BUTTONS (1 << 1) ◦
功能:表示在初始化时启用按键。
2. 引脚掩码和端口宏
• #define PIN_MASK(_pin) (1u << (uint32_t)((_pin) & (~P0_PIN_NUM))) ◦
功能:根据传入的引脚编号 _pin 生成对应的引脚掩码,用于后续对引脚的操作。
• #define PIN_PORT(_pin) (((_pin) >= P0_PIN_NUM) ? NRF_P1 : NRF_GPIO) ◦
功能:依据传入的引脚编号 _pin 判断该引脚所属的端口,若引脚编号大于等于 P0_PIN_NUM 则属于 NRF_P1 端口,否则属于 NRF_GPIO 端口。
3. LED 和按键掩码宏
• #define LEDS_MASK (BSP_LED_0_MASK | BSP_LED_1_MASK | ... | BSP_LED_7_MASK) ◦ 功能:将所有 LED 的掩码进行按位或操作,得到所有 LED 的总掩码,用于对所有 LED 进行统一操作。
• #define BUTTONS_MASK (BSP_BUTTON_0_MASK | BSP_BUTTON_1_MASK | ... | BSP_BUTTON_7_MASK) ◦
功能:将所有按键的掩码进行按位或操作,得到所有按键的总掩码,用于对所有按键进行统一操作。
4. LED 控制宏
• #define LEDS_OFF(leds_mask) ◦
功能:熄灭由 leds_mask 指定的 LED。此宏仅支持 P0 端口,若 LED 位于其他端口则不适用。
• #define LEDS_ON(leds_mask) ◦
功能:点亮由 leds_mask 指定的 LED。此宏仅支持 P0 端口,若 LED 位于其他端口则不适用。
• #define LED_IS_ON(leds_mask) ◦
功能:判断由 leds_mask 指定的 LED 是否点亮。此宏仅支持 P0 端口,若 LED 位于其他端口则不适用。
• #define LEDS_INVERT(leds_mask) ◦
功能:反转由 leds_mask 指定的 LED 的状态。此宏仅支持 P0 端口,若 LED 位于其他端口则不适用。
• #define LEDS_CONFIGURE(leds_mask) ◦
功能:将由 leds_mask 指定的引脚配置为输出模式,用于控制 LED。此宏仅支持 P0 端口,若 LED 位于其他端口则不适用。
除了上述函数,BOARDS_H中还定义了哪些有用的功能?
除了前面提到的函数,BOARDS_H 头文件中还定义了很多其他有用的功能,主要通过宏定义和条件编译来实现,下面为你详细介绍:
1. 开发板特定头文件的包含
#if defined(BOARD_NRF6310)
#include "nrf6310.h"
#elif defined(BOARD_PCA10000)
#include "pca10000.h"
# ... 其他类似条件编译
#else
#error "Board is not defined"
#endif
• 功能:根据不同的 BOARD_* 宏定义,包含相应开发板的特定头文件。若未定义任何已知的开发板宏,会产生编译错误,提示用户需要定义开发板类型。这使得代码能够适配不同的硬件开发板,增强了代码的可移植性。
2. 扩展板头文件的包含 c #if defined (SHIELD_BSP_INC)
#include STRINGIFY(SHIELD_BSP_INC.h)
#endif
• 功能:如果定义了 SHIELD_BSP_INC 宏,就会包含对应的扩展板头文件。这为开发板添加扩展功能提供了便利,用户可以根据需要启用不同的扩展板。
3. 开发板初始化标志宏定义 c #define BSP_INIT_NONE 0
#define BSP_INIT_LEDS (1 << 0)
#define BSP_INIT_BUTTONS (1 << 1)
• 功能:这些宏用于表示开发板初始化时的不同标志。BSP_INIT_NONE 表示不初始化 LED 和按键;BSP_INIT_LEDS 表示初始化时启用 LED;BSP_INIT_BUTTONS 表示初始化时启用按键。可以通过位运算组合这些标志,灵活控制开发板的初始化过程。
4. LED 和按键编号宏定义 c #define BSP_BOARD_LED_0 0
#define BSP_BOARD_LED_1 1
# ... 其他 LED 编号宏
#define BSP_BOARD_BUTTON_0 0
#define BSP_BOARD_BUTTON_1 1
# ... 其他按键编号宏
• 功能:为开发板上的 LED 和按键定义了统一的编号,从 0 开始计数。这些编号可用于后续的 LED 和按键操作函数,提高了代码的可读性和可维护性。
5. 引脚掩码和端口宏定义 c #define PIN_MASK(_pin) (1u << (uint32_t)((_pin) & (~P0_PIN_NUM)))
#define PIN_PORT(_pin) (((_pin) >= P0_PIN_NUM) ? NRF_P1 : NRF_GPIO)
• PIN_MASK(_pin):根据传入的引脚编号 _pin 生成对应的引脚掩码。引脚掩码可用于位操作,方便对特定引脚进行控制。 • PIN_PORT(_pin):根据引脚编号判断引脚所属的端口。如果引脚编号大于等于 P0_PIN_NUM,则认为该引脚属于 NRF_P1 端口,否则属于 NRF_GPIO 端口。
6. 每个 LED 和按键的掩码和端口定义 c #ifdef BSP_LED_0
#define BSP_LED_0_MASK PIN_MASK(BSP_LED_0)
#define BSP_LED_0_PORT PIN_PORT(BSP_LED_0)
#else
#define BSP_LED_0_MASK 0
#define BSP_LED_0_PORT 0
#endif
# ... 其他 LED 类似
#ifdef BSP_BUTTON_0
#define BSP_BUTTON_0_MASK (1<<BSP_BUTTON_0)
#else
#define BSP_BUTTON_0_MASK 0
#endif
# ... 其他按键类似
• 功能:对于每个 LED 和按键,如果对应的宏(如 BSP_LED_0、BSP_BUTTON_0)被定义,则使用 PIN_MASK 和 PIN_PORT 宏生成对应的掩码和端口;否则,将掩码和端口都定义为 0。这为每个 LED 和按键提供了独立的掩码和端口信息,方便对单个元件进行操作。
7. 所有 LED 和按键的总掩码宏定义 c #define LEDS_MASK (BSP_LED_0_MASK | BSP_LED_1_MASK | ... | BSP_LED_7_MASK)
#define BUTTONS_MASK (BSP_BUTTON_0_MASK | BSP_BUTTON_1_MASK | ... | BSP_BUTTON_7_MASK)
• 功能:将所有 LED 和按键的掩码进行按位或操作,得到所有 LED 和按键的总掩码。这些总掩码可用于对所有 LED 或按键进行统一操作,例如同时点亮所有 LED 或检测所有按键的状态。
8. LED 控制宏定义 c #define LEDS_OFF(leds_mask) ...
#define LEDS_ON(leds_mask) ...
#define LED_IS_ON(leds_mask) ...
#define LEDS_INVERT(leds_mask) ...
#define LEDS_CONFIGURE(leds_mask) ...
• LEDS_OFF(leds_mask):熄灭由 leds_mask 指定的 LED。 • LEDS_ON(leds_mask):点亮由 leds_mask 指定的 LED。 • LED_IS_ON(leds_mask):判断由 leds_mask 指定的 LED 是否点亮。 • LEDS_INVERT(leds_mask):反转由 leds_mask 指定的 LED 的状态。 • LEDS_CONFIGURE(leds_mask):将由 leds_mask 指定的引脚配置为输出模式,用于控制 LED。 这些宏提供了便捷的方式来控制 LED 的状态,并且使用掩码进行操作,使得可以同时控制多个 LED。需要注意的是,这些宏仅支持 P0 端口,如果 LED 位于其他端口,则不适用。
相关文章:
8、nRF52xx蓝牙学习(boards.h文件学习)
boards.h文件的代码如下: #ifndef BOARDS_H #define BOARDS_H#include "nrf_gpio.h" #include "nordic_common.h"#if defined(BOARD_NRF6310)#include "nrf6310.h" #elif defined(BOARD_PCA10000)#include "pca10000.h" #…...
辛格迪客户案例 | 河南宏途食品实施电子合约系统(eSign)
01 河南宏途食品有限公司:食品行业的数字化践行者 河南宏途食品有限公司(以下简称“宏途食品”)作为国内食品行业的创新企业,专注于各类食品的研发、生产和销售。公司秉承“质量为先、创新驱动、服务至上”的核心价值观ÿ…...
webrtc-stats
1. RTP 相关统计 1.1 inbound-rtp (接收端统计) 接收到的 RTP 流统计信息,包含以下关键指标: bytesReceived: 接收到的字节总数packetsReceived: 接收到的数据包总数packetsLost: 丢失的数据包数量jitter: 数据包到达时间的抖动(毫秒&…...
【LangChain框架组成】 LangChain 技术栈的模块化架构解析
目录 整体架构概述 整体架构层级划分 模块详细解析 1. 部署与服务层(LangServe & Deployments) 2. 应用模板层(Templates & Committee Architectures) 3. 核心功能层(LangChain) 4. 社区扩展…...
RNN、LSTM、GRU汇总
RNN、LSTM、GRU汇总 0、论文汇总1.RNN论文2、LSTM论文3、GRU4、其他汇总 1、发展史2、配置和架构1.配置2.架构 3、基本结构1.神经元2.RNN1. **RNN和前馈网络区别:**2. 计算公式:3. **梯度消失:**4. **RNN类型**:(查看发展史)5. **…...
用TypeScript和got库编写爬虫程序指南
用TypeScript和got库写一个爬虫程序。首先,我得确认他们对TypeScript和Node.js的基础了解,可能他们已经有了一些JS的经验,但不确定。接下来,需要明确爬虫的目标,比如要爬取的网站、需要的数据类型以及处理方式。 首先…...
使用 Spring Boot 快速构建企业微信 JS-SDK 权限签名后端服务
使用 Spring Boot 快速构建企业微信 JS-SDK 权限签名后端服务 本篇文章将介绍如何使用 Spring Boot 快速构建一个用于支持企业微信 JS-SDK 权限校验的后端接口,并提供一个简单的 HTML 页面进行功能测试。适用于需要在企业微信网页端使用扫一扫、定位、录音等接口的…...
【软考-架构】13.2、软件层次风格
✨资料&文章更新✨ GitHub地址:https://github.com/tyronczt/system_architect 文章目录 2、层次架构风格两层C/S架构三层C/S架构三层B/S架构富互联网应用RIAMVC架构MVP架构MVVM架构 ✨3、面向服务的架构风格SOASOA中应用的关键技术WEB Service企业服务总线ESB …...
Java 进阶-全面解析
目录 异常处理 集合框架 List 集合 Set 集合 Map 集合 文件与字符集 IO 流 多线程 通过继承Thread类创建线程 通过实现Runnable接口创建线程 线程同步示例 线程通信示例 网络编程 Java 高级技术 反射机制 动态代理 注解 异常处理 在 Java …...
mongodb 创建keyfile
在 MongoDB 中,keyFile 是用于副本集成员间内部认证的密钥文件。它是一个包含随机字符串的文件,所有副本集成员必须使用相同的 keyFile 进行通信。以下是创建和配置 keyFile 的详细步骤。 创建 KeyFile 的步骤 1. 生成随机字符串 使用以下命令生成一个…...
工业4.0时代,RK3562工控机为何成为智慧工位首选?
在制造业数字化转型的浪潮中,智慧车间已成为提升生产效率、降低运营成本的关键战场。作为智慧车间的"神经末梢",工位机的智能化程度直接影响着整个生产线的运行效率。RK3562工控机凭借其强大的计算性能、稳定的运行表现和丰富的接口配置&#…...
WPF 资源加载问题:真是 XAML 的锅吗?
你的观察很敏锐!确实,在 WPF 项目中,.cs 文件主要负责逻辑实现,而资源加载的问题通常跟 XAML(以及它背后的 .csproj 配置)关系更大。我会围绕这个观点,用 CSDN 博客风格详细解释一下 .cs、XAML …...
5. 深度剖析:Spring AI项目架构与分层体系全解读
1、前言 前面我们已经可以通过简单的方式集成Spring AI进行快速开发了。授人以鱼不如授人以渔,我们还是需要了解Spring AI的项目结构,以及他的一些核心概念。 2、项目结构 我们将Spring AI代码直接fork到我们自己的仓库中。fork的目的是方便我们为了学…...
2025最新数字化转型国家标准《数字化转型管理参考架构》 正式发布
当前,数字化转型是数字时代企业生存和发展的必答题,其根本任务是价值体系优化、创新和重构。数字生产力的飞速发展不仅引发了生产方式的转变,也深刻改变了企业的业务体系和价值模式。 为进一步引导企业明确数字化转型的主要任务和关键着力点…...
蓝桥杯备赛 Day 20 树基础
![[树的基础概念.png]] 树的遍历 二叉树遍历分类 DFS前序遍历 根节点-左儿子-右儿子 DFS中序遍历 左儿子-根节点-右儿子 DFS后序遍历 左儿子-右儿子-根节点 BFS层序遍历![[树的遍历.png]] 代码: #include <bits/stdc.h>using namespace std; const int N20; i…...
清晰易懂的Jfrog Artifactory 安装与核心使用教程
JFrog Artifactory 是企业级二进制仓库管理工具,支持 Maven、Docker、npm 等 30 包格式。本教程将手把手教你完成 安装、配置、核心操作,并指出企业级部署的避坑要点,助你快速搭建私有仓库! 一、安装 JFrog Artifactory࿰…...
苍穹外卖总结
苍穹外卖学习知识点 整体概括: 学到目前(day10),总体最核心的部分就是CURD各种数据,因为一些接口,前端页面都已经设计好,在实际开发中也应该是这样,重点是在每个不同的业务板块区别出细微不同的业务逻辑 Swagger注解 swagger是一种自动生成接口文档的插件 使用注解,就可以…...
python学智能算法(九)|决策树深入理解
【1】引言 前序学习进程中,初步理解了决策树的各个组成部分,此时将对决策树做整体解读,以期实现深入理解。 各个部分的解读文章链接为: python学智能算法(八)|决策树-CSDN博客 【2】代码 【2.1】完整代…...
HTTP代理:内容分发战场上的「隐形指挥官」
目录 一、技术本质:流量博弈中的「规则改写者」 二、战略价值:内容分发的「四维升级」 三、实战案例:代理技术的「降维打击」 四、未来进化:代理技术的「认知升级」 五、结语:代理技术的「战略觉醒」 在数字内容爆…...
学习笔记(C++篇)--- Day2
1.类的定义 1.1 类的格式 ①class为类的关键字 ②在类的内容中还可以写函数,具体格式请看示例。 ③为了区分成员变量,一般习惯上成员变量会加一个特殊标识(如成员变量前面或者后面加_ 或者 m开头,注意C中这个并不是强制的&#x…...
下载firefox.tar.xz后如何将其加入到Gnome启动器
起因:近期(2025-04-07)发现firefox公布了130.0 版本,可以对pdf文档进行签名了,想试一下,所以卸载了我的Debian12上的firefox-esr,直接下载了新版本的tar.xz 包。 经过一番摸索,实现了将其加入Gn…...
VSCode英文翻译插件:变量命名、翻单词、翻句子
目录 【var-translate】 【Google Translate】 【code-translator】 【其他插件】 【var-translate】 非常推荐,可以提供小驼峰、大驼峰、下划线、中划线、常量等翻译,Windows下快捷键为Ctrl Shift v 可以整句英文翻译,并且支持多个免费…...
快速高效的MCP Severs
通用AI Agent的瓶颈 最近一直在用MCP协议开发通用智能体。 虽然大模型本身请求比较慢,但是还可以接受。 而最让人沮丧的是,工具效率也不高 比如社区的filesystem,每次只能创建一个目录,生成文件时,如果目录不存在&…...
原子化 CSS 的常见实现框架
原子化 CSS 是一种 CSS 架构方法,其核心思想是将样式拆分为最小粒度的单一功能类,每个类仅对应一个具体的样式属性(如颜色、边距、字体大小等),通过组合这些类来构建复杂的界面。这种方式强调代码复用性、维护性和灵活…...
技术速递|使用 GitHub Copilot Agent Mode 进行编程
作者:卢建晖 - 微软高级云技术布道师 翻译/排版:Alan Wang GitHub Copilot 持续发展,从最初的代码补全、生成、优化功能,到通过对话交互提升 AI 代码质量的 GitHub Copilot Chat,再到能够基于项目中多个文件的关联进行…...
Linux系统(Ubuntu和树莓派)的远程操作练习
目录 实验准备一、Ubuntu 下的远程操作二、树莓派下的远程操作三、思考 实验准备 1.双方应保证处于同一个局域网内 2.关闭防火墙 (否则别人将不能 ping 通自己,具体说明请参考:windows-关闭防火墙) 3.配置虚拟机 a.网桥模式配置 查询…...
电脑屏保壁纸怎么设置 桌面壁纸设置方法详解
电脑桌面壁纸作为我们每天面对的第一视觉元素,不仅能够彰显个人品味,还能营造舒适的工作或娱乐氛围。电脑桌面壁纸怎么设置呢?下面本文将为大家介绍Windows和macOS两大主流操作系统中设置电脑桌面壁纸的方法,帮助大家快速设置个性…...
为什么选择Redis?解析核心使用场景与性能优化技巧
解析核心使用场景与性能优化技巧 redis只能能操作字符串,要把Java对象存入redis非关系型数据库,需要用序列化变成字符串,再反序列化成Java对象 not only sql NoSQL非关系型数据库:缓存数据库,只能读取数据࿰…...
Docker中Redis修改密码失效
docker容器中,我们通过docker run命令运行某一容器 这里,我们通过以下命令来进行运行【注意,这里有两个关键点:-d 和--requirepass】 docker run \ --restartalways \ --log-opt max-size100m \ --log-opt max-file2 \ -p 6379:6…...
质数质数筛
1.试除法判定质数–O(sqrt(N)) bool is_prime(int x) {if (x < 2) return false;for (int i 2; i < x / i; i )if (x % i 0)return false;return true; }2.试除法分解质因数–O(logN)~O(sqrt(N)) void divide(int x) {for (int i 2; i < x / i; i )if (x % i …...
VGA接口设计
1.VGA简介 VGA(Video Graphics Array)视频图形阵列接口是一种模拟信号视频传输标准,用于连接计算机主机和显示设备,如显示器、投影仪等。 VGA接口能够传输红、绿、蓝三原色的模拟信号以及同步信号(数字信号),实现计算机图形和视频信号的输出和显示。 尽管数字化显示接口…...
clickhouse注入手法总结
clickhouse 遇到一题clickhouse注入相关的,没有见过,于是来学习clickhouse的使用,并总结相关注入手法。 环境搭建 直接在docker运行 docker pull clickhouse/clickhouse-server docker run -d --name some-clickhouse-server --ulimit n…...
VsCode保存时删除无用的引用
打开设置文件 教程:打开VsCode设置设置里添加 {"editor.codeActionsOnSave": {"source.organizeImports": false, // 禁用默认的整理导入"source.removeUnusedImports": true // 仅删除未使用的导入} }...
轻松Linux-4.进程概念
屋漏偏逢连夜雨,今天就学Linux 话不多说,展示军火 1.认识冯诺依曼体系 冯诺依曼体系其实并不是什么稀罕的东西,我们生活中的笔记本、服务器、计算机等等大多都遵守冯诺依曼体系 非常经典的一张图 我们所认识的计算机,是由一个个…...
畅游Diffusion数字人(21):基于Wan2.1的音频驱动数字人FantasyTalking
畅游Diffusion数字人(0):专栏文章导航 前言:AI数字人是目前视觉AIGC最有希望大规模落地的场景之一。现阶段的商业工具,如字节的OminiHuman-1(即梦大师版)、快手的可灵对口型,虽然效果不错,但是收费昂贵。而开源解决方案…...
CentOS禁用nouveau驱动
1、验证 nouveau 是否在运行 lsmod | grep nouveau如果命令返回结果,说明 nouveau 驱动正在运行。 2、编辑黑名单文件 通过编辑黑名单配置文件来禁用 nouveau 驱动,这样在系统启动时不会加载它。 vi /etc/modprobe.d/blacklist-nouveau.conf修改以下…...
《Operating System Concepts》阅读笔记:p587-p596
《Operating System Concepts》学习第 52 天,p587-p596 总结,总计 10 页。 一、技术总结 1.Recovery (1)consistency checking consistency checking 工具:fsck。 (2)log-structure file system (3)WAFL file system 2.Veritas (1)Ve…...
k8s 1.24.17版本部署(使用Flannel插件)
1.k8s集群环境准备 推荐阅读: https://kubernetes.io/zh/docs/setup/production-environment/tools/kubeadm/install-kubeadm/ 1.1 环境准备 环境准备:硬件配置: 2core 4GB磁盘: 50GB操作系统: Ubuntu 22.04.04 LTSIP和主机名:10.0.0.231 master23110.0.0.232 worker23210.0…...
通信协议详解(十):PSI5 —— 汽车安全传感器的“抗干扰狙击手”
一、PSI5是什么? 一句话秒懂 PSI5就像传感器界的“防弹信使”:在汽车安全系统(如气囊)中,用两根线同时完成供电数据传输,即便车祸时线路受损,仍能确保关键信号准确送达! 基础概念…...
Kafka生产者和消费者:数据管道的核心引擎与智能终端
在分布式系统中,数据的高效流动如同人体的血液循环,而Kafka的生产者(Producer)与消费者(Consumer)正是驱动这一循环的核心组件。它们不仅是Kafka客户端的基本形态,更是构建实时数据生态的基石。…...
特权FPGA之按键消抖
完整代码如下所示: timescale 1ns / 1ps// Company: // Engineer: 特权 // // Create Date: // Design Name: // Module Name: // Project Name: // Target Device: // Tool versions: // Description: // // Dependencies: // // Revision: // …...
实时比分更新系统的搭建
搭建一个实时比分更新系统需要考虑多个技术环节,以下是一个完整的实现方案: 一、系统架构 1.数据获取层 比分数据API接入(如熊猫比分、API-Football等) 网络爬虫(作为备用数据源) 2.数据处理层 …...
【Linux】线程的概念与控制
目录 1. 整体学习思维导图 2. 线程的概念 2.1 基础概念 2.2 Linux下的线程 初步理解: 2. 分页式存储 3.1 页表 3.1.1 页框/页 3.1.2 页表机制 3.1.3 从虚拟地址到物理地址的转换 总结: 3.2 TLB快表 3.3 缺页异常(Page Fault&am…...
K8s 老鸟的配置管理避雷手册
Yining, China 引言 对于这种案例,你们的处理思路是怎么样的呢,是否真正的处理过,如果遇到,你们应该怎么处理。 最后有相关的学习群,有兴趣可以加入。 开始 一、血泪教训:环境变量引发的真实灾难 1.1 …...
飞速(FS)解决方案验证实验室搬迁升级,赋能客户技术服务
飞速(FS)解决方案验证实验室近日顺利完成搬迁升级,标志着飞速(FS)在解决方案可行性验证、质量保障以及定制化需求支持方面迈上新台阶,进一步提升了产品竞争力和客户信任度。 全新升级的实验室定位为技术验证…...
柔性关节双臂机器人奇异摄动鲁棒自适应PD控制
1 双臂机器人动力学模型 对于一个具有多个关节的机器人来说,机器人端动力学子方程及关节驱动电机端动力学子方程为: 以上为推导过程,MATLAB程序已完成,若需要可找我。...
遵循IEC62304YY/T0664:确保医疗器械软件生命周期合规性
一、EC 62304与YY/T 0664的核心定位与关系 IEC 62304(IEC 62304)是国际通用的医疗器械软件生命周期管理标准,适用于所有包含软件的医疗器械(如嵌入式软件、独立软件、移动应用等),其核心目标是确保软件的安…...
Kafka和RocketMQ相比有什么区别?那个更好用?
Kafka和RocketMQ相比有什么区别?那个更好用? Kafka 和 RocketMQ 都是广泛使用的消息队列系统,它们有很多相似之处,但也有一些关键的区别。具体选择哪个更好用,要根据你的应用场景和需求来决定。以下是它们之间的主要区别: 1. …...
空对象模式(Null Object Pattern)在C#中的实现详解
一 、什么是空对象模式 空对象模模是靠”空对孔象式是书丯一种引施丼文行为,行凌,凌万成,个默疤"空象象象象来飞䛿引用用用用电从延盈盈甘仙丿引用用用职从延务在仅代砷易行行 」这种燕式亲如要目的片片 也说媚平父如如 核心思烟 定义一个人 派一个 � 创建…...
【Windows】Win2008服务器SQL服务监控重启脚本
以下是一个用于监控并自动重启 SQL Server 服务的批处理脚本,适用于 Windows Server 2008 和 SQL Server 2012(默认实例): echo off setlocal enabledelayedexpansion:: 配置参数 set SERVICE_NAMEMSSQLSERVER set LOG_FILEC:\SQ…...