news 2026/9/30 10:42:59

STM3流水灯综合实验

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
STM3流水灯综合实验

实验一 寄存器方式实现四路流水灯

实验名称

STM32F103C8T6寄存器编程实现四路LED流水灯

一、实验目的

1. 熟悉STM32F103最小系统板硬件,理解GPIO端口功能与APB2外设时钟作用。

​

2. 掌握直接操作寄存器配置GPIO,理解CRL、CRH、BSRR寄存器功能,学会位操作。

​

3. 使用PA0、PB0、PB1外接LED,结合板载PC13 LED,实现四路流水灯,间隔约1s轮流点亮。

​

4. 掌握Keil‑MDK工程创建、编译、ST‑Link下载调试流程。

​

5. 理解 volatile 关键字作用;练习将工程上传Gitee,撰写实验博客。

二、实验器材

1. STM32F103C8T6最小系统板

​

2. ST‑Link仿真下载器

​

3. 面包板,红、绿、蓝LED各1只,220Ω限流电阻,杜邦线若干

​

4. 笔记本电脑,Keil uVision5

三、实验原理

GPIO外设使用前必须开启对应总线时钟,GPIOA、GPIOB、GPIOC挂载在APB2总线,由 RCC->APB2ENR 控制时钟。

- GPIOx‑>CRL :管理引脚0‑7,配置模式与输出速度,PA0、PB0、PB1由CRL控制。

​

- GPIOx‑>CRH :管理引脚8‑15,PC13使用CRH寄存器。

​

- BSRR 置位复位寄存器:低16位写1引脚输出高电平;高16位写1引脚输出低电平,无读改写风险。

硬件电路:

外接LED:PA0、PB0、PB1串联220Ω电阻接LED阳极,阴极接GND,高电平点亮。

板载PC13 LED:硬件反向驱动,低电平点亮,高电平熄灭。

延时采用双层for空循环软件延时,会受编译器优化影响,延时并不严格准确。

表格

寄存器 基地址 偏移地址

RCC 0x40021000 0x18(APB2ENR)

GPIOA 0x40010800 0x00(CRL)、0x10(BSRR)

GPIOB 0x40010C00 0x00(CRL)、0x10(BSRR)

GPIOC 0x40011000 0x04(CRH)、0x10(BSRR)

四、程序设计思路

1. 使用寄存器指针访问硬件寄存器, volatile 防止编译器优化读写。

​

2. 开启GPIOA、GPIOB、GPIOC的APB2外设时钟。

​

3. CRL、CRH对应位先清零再赋值,配置PA0、PB0、PB1、PC13为50MHz推挽输出。

​

4. 初始化所有LED为熄灭状态。

​

5. 编写软件延时函数。

​

6. while死循环,使用BSRR寄存器依次点亮单路LED,其余熄灭,延时后切换,流水顺序PA0→PB0→PB1→PC13循环。

五、实验代码

while(1)

#include "stm32f10x.h"

//软件粗略延时,volatile防止编译器优化

void Soft_Delay(uint32_t t)

{

volatile uint32_t i,j;

for(i = 0; i < t; i++)

{

for(j = 0; j < 7200; j++);

}

}

int main(void)

{

//开启GPIOA GPIOB GPIOC时钟

RCC->APB2ENR |= (1U << 2) | (1U << 3) | (1U << 4);

//PA0 50MHz推挽输出

GPIOA->CRL &= ~(0x0FU << 0);

GPIOA->CRL |= (0x03U << 0);

//PB0 50MHz推挽输出

GPIOB->CRL &= ~(0x0FU << 0);

GPIOB->CRL |= (0x03U << 0);

//PB1 50MHz推挽输出

GPIOB->CRL &= ~(0x0FU << 4);

GPIOB->CRL |= (0x03U << 4);

//PC13,CRH寄存器,50MHz推挽输出

GPIOC->CRH &= ~(0x0FU << 20);

GPIOC->CRH |= (0x03U << 20);

//全部LED初始熄灭

GPIOA->BSRR = (1U << 0) << 16;

GPIOB->BSRR = ((1U << 0)|(1U << 1)) << 16;

GPIOC->BSRR = (1U << 13);

while(1)

{

//点亮PA0

GPIOA->BSRR = 1U << 0;

GPIOB->BSRR = ((1U<<0)|(1U<<1)) <<16;

GPIOC->BSRR = 1U <<13;

Soft_Delay(1000);

//点亮PB0

GPIOA->BSRR = (1U<<0)<<16;

GPIOB->BSRR = 1U << 0;

GPIOB->BSRR = (1U<<1)<<16;

GPIOC->BSRR = 1U <<13;

Soft_Delay(1000);

//点亮PB1

GPIOA->BSRR = (1U<<0)<<16;

GPIOB->BSRR = (1U<<0)<<16;

GPIOB->BSRR = 1U << 1;

GPIOC->BSRR = 1U <<13;

Soft_Delay(1000);

//点亮PC13板载LED

GPIOA->BSRR = (1U<<0)<<16;

GPIOB->BSRR = ((1U<<0)|(1U<<1)) <<16;

GPIOC->BSRR = (1U << 13) <<16;

Soft_Delay(1000);

}

}

六、实验步骤

1. 硬件接线:PA0、PB0、PB1串联220Ω电阻接LED,LED阴极接GND;ST‑Link连接SWDIO、SWCLK、GND、3.3V。

​

2. Keil新建工程,选择芯片STM32F103C8,添加启动文件,新建main.c粘贴代码。

​

3. 调试器选择ST‑Link,设置下载后自动复位运行。

​

4. 编译工程,无报错后下载程序。

​

5. 上电观察LED流水现象,截图Keil界面、硬件实物。

​

6. 将工程Git上传Gitee仓库。

七、实验现象

上电后LED按照PA0→PB0→PB1→PC13顺序依次点亮,同一时刻只亮一盏灯,每盏灯维持约1s循环流水。软件延时存在误差,间隔不是严格1秒。

八、遇到的问题与解决

1. 没有加 volatile 修饰延时变量,编译器直接优化掉延时,灯切换飞快。添加volatile后延时正常。

​

2. 一开始用ODR寄存器,出现引脚互相干扰,改用BSRR置位复位寄存器解决。

​

3. PC13错误操作CRL寄存器,板载LED无反应,修改操作CRH寄存器后正常。

​

4. ST‑Link下载失败,是SWCLK杜邦线接触不良,重新插紧即可下载。

九、实验总结

寄存器编程直接操作硬件地址,可以深入理解GPIO底层工作原理,但是要记住寄存器地址与每一位功能,写代码比较繁琐。

必须开启外设时钟GPIO才可以工作;PC13属于CRH寄存器;BSRR比ODR更加安全。软件延时只能粗略等待,不能用于高精度时序。

实验二 标准外设库实现四路流水灯

实验名称

STM32F103标准外设库流水灯实验

一、实验目的

1. 掌握Keil中搭建标准外设库工程,添加库文件,配置头文件路径与编译宏。

​

2. 学会使用标准库RCC、GPIO函数,理解库对寄存器的封装。

​

3. 实现PA0、PB0、PB1、PC13四路流水灯,间隔约1s轮流点亮。

​

4. 使用Keil逻辑分析仪仿真,观察引脚波形,分析软件延时误差。

​

5. 工程上传Gitee,记录实验过程。

二、实验器材

1. STM32F103C8T6最小系统板

​

2. ST‑Link仿真下载器

​

3. 面包板,LED×3,220Ω电阻,杜邦线

​

4. 电脑,Keil uVision5,STM32F10x标准外设库

三、实验原理

标准外设库将底层寄存器操作封装成C函数,不用手动操作寄存器地址。

- RCC_APB2PeriphClockCmd() :使能GPIO端口时钟。

​

- GPIO_InitTypeDef 结构体:配置引脚模式、输出速度。

​

- GPIO_SetBits() 引脚输出高电平; GPIO_ResetBits() 输出低电平。

硬件接线和实验一完全一致:外接LED高电平点亮,PC13板载LED低电平点亮。延时依旧使用软件双层循环,定时精度有限。Keil逻辑分析仪可以仿真观察引脚电平变化,测量实际延时。

四、程序设计思路

1. 工程导入标准库 stm32f10x_rcc.c 、 stm32f10x_gpio.c ,配置编译宏 USE_STDPERIPH_DRIVER 。

​

2. 编写GPIO初始化函数,开启GPIOA/GPIOB/GPIOC时钟,配置引脚为50MHz推挽输出。

​

3. 编写软件延时函数。

​

4. main死循环,依次点亮PA0→PB0→PB1→PC13,其余熄灭,延时循环。

五、实验代码

#include "stm32f10x.h"

void Delay_ms(uint32_t ms)

{

uint32_t i,j;

for(i = 0; i < ms; i++)

for(j = 0; j < 7200; j++);

}

void LED_Init(void)

{

GPIO_InitTypeDef GPIO_InitStruct;

RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_GPIOB,ENABLE);

//PA0??

GPIO_InitStruct.GPIO_Pin = GPIO_Pin_0;

GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP;

GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;

GPIO_Init(GPIOA,&GPIO_InitStruct);

//PB0 PB1??

GPIO_InitStruct.GPIO_Pin = GPIO_Pin_0|GPIO_Pin_1;

GPIO_Init(GPIOB,&GPIO_InitStruct);

GPIO_SetBits(GPIOA,GPIO_Pin_0);

GPIO_SetBits(GPIOB,GPIO_Pin_0|GPIO_Pin_1);

}

六、实验步骤

1. 硬件保持实验一接线不变,ST‑Link连接开发板。

​

2. 新建Keil工程,复制标准库inc、src文件夹到工程目录。

​

3. 新建工程分组User、StdPeriph_Driver、Startup;添加main.c、rcc.c、gpio.c、启动文件。

​

4. 魔术棒配置头文件路径,添加宏定义 USE_STDPERIPH_DRIVER,STM32F10X_MD 。

​

5. 调试器选择ST‑Link,编译下载程序。

​

6. 打开Keil软件仿真,调出逻辑分析仪,添加PA0、PB0、PB1、PC13引脚,观察波形。

​

7. 记录现象,截图,工程上传Gitee。

七、实验现象

下载完成,LED按PA0→PB0→PB1→PC13顺序轮流点亮,每个灯约1秒切换。逻辑分析仪观察引脚周期性翻转,软件延时实际时间和理论1秒存在误差。

八、遇到的问题与解决

1. 编译报大量头文件找不到,没有配置inc头文件路径,添加路径后解决。

​

2. 忘记添加 USE_STDPERIPH_DRIVER 宏,库函数全部未定义报错。

​

3. PC13电平逻辑搞反,调用 GPIO_SetBits() 点亮板载LED,灯反而熄灭,修改为 GPIO_ResetBits() 。

​

4. 逻辑分析仪看不到波形,没有切换到软件仿真模式,修改工程仿真设置。

​

5. 把全部库文件加入工程,编译速度很慢,只添加rcc.c与gpio.c即可。

九、实验总结

标准外设库对寄存器进行封装,不用记忆寄存器地址,代码可读性高。使用结构体配置GPIO很方便,但同样必须开启外设时钟。

仿真波形直观看到软件延时精度不足,如果需要精准定时,需要使用定时器外设。

实验三 HAL库外部中断:按键控制流水灯暂停/继续

实验名称

HAL库+外部中断实验,按键控制四路流水灯暂停恢复

一、实验目的

1. 熟悉STM32CubeMX图形化配置,生成HAL库工程。

​

2. 掌握外部中断配置,理解中断回调函数运行机制。

​

3. 在四路流水灯基础上,按键触发外部中断,实现流水灯运行与暂停切换。

​

4. 理解中断编程规范:回调函数只修改标志位,耗时代码放在主循环。

​

5. 工程上传Gitee,整理实验记录。

二、实验器材

1. STM32F103C8T6最小系统板

​

2. ST‑Link下载器

​

3. 面包板,LED,220Ω电阻,按键,杜邦线

​

4. 电脑,STM32CubeMX,Keil‑MDK

三、实验原理

外部中断EXTI:引脚电平跳变触发中断,CPU暂停主循环,执行中断服务函数,最终调用 HAL_GPIO_EXTI_Callback() 回调函数。

本实验按键接PA0,下降沿触发外部中断;设置全局标志位 run_flag ,中断中翻转标志位。

主循环判断标志位: run_flag=1 执行流水灯; run_flag=0 停止流水,LED保持当前状态。

重要:中断回调函数不能放置延时、循环等耗时代码,仅允许简单变量修改。

LED硬件电路和前面实验保持一致。按键一端接PA0,一端接GND,开启内部上拉。

四、程序设计思路

1. CubeMX配置:系统时钟72MHz;PA0配置外部中断下降沿触发,开启上拉;PA0、PB0、PB1、PC13配置为GPIO输出。

​

2. 生成Keil HAL工程。

​

3. 定义全局标志位 run_flag=1 ,代表流水灯运行。

​

4. 在外部中断回调函数翻转run_flag。

​

5. while主循环判断标志位,标志位为1执行流水灯逻辑,为0不执行。

​

6. 软件延时,下载调试观察现象。

五、核心代码

/* USER CODE BEGIN Header */

/**

******************************************************************************

* @file : main.c

* @brief : Main program body

******************************************************************************

* @attention

*

* Copyright (c) 2026 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"

/* 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 */

uint8_t run_flag = 1; //1=流水灯运行,0=暂停

/* USER CODE END PV */

/* Private function prototypes -----------------------------------------------*/

void SystemClock_Config(void);

static void MX_GPIO_Init(void);

/* USER CODE BEGIN PFP */

/* USER CODE END PFP */

/* Private user code ---------------------------------------------------------*/

/* USER CODE BEGIN 0 */

//外部中断回调函数,PA2触发中断自动进入

void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)

{

if(GPIO_Pin == GPIO_PIN_2)

{

run_flag = !run_flag; //翻转状态:运行 ↔ 暂停

}

}

/* 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();

/* USER CODE BEGIN 2 */

/* USER CODE END 2 */

/* Infinite loop */

/* USER CODE BEGIN WHILE */

while (1)

{

if(run_flag == 1)

{

//PA0亮1秒

HAL_GPIO_WritePin(GPIOA, GPIO_PIN_0, GPIO_PIN_RESET);

HAL_Delay(1000);

HAL_GPIO_WritePin(GPIOA, GPIO_PIN_0, GPIO_PIN_SET);

//PB0亮1秒

HAL_GPIO_WritePin(GPIOB, GPIO_PIN_0, GPIO_PIN_RESET);

HAL_Delay(1000);

HAL_GPIO_WritePin(GPIOB, GPIO_PIN_0, GPIO_PIN_SET);

//PB1亮1秒

HAL_GPIO_WritePin(GPIOB, GPIO_PIN_1, GPIO_PIN_RESET);

HAL_Delay(1000);

HAL_GPIO_WritePin(GPIOB, GPIO_PIN_1, GPIO_PIN_SET);

}

//run_flag=0时,循环空转,流水灯保持暂停

}

/* 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();

}

}

/**

* @brief GPIO Initialization Function

* @param None

* @retval None

*/

static void MX_GPIO_Init(void)

{

GPIO_InitTypeDef GPIO_InitStruct = {0};

/* GPIO Ports Clock Enable */

__HAL_RCC_GPIOC_CLK_ENABLE();

__HAL_RCC_GPIOD_CLK_ENABLE();

__HAL_RCC_GPIOA_CLK_ENABLE();

__HAL_RCC_GPIOB_CLK_ENABLE();

/*Configure GPIO pin Output Level */

HAL_GPIO_WritePin(GPIOA, GPIO_PIN_0, GPIO_PIN_SET);

/*Configure GPIO pin Output Level */

HAL_GPIO_WritePin(GPIOB, GPIO_PIN_0|GPIO_PIN_1, GPIO_PIN_SET);

/*Configure GPIO pin : PA0 */

GPIO_InitStruct.Pin = GPIO_PIN_0;

GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;

GPIO_InitStruct.Pull = GPIO_NOPULL;

GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;

HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

/*Configure GPIO pin : PA2 */

GPIO_InitStruct.Pin = GPIO_PIN_2;

GPIO_InitStruct.Mode = GPIO_MODE_IT_FALLING;

GPIO_InitStruct.Pull = GPIO_PULLUP;

HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

/*Configure GPIO pins : PB0 PB1 */

GPIO_InitStruct.Pin = GPIO_PIN_0|GPIO_PIN_1;

GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;

GPIO_InitStruct.Pull = GPIO_NOPULL;

GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;

HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);

/* EXTI interrupt init*/

HAL_NVIC_SetPriority(EXTI2_IRQn, 0, 0);

HAL_NVIC_EnableIRQ(EXTI2_IRQn);

}

/**

* @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. 保留LED接线;按键接PA0与GND,ST‑Link连接开发板。

​

2. CubeMX选择芯片STM32F103C8T6;配置外部晶振,调试接口Serial Wire。

​

3. PA0设置为 GPIO_EXTI0 下降沿触发,开启上拉;PA0、PB0、PB1、PC13设置输出。时钟树配置72MHz。

​

4. 生成Keil工程。

​

5. 打开工程,替换main.c业务代码,编译。

​

6. ST‑Link下载程序,按下按键观察流水灯暂停与继续效果。

​

7. 记录现象截图,工程上传Gitee。

七、实验现象

八、遇到的问题与解决

1. 按键偶尔多次触发,缺少硬件消抖,后续可以增加软件消抖代码。

​

2. 一开始在中断回调写延时,程序运行异常,老师提醒中断不能放耗时代码,只修改标志位。

​

3. CubeMX没有开启引脚内部上拉,按键电平不稳定,开启上拉配置后按键识别正常。

​

4. 重新生成CubeMX工程把main.c代码覆盖,需要保留用户代码段。

九、实验总结

HAL库配合CubeMX图形配置硬件,不需要手写大量初始化代码,开发效率高。

外部中断不需要CPU轮询查询按键,电平变化立刻响应。中断回调函数要尽量简短,业务逻辑放到主循环处理。

对比寄存器、标准库、HAL三种开发方式,对GPIO、时钟、中断有了更加完整理解。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/30 10:40:58

毕业生实测|2026 国内 AI 论文工具横向盘点,按场景选不踩坑

写在前面 临近毕业&#xff0c;很多人一口气收藏七八个 AI 论文网站&#xff0c;用到最后发现&#xff1a;有的只能翻译外文&#xff0c;有的只会简单润色&#xff0c;想走完开题、文献、写作、绘图、自查、排版、答辩 PPT 整套流程&#xff0c;来回切换账号&#xff0c;文件反…

作者头像 李华
网站建设 2026/9/30 10:40:05

开源阅读APP书源全指南:导入筛选与TTS维护实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/30 10:39:14

EMQX ACL实战:多租户MQTT权限控制、外部授权与排障

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/30 10:36:36

GEO内容工具怎么选?6个维度实测

生成式引擎优化&#xff08;GEO&#xff09;的落地&#xff0c;核心离不开内容工具的支撑。不少运营者在搭建账号矩阵时&#xff0c;会纠结工具选型&#xff1a;有的工具擅长批量撰稿&#xff0c;有的侧重关键词挖掘&#xff0c;还有的主打多平台一键分发。盲目采购不仅浪费预算…

作者头像 李华
网站建设 2026/9/30 10:36:30

卫星互联网安全:Starlink用户链路IP欺骗检测与防御实战

简介&#xff1a;这份PDF面向网络安全研究者、卫星通信从业者及CTF-Misc方向学习者&#xff0c;聚焦Starlink用户链路流量中的IP欺骗防御问题&#xff0c;系统梳理卫星互联网安全威胁与应对思路。资源为单份PDF文档&#xff0c;共4.56MB&#xff0c;支持目录章节跳转与阅读器左…

作者头像 李华
网站建设 2026/9/30 10:36:20

MQTT协议详解:报文结构、QoS语义与Broker选型避坑指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华