当前位置: 首页 > article >正文

【极光 Orbit·STC8AH】04. 深度探索 GPIO 底层逻辑


【极光 Orbit·STC8A&H】04. 深度探索 GPIO 底层逻辑

引言:当代码遇见硬件

上周我看着学生调试的工控产品,他们困惑地盯着自己编写的代码:“老师,这段C语言明明在PC上跑得没问题啊!” ,让我想起自己初学嵌入式时的窘迫——那时我曾用标准C的思维写代码,结果让价值数万的工业控制器冒起了青烟。

这个小插曲恰恰揭示了嵌入式开发的核心矛盾:纯软件思维与硬件物理特性的碰撞。学生们用熟悉的printf()调试习惯,将LED控制写成简单的led = 1;,却忽略了单片机GPIO需要先配置方向寄存器的底层逻辑。这种思维差异,正是本文要探讨的嵌入式编程特殊性。

故此,STC8A 这个专栏停更了一周,专门开设了【编程技巧】,写了一点嵌入式编程的感悟,全是学校里学不到的内容,希望大家喜欢。

纯C与嵌入式C的三大本质区别
  1. 硬件寄存器的直接操作
    纯C代码:int led = 1;(逻辑值)
    嵌入式C:P0 = 0xFF; P0M0 = 0xFF;(需同时配置数据寄存器和模式寄存器)
  2. 时序敏感性
    纯C:delay(1000);(依赖系统时钟)
    嵌入式C:for(volatile uint16_t i=0;i<12000;i++);(精确控制时序)
  3. 资源约束
    纯C:可自由使用动态内存、复杂数据结构
    嵌入式C:需手动管理有限的RAM(如STC8H仅8KB SRAM)

当用标准C的int led_array[8]记录LED状态时,程序在STC8A上频繁崩溃——因为数组占用了宝贵的硬件堆栈空间。这正是本文要深入剖析的GPIO底层逻辑:从寄存器直接操作的"硬件级编程",到官方库函数封装的"开发友好模式",再到结合两者优势的"优化位操作",开发者需要理解不同模式背后的硬件原理。

接下来我们将通过GPIO控制LED的典型案例,对比三种编程模式的实现差异,揭示嵌入式C语言如何通过代码与硬件的"对话",实现从算法到物理世界的精准控制。这个过程就像在数字电路与软件逻辑之间架设桥梁——而这座桥梁的建材,正是本文要展开的底层寄存器配置与优化技巧。

硬件连接

硬件电路图

  • LED连接方式
    将8只LED的阳极分别连接到单片机的GPIO引脚(如P0.0~P0.7),阴极通过限流电阻(如220Ω)接地。
    • 共阳极接法:GPIO输出低电平点亮LED。
    • 共阴极接法:GPIO输出高电平点亮LED。

单片机引脚分配

引脚名称功能说明
P0.0~P0.7GPIO输出控制8只LED的亮灭

编程模式详解

1. 寄存器直接操作模式

步骤说明
  1. 配置GPIO方向:将P0端口的所有引脚设置为推挽输出模式。
  2. 控制LED状态:通过写入P0寄存器的值直接控制LED的亮灭。
关键寄存器
  • P0M0和P0M1:控制P0端口每个引脚的模式。
    • P0M0 = 0xFFP0M1 = 0xFF:设置所有引脚为推挽输出模式。
  • P0:数据寄存器,直接控制引脚的输出电平。
代码示例
#include "stc8h.h"void Delay(uint16_t ms) {while (ms--) {for (volatile uint16_t i = 0; i < 12000; i++);}
}int main() {// 1. 配置P0端口为推挽输出模式P0M0 = 0xFF;  // 低四位控制P0.0~P0.3,高四位控制P0.4~P0.7P0M1 = 0xFF;  // 低四位控制P0.0~P0.3,高四位控制P0.4~P0.7while (1) {// 2. 全部点亮LED(假设共阴极)P0 = 0xFF;  // 输出高电平Delay(500);// 3. 熄灭所有LEDP0 = 0x00;  // 输出低电平Delay(500);}
}
原理分析
  • 优势:直接操作硬件寄存器,执行效率最高,适合对性能要求高的场景。
  • 缺点:代码可读性低,需熟悉寄存器功能。

2. 官方库函数模式

GPIO.C

#### 步骤说明
1. **包含头文件**:引入STC标准库头文件。
2. **初始化GPIO**:通过结构体配置GPIO方向和初始值。
3. **控制LED**:使用库函数切换GPIO电平。
/*---------------------------------------------------------------------*/
/* --- STC MCU Limited ------------------------------------------------*/
/* --- STC 1T Series MCU Demo Programme -------------------------------*/
/* --- Mobile: (86)13922805190 ----------------------------------------*/
/* --- Fax: 86-0513-55012956,55012947,55012969 ------------------------*/
/* --- Tel: 86-0513-55012928,55012929,55012966 ------------------------*/
/* --- Web: www.STCMCU.com --------------------------------------------*/
/* --- Web: www.STCMCUDATA.com  ---------------------------------------*/
/* --- QQ:  800003751 -------------------------------------------------*/
/* 如果要在程序中使用此代码,请在程序中注明使用了STC的资料及程序            */
/*---------------------------------------------------------------------*//***************	功能说明	****************本文件为STC8系列的端口初始化程序,用户几乎可以不修改这个程序.******************************************/#include	"GPIO.h"//========================================================================
// 函数: u8	GPIO_Inilize(u8 GPIO, GPIO_InitTypeDef *GPIOx)
// 描述: 初始化IO口.
// 参数: GPIOx: 结构参数,请参考timer.h里的定义.
// 返回: 成功返回0, 空操作返回1,错误返回2.
// 版本: V1.0, 2012-10-22
//========================================================================
u8	GPIO_Inilize(u8 GPIO, GPIO_InitTypeDef *GPIOx)
{if(GPIO > GPIO_P7)				return 1;	//空操作if(GPIOx->Mode > GPIO_OUT_PP)	return 2;	//错误if(GPIO == GPIO_P0){if(GPIOx->Mode == GPIO_PullUp)		P0M1 &= ~GPIOx->Pin,	P0M0 &= ~GPIOx->Pin;	 //上拉准双向口if(GPIOx->Mode == GPIO_HighZ)		P0M1 |=  GPIOx->Pin,	P0M0 &= ~GPIOx->Pin;	 //浮空输入if(GPIOx->Mode == GPIO_OUT_OD)		P0M1 |=  GPIOx->Pin,	P0M0 |=  GPIOx->Pin;	 //开漏输出if(GPIOx->Mode == GPIO_OUT_PP)		P0M1 &= ~GPIOx->Pin,	P0M0 |=  GPIOx->Pin;	 //推挽输出}if(GPIO == GPIO_P1){if(GPIOx->Mode == GPIO_PullUp)		P1M1 &= ~GPIOx->Pin,	P1M0 &= ~GPIOx->Pin;	 //上拉准双向口if(GPIOx->Mode == GPIO_HighZ)		P1M1 |=  GPIOx->Pin,	P1M0 &= ~GPIOx->Pin;	 //浮空输入if(GPIOx->Mode == GPIO_OUT_OD)		P1M1 |=  GPIOx->Pin,	P1M0 |=  GPIOx->Pin;	 //开漏输出if(GPIOx->Mode == GPIO_OUT_PP)		P1M1 &= ~GPIOx->Pin,	P1M0 |=  GPIOx->Pin;	 //推挽输出}if(GPIO == GPIO_P2){if(GPIOx->Mode == GPIO_PullUp)		P2M1 &= ~GPIOx->Pin,	P2M0 &= ~GPIOx->Pin;	 //上拉准双向口if(GPIOx->Mode == GPIO_HighZ)		P2M1 |=  GPIOx->Pin,	P2M0 &= ~GPIOx->Pin;	 //浮空输入if(GPIOx->Mode == GPIO_OUT_OD)		P2M1 |=  GPIOx->Pin,	P2M0 |=  GPIOx->Pin;	 //开漏输出if(GPIOx->Mode == GPIO_OUT_PP)		P2M1 &= ~GPIOx->Pin,	P2M0 |=  GPIOx->Pin;	 //推挽输出}if(GPIO == GPIO_P3){if(GPIOx->Mode == GPIO_PullUp)		P3M1 &= ~GPIOx->Pin,	P3M0 &= ~GPIOx->Pin;	 //上拉准双向口if(GPIOx->Mode == GPIO_HighZ)		P3M1 |=  GPIOx->Pin,	P3M0 &= ~GPIOx->Pin;	 //浮空输入if(GPIOx->Mode == GPIO_OUT_OD)		P3M1 |=  GPIOx->Pin,	P3M0 |=  GPIOx->Pin;	 //开漏输出if(GPIOx->Mode == GPIO_OUT_PP)		P3M1 &= ~GPIOx->Pin,	P3M0 |=  GPIOx->Pin;	 //推挽输出}if(GPIO == GPIO_P4){if(GPIOx->Mode == GPIO_PullUp)		P4M1 &= ~GPIOx->Pin,	P4M0 &= ~GPIOx->Pin;	 //上拉准双向口if(GPIOx->Mode == GPIO_HighZ)		P4M1 |=  GPIOx->Pin,	P4M0 &= ~GPIOx->Pin;	 //浮空输入if(GPIOx->Mode == GPIO_OUT_OD)		P4M1 |=  GPIOx->Pin,	P4M0 |=  GPIOx->Pin;	 //开漏输出if(GPIOx->Mode == GPIO_OUT_PP)		P4M1 &= ~GPIOx->Pin,	P4M0 |=  GPIOx->Pin;	 //推挽输出}if(GPIO == GPIO_P5){if(GPIOx->Mode == GPIO_PullUp)		P5M1 &= ~GPIOx->Pin,	P5M0 &= ~GPIOx->Pin;	 //上拉准双向口if(GPIOx->Mode == GPIO_HighZ)		P5M1 |=  GPIOx->Pin,	P5M0 &= ~GPIOx->Pin;	 //浮空输入if(GPIOx->Mode == GPIO_OUT_OD)		P5M1 |=  GPIOx->Pin,	P5M0 |=  GPIOx->Pin;	 //开漏输出if(GPIOx->Mode == GPIO_OUT_PP)		P5M1 &= ~GPIOx->Pin,	P5M0 |=  GPIOx->Pin;	 //推挽输出}if(GPIO == GPIO_P6){if(GPIOx->Mode == GPIO_PullUp)		P6M1 &= ~GPIOx->Pin,	P6M0 &= ~GPIOx->Pin;	 //上拉准双向口if(GPIOx->Mode == GPIO_HighZ)		P6M1 |=  GPIOx->Pin,	P6M0 &= ~GPIOx->Pin;	 //浮空输入if(GPIOx->Mode == GPIO_OUT_OD)		P6M1 |=  GPIOx->Pin,	P6M0 |=  GPIOx->Pin;	 //开漏输出if(GPIOx->Mode == GPIO_OUT_PP)		P6M1 &= ~GPIOx->Pin,	P6M0 |=  GPIOx->Pin;	 //推挽输出}if(GPIO == GPIO_P7){if(GPIOx->Mode == GPIO_PullUp)		P7M1 &= ~GPIOx->Pin,	P7M0 &= ~GPIOx->Pin;	 //上拉准双向口if(GPIOx->Mode == GPIO_HighZ)		P7M1 |=  GPIOx->Pin,	P7M0 &= ~GPIOx->Pin;	 //浮空输入if(GPIOx->Mode == GPIO_OUT_OD)		P7M1 |=  GPIOx->Pin,	P7M0 |=  GPIOx->Pin;	 //开漏输出if(GPIOx->Mode == GPIO_OUT_PP)		P7M1 &= ~GPIOx->Pin,	P7M0 |=  GPIOx->Pin;	 //推挽输出}return 0;	//成功
}

GPIO.H

/*---------------------------------------------------------------------*/
/* --- STC MCU Limited ------------------------------------------------*/
/* --- STC 1T Series MCU Demo Programme -------------------------------*/
/* --- Mobile: (86)13922805190 ----------------------------------------*/
/* --- Fax: 86-0513-55012956,55012947,55012969 ------------------------*/
/* --- Tel: 86-0513-55012928,55012929,55012966 ------------------------*/
/* --- Web: www.STCMCU.com --------------------------------------------*/
/* --- Web: www.STCMCUDATA.com  ---------------------------------------*/
/* --- QQ:  800003751 -------------------------------------------------*/
/* 如果要在程序中使用此代码,请在程序中注明使用了STC的资料及程序            */
/*---------------------------------------------------------------------*/#ifndef	__GPIO_H
#define	__GPIO_H#include	"config.h"#define	GPIO_PullUp		0	//上拉准双向口
#define	GPIO_HighZ		1	//浮空输入
#define	GPIO_OUT_OD		2	//开漏输出
#define	GPIO_OUT_PP		3	//推挽输出#define	GPIO_Pin_0		0x01	//IO引脚 Px.0
#define	GPIO_Pin_1		0x02	//IO引脚 Px.1
#define	GPIO_Pin_2		0x04	//IO引脚 Px.2
#define	GPIO_Pin_3		0x08	//IO引脚 Px.3
#define	GPIO_Pin_4		0x10	//IO引脚 Px.4
#define	GPIO_Pin_5		0x20	//IO引脚 Px.5
#define	GPIO_Pin_6		0x40	//IO引脚 Px.6
#define	GPIO_Pin_7		0x80	//IO引脚 Px.7
#define	GPIO_Pin_All	0xFF	//IO所有引脚#define	GPIO_P0			0		//
#define	GPIO_P1			1
#define	GPIO_P2			2
#define	GPIO_P3			3
#define	GPIO_P4			4
#define	GPIO_P5			5
#define	GPIO_P6			6
#define	GPIO_P7			7typedef struct
{u8	Mode;		//IO模式,  		GPIO_PullUp,GPIO_HighZ,GPIO_OUT_OD,GPIO_OUT_PPu8	Pin;		//要设置的端口	
} GPIO_InitTypeDef;u8	GPIO_Inilize(u8 GPIO, GPIO_InitTypeDef *GPIOx);#endif
关键库函数
  • GPIO_Inilize(u8 GPIO, GPIO_InitTypeDef *GPIOx):初始化GPIO引脚方向和模式。
代码示例
#include "stc8h.h"void Delay(uint16_t ms) {while (ms--) {for (volatile uint16_t i = 0; i < 12000; i++);}
}void	GPIO_config(void)
{GPIO_InitTypeDef	GPIO_InitStructure;				//结构定义GPIO_InitStructure.Pin  = GPIO_Pin_All;				//指定要初始化的IO,GPIO_InitStructure.Mode = GPIO_PullUp;				//指定IO的输入或输出方式,GPIO_PullUp,GPIO_HighZ,GPIO_OUT_OD,GPIO_OUT_PPGPIO_Inilize(GPIO_P0,&GPIO_InitStructure);			//初始化
}int main() {// 1. 配置P0端口为推挽输出模式GPIO_config(); while (1) {// 2. 全部点亮LED(假设共阴极)P0 = 0xFF;  // 输出高电平Delay(500);// 3. 全部熄灭LEDP0 = 0;      // 输出低电平Delay(500);}
}
原理分析
  • 优势:代码简洁易读,封装了寄存器操作细节。
  • 缺点:函数调用开销较大,执行速度略低于直接寄存器操作。

3. 优化库函数模式(位操作)

步骤说明
  1. 配置GPIO模式:通过寄存器设置为推挽输出。
  2. 位操作:利用STC的位(Bit-Band)功能快速操作单个引脚。
优化技巧:
(1)使用宏定义GPIO端口和引脚
/* GPIO组号,是GPIO宏操作函数的第一个参数,支持对这个宏进行再封装 */
#define	GPIO_P0  0 /*!< IO P0. */
#define	GPIO_P1  1 /*!< IO P1. */
#define	GPIO_P2  2 /*!< IO P2. */
#define	GPIO_P3  3 /*!< IO P3. */
#define	GPIO_P4  4 /*!< IO P4. */
#define	GPIO_P5  5 /*!< IO P5. */
#define	GPIO_P6  6 /*!< IO P6. */
#define	GPIO_P7  7 /*!< IO P7. *//* GPIO端口号,是GPIO宏操作函数的第二个参数,支持多个宏进行或运算,同时配置多个IO */
#define	Pin_0    0x01  /*!< IO Pin Px.0 . */
#define	Pin_1    0x02  /*!< IO Pin Px.1 . */
#define	Pin_2    0x04  /*!< IO Pin Px.2 . */
#define	Pin_3    0x08  /*!< IO Pin Px.3 . */
#define	Pin_4    0x10  /*!< IO Pin Px.4 . */
#define	Pin_5    0x20  /*!< IO Pin Px.5 . */
#define	Pin_6    0x40  /*!< IO Pin Px.6 . */
#define	Pin_7    0x80  /*!< IO Pin Px.7 . */
#define	Pin_Low  0x0F  /*!< IO Pin Px.0~3 . */
#define	Pin_High 0xF0  /*!< IO Pin Px.4~7 . */
#define	Pin_All  0xFF  /*!< IO Pin All . */
(2)用枚举定义输入输出模式和IO端口电平
typedef enum
{GPIO_MODE_WEAK_PULL 	= 0x00,GPIO_MODE_IN_FLOATING = 0x01,GPIO_MODE_OUT_OD 			= 0x10,GPIO_MODE_OUT_PP 			= 0x11,
} eGPIO_Mode;/* GPIO Bit SET和Bit RESET枚举 */
typedef enum
{GPIO_PIN_RESET = 0,GPIO_PIN_SET = 1
} eGPIO_PinState;
(3)使用 ## 字符连接宏定义
/* ## 字符连接宏定义 A(x) (T_##X) == A(1) --> T_1 	*/
#define GPIO_Px(x)  (P##x)		// GPIO_Px(1) --> P1
#define Px_M1(x) 	(P##x##M1)  // Px_M1(0) --> P0M1	//GPIO_P0M1 GPIO_P0M0
#define Px_M0(x) 	(P##x##M0)  // P0M1 P0M0
(4)写模式配置宏函数
/* GPIO设置为准双向口(弱上拉)模式宏函数。*/
#define GPIO_MODE_WEAK_PULL(gpio_x,pin)   	\do{Px_M1(gpio_x) &= ~(pin); Px_M0(gpio_x) &= ~(pin);}while(0)/* GPIO设置为浮空输入模式宏函数。*/
#define GPIO_MODE_IN_FLOATING(gpio_x,pin) 	\do{ Px_M1(gpio_x) |=  (pin); Px_M0(gpio_x) &= ~(pin);}while(0)/* GPIO设置为开漏输出模式宏函数。*/
#define GPIO_MODE_OUT_OD(gpio_x,pin) 		\do{Px_M1(gpio_x) |=  (pin); Px_M0(gpio_x) |=  (pin);}while(0)/* GPIO设置为推挽输出模式宏函数。*/
#define	GPIO_MODE_OUT_PP(gpio_x,pin) 		\do{Px_M1(gpio_x) &= ~(pin); Px_M0(gpio_x) |=  (pin);}while(0)
(5)使用 if 优化模式配置宏函数
#define GPIO_Init(gpio_x, pin, mode)					\do{ if(mode & 0x01)	Px_M0(gpio_x) |= (pin);			\else	Px_M0(gpio_x) &= ~(pin);				\if((mode & 0x02))	Px_M1(gpio_x) |= (pin);		\else	Px_M1(gpio_x) &= ~(pin);				\}while(0)
(6)使用三目运算符优化模式配置宏函数
#define GPIO_MODE_CFG(gpio_x, pin, mode)							  					  		\	do{ Px_M0(gpio_x) = ((mode & 0x01)? Px_M0(gpio_x)|(pin) : Px_M0(gpio_x)&(~pin));	\Px_M1(gpio_x) = ((mode & 0x02)? Px_M1(gpio_x)|(pin) : Px_M1(gpio_x)&(~pin));  	\	}while(0)

看到这里,是不是有一种代码好美的感觉。


三种模式对比

模式代码复杂度执行效率可读性适用场景
寄存器直接操作最高需极致性能的实时控制
标准库函数快速开发与调试
优化库函数高效且可读的代码

总结

通过三种编程模式的对比与示例,开发者可根据项目需求灵活选择实现方式:

  • 寄存器直接操作:适合对性能要求极高的场景(如实时控制)。
  • 官方库函数:适合快速开发与调试,代码可读性高。
  • 优化库函数:在保证高效性的同时,提供对单个引脚的精准控制。

通过合理选择模式,可兼顾开发效率与硬件性能,满足不同场景需求。顾性能与开发效率。

终极奥义
“通过重构库函数,深入单片机寄存器操作,悟出最佳逻辑,掌控单片机!”

希望本教程对您有所帮助,祝您在嵌入式开发的道路上取得更大的成功!

相关文章:

【极光 Orbit·STC8AH】04. 深度探索 GPIO 底层逻辑

【极光 OrbitSTC8A&H】04. 深度探索 GPIO 底层逻辑 引言&#xff1a;当代码遇见硬件 上周我看着学生调试的工控产品&#xff0c;他们困惑地盯着自己编写的代码&#xff1a;“老师&#xff0c;这段C语言明明在PC上跑得没问题啊&#xff01;” &#xff0c;让我想起自己初学…...

67.Harmonyos NEXT 图片预览组件之性能优化策略

温馨提示&#xff1a;本篇博客的详细代码已发布到 git : https://gitcode.com/nutpi/HarmonyosNext 可以下载运行哦&#xff01; Harmonyos NEXT 图片预览组件之性能优化策略 文章目录 Harmonyos NEXT 图片预览组件之性能优化策略效果预览一、性能优化概述1. 性能优化的关键指标…...

uni-app+SpringBoot: 前端传参,后端如何接收参数

做项目中的一些小经验&#xff0c;方便后续 &#xff08;1&#xff09;前端代码中&#xff0c;请求的 URL 是通过查询参数&#xff08;?id${articleId}&#xff09;传递的 后端接口&#xff1a; GetMapping("/knowledgeDetail") public Result getKnowledgeByid(R…...

【Vue.js】

一、简介 1、概述 官网GitHub - Vuejs Vue 是一款用于构建用户界面的 JavaScript 框架。它基于标准 HTML、CSS 和 JavaScript 构建&#xff0c;并提供了一套声明式的、组件化的编程模型&#xff0c;帮助你高效地开发用户界面。 Vue.js作为一个渐进式框架&#xff0c;其设计理…...

正则表达式入门及常用的正则表达式

正则表达式&#xff08;Regular Expression&#xff0c;简称 Regex&#xff09;是一种强大的文本处理工具&#xff0c;用于匹配、查找和替换字符串中的特定模式。以下是入门指南和常用正则表达式示例&#xff1a; 一、正则表达式入门 1. 基本语法 符号说明示例.匹配任意单个字…...

Windows下安装Git客户端

① 官网地址&#xff1a;https://git-scm.com/。 ② Git的优势 大部分操作在本地完成&#xff0c;不需要联网&#xff1b;完整性保证&#xff1b;尽可能添加数据而不是删除或修改数据&#xff1b;分支操作非常快捷流畅&#xff1b;与Linux 命令全面兼容。 ③ Git的安装 从官网…...

SAP IBP for Supply Chain Certification Guide (Parag Bakde, Rishabh Gupta)

SAP IBP for Supply Chain Certification Guide (Parag Bakde, Rishabh Gupta)...

【计算机网络通信 AMQP】使用 Qt 调用 qamqp 库进行 AMQP 通信

以下是一个使用 Qt 实现 AMQP 通信的代码示例。为了实现这个功能&#xff0c;我们可以使用 qamqp 库&#xff0c;它是一个基于 Qt 的 AMQP 客户端库。首先&#xff0c;你需要将 qamqp 库添加到你的 Qt 项目中&#xff0c;可以通过 qmake 或 CMake 进行配置。 #include <QCo…...

C语言中的指针与数组:概念、关系与应用

指针和数组都是C语言中极其重要的概念,本文将分步骤深入分析指针和数组在C语言中的概念、它们之间的关系以及它们在实际编程中的应用。 一、指针与数组的基本概念详解 1.1 指针详解 指针是一个变量,它存储的是另一个变量的内存地址。理解指针的核心就是“内存地址”,指针…...

如何处理PHP中的日期和时间问题

如何处理PHP中的日期和时间问题 在PHP开发中&#xff0c;日期和时间的处理是一个常见且重要的任务。无论是记录用户操作时间、生成时间戳&#xff0c;还是进行日期计算&#xff0c;PHP提供了丰富的函数和类来帮助开发者高效处理这些需求。本文将详细介绍如何在PHP中处理日期和…...

TDengine 使用最佳实践

简介 阅读本文档需要具备的基础知识&#xff1a; Linux系统的基础知识&#xff0c;及基本命令网络基础知识&#xff1a;TCP/UDP、http、RESTful、域名解析、FQDN/hostname、hosts、防火墙、四层/七层负载均衡 本文档的阅读对象有&#xff1a;架构师、研发工程师&#xff0c;…...

Spring、Spring Boot、Spring Cloud 的区别与联系

1. Spring 框架 定位&#xff1a;轻量级的企业级应用开发框架&#xff0c;核心是 IoC&#xff08;控制反转&#xff09; 和 AOP&#xff08;面向切面编程&#xff09;。 核心功能&#xff1a; 依赖注入&#xff08;DI&#xff09;&#xff1a;通过 Autowired、Component 等注解…...

AutoGen-构建问答智能体

概述 如https://github.com/microsoft/autogen所述&#xff0c;autogen是一多智能体的框架&#xff0c;属于微软旗下的产品。 依靠AutoGen我们可以快速构建出一个多智能体应用&#xff0c;以满足我们各种业务场景。 环境说明 python&#xff0c;3.10AutoGen&#xff0c;0.4.2…...

C语言实现括号匹配检查及栈的应用详解

目录 栈数据结构简介 C语言实现栈 栈的初始化 栈的销毁 栈的插入 栈的删除 栈的判空 获取栈顶数据 利用栈实现括号匹配检查 总结 在编程中&#xff0c;经常会遇到需要检查括号是否匹配的问题&#xff0c;比如在编译器中检查代码的语法正确性&#xff0c;或者在…...

C语言中的字符串与数组的关系

在C语言中,字符串和数组之间有着紧密的关系。理解它们的区别和联系对于编写高效且可靠的代码至关重要。在本篇博文中,我们将详细分析字符串和数组在C语言中的概念、它们的关系以及如何在编程中应用它们。 一、字符串与数组的基础知识 1.1 数组概念 在C语言中,数组是一组相…...

阿里云魔笔低代码应用开发平台快速搭建教程

AI低代码&#xff0c;大模型时代应用开发新范式 什么是魔笔 介绍什么是魔笔低代码应用开发平台。 魔笔是一款面向全端&#xff08;Web、H5、全平台小程序、App&#xff09;场景的模型驱动低代码开发平台&#xff0c;提供一站式的应用全生命周期管理&#xff0c;包括可视化开发…...

A Survey on Mixture of Experts 混合专家模型综述(第二部分:混合专家系统设计)

A Survey on Mixture of Experts 混合专家模型综述 (第一部分&#xff1a;混合专家算法设计) A Survey on Mixture of Experts arxiv github&#xff1a;A-Survey-on-Mixture-of-Experts-in-LLMs ​ ​ ​ 5 System Design of Mixture of Experts While ​Mixture of Exper…...

docker python:latest镜像 允许ssh远程

跳转到家目录 cd创建pythonsshdockerfile mkdir pythonsshdockerfile跳转pythonsshdockerfile cd pythonsshdockerfile创建Dockerfile文件 vim Dockerfile将Dockerfile的指令复制到文件中 # 使用 python:latest 作为基础镜像 # 如果我的镜像列表中没有python:latest镜像&…...

通过 CSS 的 命名页面(Named Pages) 技术实现作用域隔离,实现 @page 样式仅影响当前组件

以下是实现 page 样式仅影响当前组件的完整解决方案&#xff0c;通过 CSS 的 命名页面&#xff08;Named Pages&#xff09; 技术实现作用域隔离&#xff1a; vue <template><div><button v-print"printOptions">打印当前报表</button><…...

Aim Robotics电动胶枪:机器人涂胶点胶的高效解决方案

在自动化和智能制造领域&#xff0c;机器人技术的应用越来越广泛&#xff0c;而涂胶和点胶作为生产过程中的重要环节&#xff0c;也逐渐实现了自动化和智能化。Aim Robotics作为一家专注于机器人技术的公司&#xff0c;其推出的电动胶枪为这一领域带来了高效、灵活且易于操作的…...

动态规划----完全平方数(3种写法,逐步简化)

题目链接&#xff1a;完全平方数 完全平方数可以认为是完全背包问题。每一个平方小于n的平方数都是物品&#xff0c;而完全平方数之和n就是背包容量。每一个平方和都可以无限次使用。 写法1&#xff1a;把所有小于n的平方数存入数组nums,使用二维dp数组。 递推公式的推导可以…...

C#中通过Response.Headers设置自定义参数

一、基础设置方法 1. 直接添加自定义头 // ASP.NET Core方案 Response.Headers.Append("X-API-Version", "2.3.1"); Response.Headers.Append("Custom-Auth-Token", Guid.NewGuid().ToString());• 底层原理&#xff1a;通过IHeaderDictionary…...

【HDLbits--分支预测器简单实现】

HDLbits--分支预测器简单实现 1 timer2.branche predicitors3.Branch history shift4.Branch direction predictor 以下是分支预测器的简单其实现&#xff1b; 1 timer 实现一个计时器&#xff0c;当load1’b1时&#xff0c;加载data进去&#xff0c;当load1’b0时进行倒计时&…...

LLM自动化评测

使用的数据集&#xff1a;ceval-exam import requests from datasets import load_dataset, concatenate_datasets import re from tqdm import tqdm import re, time, tiktoken, ollama from ollama import ChatResponse from ollama import Optionsdef llm(model, query, te…...

Linux--操作系统/进程

ok&#xff0c;我们今天学习linux中的操作系统和进程 1. 冯诺依曼体系 我们常⻅的计算机&#xff0c;如笔记本。我们不常⻅的计算机&#xff0c;如服务器&#xff0c;⼤部分都遵守冯诺依曼体系。 内存是CPU和外设之间的一个巨大的缓存&#xff01; 截⾄⽬前&#xff0c;我们…...

MFC控件按钮的使用

MFC窗口的创建/消息映射机制 mfc.h #include<afxwin.h>//mfc头文件//应用程序类 class MyApp:public CWinApp //继承于应用程序类 { public://程序入口virtual BOOL InitInstance(); };//框架类 class MyFrame:public CFrameWnd { public:MyFrame();//声明宏 提供消息映…...

Java面试八股—Redis篇

一、Redis的使用场景 &#xff08;一&#xff09;缓存 1.Redis使用场景缓存 场景&#xff1a;缓存热点数据&#xff08;如用户信息、商品详情&#xff09;&#xff0c;减少数据库访问压力&#xff0c;提升响应速度。 2.缓存穿透 正常的访问是&#xff1a;根据ID查询文章&…...

计算矩阵边缘元素之和(信息学奥赛一本通-1121)

【题目描述】 输入一个整数矩阵&#xff0c;计算位于矩阵边缘的元素之和。所谓矩阵边缘的元素&#xff0c;就是第一行和最后一行的元素以及第一列和最后一列的元素。 【输入】 第一行分别为矩阵的行数m和列数n&#xff08;m<100&#xff0c;n<100&#xff09;&#xff0c…...

Web后端开发之Maven

Maven Mven是apache旗下的一个开源项目&#xff0c;用来管理和构建java项目的工具。 通过一小段描述信息来管理项目。 Maven的作用 1.依赖管理&#xff1a;方便快捷的管理项目依赖的资源&#xff08;jar包&#xff09;&#xff0c;避免版本冲突问题 以前用某个jar包需要下载…...

哈希算法,蓝桥杯java备战中

哈希表的实现 核心思路 目标&#xff1a;实现一个基于开放寻址法&#xff08;线性探测&#xff09;的哈希表&#xff0c;支持插入元素 I x 和查询元素 Q x 两种操作。 核心逻辑&#xff1a; 哈希函数&#xff1a;将元素映射到固定范围的索引&#xff08;哈希值&#xff09;。…...