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

嵌入式面试高频!!!C语言(四)(嵌入式八股文,嵌入式面经)

 更多嵌入式面试文章见下面连接,会不断更新哦!!关注一下谢谢!!!!

 ​​​​​​​https://blog.csdn.net/qq_61574541/category_12976911.html?fromshare=blogcolumn&sharetype=blogcolumn&sharerId=12976911&sharerefer=PC&sharesource=qq_61574541&sharefrom=from_linkhttps://blog.csdn.net/qq_61574541/category_12976911.html?fromshare=blogcolumn&sharetype=blogcolumn&sharerId=12976911&sharerefer=PC&sharesource=qq_61574541&sharefrom=from_link

一、volatile 关键字和 extern 关键字

1. 作用
  • 禁止编译器优化:告诉编译器 “这个变量的值可能随时以不可预知的方式被改变”,因此每次访问都必须从内存中读取,而非使用寄存器中的缓存值。
  • 典型场景
    • 硬件寄存器:如嵌入式系统中的 I/O 端口。
    • 多线程共享变量:被中断服务程序(ISR)修改的变量。
    • 内存映射设备:如 LCD 控制器的内存地址。
volatile int status_reg;  // 硬件状态寄存器// 编译器不会优化对status_reg的读取
while (status_reg != 0);  // 每次循环都从内存读取status_reg
2. 生效阶段
  • 编译阶段:编译器在生成机器码时,会强制每次都从内存读取 / 写入 volatile 变量,而非依赖寄存器缓存。

二、extern 关键字

1. 作用
  • 声明外部链接:告诉编译器 “这个变量或函数的定义在其他文件中”,从而避免重复定义。
  • 典型场景
    • 多文件项目:在头文件中声明全局变量或函数,在源文件中定义。
    • 跨语言调用:如 C++ 调用 C 函数时使用 extern "C"

// 文件1.c
int global_var = 10;  // 定义全局变量// 文件2.c
extern int global_var;  // 声明外部变量
printf("%d", global_var);  // 使用全局变量
3. 生效阶段
  • 链接阶段:编译器生成目标文件时,extern 声明的符号会被标记为 “外部引用”,由链接器在其他目标文件中查找对应的定义。

三、核心区别对比

特性volatileextern
作用禁止编译器优化,强制内存访问声明外部定义的变量或函数
生效阶段编译阶段链接阶段
影响范围单个变量或对象整个项目中的符号解析
典型场景硬件交互、多线程共享变量多文件项目、跨语言调用
与内存的关系每次访问都从内存读取 / 写入不涉及内存分配,仅声明符号存在

四、常见误区

1. volatile 用于多线程同步
  • 错误:认为 volatile 能替代同步机制(如互斥锁)。
  • 真相volatile 仅阻止编译器优化,但无法解决多线程竞争问题(如原子性)。
2. extern 用于定义变量
  • 错误:在头文件中写 extern int x = 10;
  • 真相extern 仅声明变量,定义必须在源文件中进行(int x = 10;)。

 二、堆和栈有什么不同

一、基本概念

1. 栈(Stack)
  • 内存分配:由操作系统自动管理,遵循 后进先出(LIFO) 原则。
  • 存储内容:函数调用的上下文(局部变量、参数、返回地址等)。
  • 典型场景:函数内部的局部变量、函数调用过程中的参数传递。
2. 堆(Heap)
  • 内存分配:由程序员手动管理(如 C 语言的 malloc/free,C++ 的 new/delete)。
  • 存储内容:动态分配的数据(如对象、数组等)。
  • 典型场景:需要在函数外部长期存在的数据(如动态数组、链表)。

二、核心区别对比

特性栈(Stack)堆(Heap)
内存分配方式自动分配和释放(由系统管理)手动分配和释放(需程序员干预)
分配效率高(直接移动栈指针)低(需动态查找可用内存块)
内存空间大小通常较小(如几 MB 到几十 MB)通常较大(受限于物理内存和虚拟内存)
数据生命周期随函数调用结束而销毁直到显式释放(如调用 free
内存碎片问题不存在碎片可能产生碎片(频繁分配 / 释放导致)
生长方向向低地址扩展(栈顶向下移动)向高地址扩展(堆顶向上移动)
内存连续性连续不连续(碎片化)
使用场景局部变量、函数调用上下文动态数据结构(如链表、树)
内存访问方式直接访问(通过栈指针)间接访问(通过指针)

三、典型示例

1. 栈内存示例
void func() {int a = 10;         // 局部变量,分配在栈上char buffer[20];    // 数组,分配在栈上// 函数结束时,a和buffer自动释放
}

 2. 堆内存示例

void dynamic_allocation() {int* p = (int*)malloc(sizeof(int));  // 在堆上分配内存if (p != NULL) {*p = 20;                         // 通过指针访问堆内存free(p);                         // 手动释放堆内存}
}

四、常见问题

1. 栈溢出(Stack Overflow)
  • 原因:递归过深或局部变量过大,导致栈空间耗尽。
  • 解决:减少递归深度、使用堆内存替代大数组。
2. 内存泄漏(Memory Leak)
  • 原因:堆内存分配后未释放,导致内存持续占用。
  • 解决:确保每次 malloc/new 后都有对应的 free/delete
3. 性能对比
  • :分配速度快(约为堆的 10 倍),适合短期使用的数据。
  • :分配速度慢,但灵活性高,适合长期存在的数据。

五、总结

场景推荐使用栈推荐使用堆
数据大小小且固定大或动态变化
生命周期短期(函数内)长期(跨函数)
性能要求
内存管理复杂度低(自动管理)高(手动管理)

 三、堆栈溢出一般是由什么原因导致的?

一、核心原因:栈空间耗尽

栈内存由操作系统自动管理,存储函数调用帧(局部变量、参数、返回地址等)。当栈空间被占满时,会触发堆栈溢出。常见诱因包括:

二、常见场景与示例

1. 无限递归(最常见)
  • 原因:递归函数未正确设置终止条件,导致无限调用。
  • 示例

void recursive() {recursive();  // 无终止条件,无限递归
}int main() {recursive();  // 触发堆栈溢出
}
  • 分析:每次递归调用都会在栈上创建新的函数帧,最终耗尽栈空间。
2. 过深的递归调用
  • 原因:递归深度过大(如树的遍历深度超过栈容量)。
  • 示例
void deepRecursion(int n) {if (n == 0) return;int arr[1000];  // 每次递归占用大量栈空间deepRecursion(n - 1);
}int main() {deepRecursion(100000);  // 可能导致栈溢出
}

3. 大型局部变量
  • 原因:在函数内部定义过大的数组或结构体,超出栈空间限制。
  • 示例
void largeArray() {char buffer[1024 * 1024];  // 1MB数组,可能超出栈容量
}

4. 嵌套过深的函数调用
  • 原因:非递归的多层函数调用(如 A→B→C→...),每层调用都占用栈空间。
  • 示例
void func1() { func2(); }
void func2() { func3(); }
// ... 更多嵌套函数
void func1000() { /* 占用栈空间 */ }int main() {func1();  // 可能导致深层嵌套
}

5. 栈空间不足(系统限制)
  • 原因:操作系统默认栈空间较小(如 Linux 默认 8MB),无法满足程序需求。
  • 解决:通过命令行增大栈空间限制(如 Linux 的 ulimit -s)。

    三、不同语言的堆栈溢出表现

    语言错误提示常见诱因
    C/C++Segmentation fault无限递归、大型局部数组
    JavaStackOverflowError无限递归(如 toString () 循环引用)
    PythonRecursionError递归深度超过限制(默认约 1000 次)
    JavaScriptRangeError: Maximum call stack size exceeded浏览器环境中的无限递归

四、预防与解决方法 

  1. 修复递归终止条件:确保递归函数有明确的退出条件。

void safeRecursion(int n) {if (n <= 0) return;  // 正确终止条件safeRecursion(n - 1);
}

 2.使用迭代替代递归:对于深度不确定的场景,用循环代替递归。

void iterative() {while (true) {  // 循环实现,不占用栈空间// ...}
}

 3.减小局部变量大小:将大型数组或结构体改为动态分配(堆内存)。

void dynamicAllocation() {char* buffer = (char*)malloc(1024 * 1024);  // 堆分配if (buffer) {// 使用bufferfree(buffer);}
}

4.增加系统栈限制:在 Linux 中通过 ulimit -s unlimited 临时增大栈空间。

5.尾递归优化:部分语言(如 Python 不支持,C++ 支持)可将递归转换为循环。

// 尾递归示例(需编译器优化)
int tailRecursive(int n, int acc) {if (n == 0) return acc;return tailRecursive(n - 1, acc + n);  // 尾递归调用
}

  四、内存泄漏和内存池

一、内存泄漏(Memory Leak)

1. 定义
  • 程序在堆上动态分配的内存(如 malloc/new),在不再使用时未被释放(如未调用 free/delete),导致这部分内存无法被操作系统回收。
2. 常见原因
  • 忘记释放内存
void leakExample() {int* ptr = (int*)malloc(sizeof(int));// 使用ptr,但未调用free(ptr)
}  // 内存泄漏!

  • 异常导致的泄漏:函数中途抛出异常,未执行释放代码。
  • 循环分配内存:在循环中持续分配内存而不释放。
  • 指针丢失:指向内存的指针被覆盖,导致无法释放。
3. 危害
  • 长期运行的程序(如服务器)会逐渐耗尽可用内存,最终导致系统崩溃。
  • 碎片化内存:频繁分配和释放不同大小的内存块,导致内存碎片化,降低分配效率。
4. 检测工具
  • Valgrind(Linux):检测内存泄漏和越界访问。
  • AddressSanitizer(ASan):GCC/Clang 内置的快速内存错误检测工具。
  • Visual Studio 内存分析器:Windows 平台下的内存调试工具。

二、内存池(Memory Pool)

1. 定义
  • 一种内存管理技术,预先分配大块内存(池),然后按需分配小块内存给程序使用。当程序释放内存时,内存块不直接返回给操作系统,而是返回给池以便后续复用。
2. 核心思想
  • 预分配:一次性分配大块内存,减少系统调用次数。
  • 复用:回收的内存块不释放,直接复用,避免频繁分配 / 释放。
  • 减少碎片:通过固定大小的内存块或智能分配算法,减少内存碎片。
3. 简单实现示例

#include <stdlib.h>// 内存池节点结构
typedef struct MemNode {struct MemNode* next;char data[1];  // 实际数据从这里开始
} MemNode;// 内存池结构
typedef struct {MemNode* freeList;  // 空闲链表size_t blockSize;   // 每个内存块大小size_t chunkSize;   // 每次分配的块数量
} MemPool;// 初始化内存池
MemPool* createPool(size_t blockSize, size_t chunkSize) {MemPool* pool = (MemPool*)malloc(sizeof(MemPool));pool->blockSize = blockSize;pool->chunkSize = chunkSize;pool->freeList = NULL;return pool;
}// 从内存池分配内存
void* poolAlloc(MemPool* pool) {if (pool->freeList == NULL) {// 无空闲块,分配新的一组块size_t realSize = sizeof(MemNode) + pool->blockSize - 1;MemNode* chunk = (MemNode*)malloc(realSize * pool->chunkSize);// 将新分配的块加入空闲链表for (size_t i = 0; i < pool->chunkSize; i++) {MemNode* node = &chunk[i];node->next = pool->freeList;pool->freeList = node;}}// 从空闲链表取出一个块MemNode* node = pool->freeList;pool->freeList = node->next;return &node->data;
}// 释放内存回池
void poolFree(MemPool* pool, void* ptr) {MemNode* node = (MemNode*)((char*)ptr - offsetof(MemNode, data));node->next = pool->freeList;pool->freeList = node;
}// 销毁内存池
void destroyPool(MemPool* pool) {// 实际实现中需遍历所有分配的块并释放free(pool);
}
4. 优势
  • 高性能:减少系统调用(malloc/free),分配速度提升 5-10 倍。
  • 减少碎片:通过固定大小的内存块或分桶策略,降低内存碎片。
  • 控制内存:可预测的内存使用模式,避免内存泄漏。
5. 适用场景
  • 频繁分配 / 释放小对象:如网络服务器中的连接请求处理。
  • 实时系统:需要确定性的内存分配时间(如游戏引擎)。
  • 内存碎片敏感场景:长期运行的程序(如数据库、中间件)。

三、内存泄漏 vs 内存池

特性内存泄漏内存池
本质内存管理错误内存管理优化技术
原因未释放不再使用的内存预分配和复用内存块
危害内存耗尽、系统崩溃可能占用更多常驻内存
解决方法检测工具(Valgrind)、RAII自行实现或使用第三方库(如 Boost)
性能影响无直接影响(但可能导致系统变慢)显著提升分配速度
适用场景所有动态内存分配场景高频分配 / 释放相同大小内存的场景

四、高级内存池技术

  1. 分级内存池:按不同大小分桶管理内存块。
  2. 线程私有内存池:每个线程独立维护内存池,避免锁竞争。
  3. 内存池与垃圾回收结合:在某些语言(如 Python)中自动回收不再使用的内存池。

   五、指针的运算

                int *ptr//假设地址为0x00 00 00 00 (32位系统)

                prt++;//0x00 00 00 04

                对于32位系统所有类型的指针都只占4字节的空间。

相关文章:

嵌入式面试高频!!!C语言(四)(嵌入式八股文,嵌入式面经)

更多嵌入式面试文章见下面连接&#xff0c;会不断更新哦&#xff01;&#xff01;关注一下谢谢&#xff01;&#xff01;&#xff01;&#xff01; ​​​​​​​https://blog.csdn.net/qq_61574541/category_12976911.html?fromshareblogcolumn&sharetypeblogcolumn&…...

数据治理在制造业的实践案例

一、数据治理在制造业的重要性 随着工业4.0的到来,制造业正经历着前所未有的变革。数据治理作为制造业数字化转型的关键组成部分,对提升企业竞争力、优化生产流程、提高产品质量和客户满意度等方面起着至关重要的作用。在制造业中,数据治理不仅涉及到数据的收集、存…...

【强化学习】——03 Model-Free RL之基于价值的强化学习

【强化学习】——03 Model-Free RL之基于价值的强化学习 \quad\quad \quad\quad 动态规划算法是基于模型的算法,要求已知状态转移概率和奖励函数。但很多实际问题中环境 可能是未知的,这就需要不基于模型(Model-Free)的RL方法。 \quad\quad 其又分为: 基于价值(Valu…...

Edge(Bing)自动领积分脚本部署——基于python和Selenium(附源码)

微软的 Microsoft Rewards 计划可以通过 Bing 搜索赚取积分&#xff0c;积分可以兑换礼品卡、游戏等。每天的搜索任务不多&#xff0c;我们可以用脚本自动完成&#xff0c;提高效率&#xff0c;解放双手。 本文将手把手教你如何部署一个自动刷积分脚本&#xff0c;并解释其背…...

html表格转换为markdown

文章目录 工具功能亮点1.核心实现解析1. 剪贴板交互2. HTML检测与提取3. 转换规则设计 2. 完整代码 在日常工作中&#xff0c;我们经常遇到需要将网页表格快速转换为Markdown格式的场景。无论是文档编写、知识整理还是数据迁移&#xff0c;手动转换既耗时又容易出错。本文将介绍…...

VsCode 安装 Cline 插件并使用免费模型(例如 DeepSeek)

当前时间为 25/6/3&#xff0c;Cline 版本为 3.17.8 点击侧边栏的“扩展”图标 在搜索框中输入“Cline” 找到 Cline 插件&#xff0c;然后点击“安装” 安装完成后&#xff0c;Cline 图标会出现在 VS Code 的侧边栏中 点击 Use your own API key API Provider 选择 OpenRouter…...

短视频矩阵系统源码新发布技术方案有那几种?

短视频矩阵运营在平台政策频繁更迭的浪潮中&#xff0c;已成为内容分发的核心战场。行业领先者如筷子科技、云罗抖去推、超级编导等平台&#xff0c;其稳定高效的代发能力背后&#xff0c;离不开前沿技术方案的强力支撑。本文将深入剖析当前主流的六大短视频矩阵系统代发解决方…...

React 第五十二节 Router中 useResolvedPath使用详解和注意事项示例

前言 useResolvedPath 是 React Router v6 提供的一个实用钩子&#xff0c;用于解析给定路径为完整路径对象。 它根据当前路由上下文解析相对路径&#xff0c;生成包含 pathname、search 和 hash 的完整路径对象。 一、useResolvedPath 核心用途 路径解析&#xff1a;将相对…...

【PmHub面试篇】性能监控与分布式追踪利器Skywalking面试专题分析

你好&#xff0c;欢迎来到本次关于PmHub整合性能监控与分布式追踪利器Skywalking的面试系列分享。在这篇文章中&#xff0c;我们将深入探讨这一技术领域的相关面试题预测。若想对相关内容有更透彻的理解&#xff0c;强烈推荐参考之前发布的博文&#xff1a;【PmHub后端篇】Skyw…...

Cursor快速梳理ipynb文件Prompt

1. 整体鸟瞰 请在不运行代码的前提下&#xff0c;总结 <文件名.ipynb> 的主要目的、核心逻辑流程和输出结果。阅读整个项目目录&#xff0c;列出每个 .ipynb / .py 文件的角色&#xff0c;以及它们之间的数据依赖关系&#xff08;输入→处理→输出&#xff09;。2. 结构…...

天机学堂-分页查询

需求 分页查询我的课表 返回&#xff1a; 总条数、总页数、当前页的课表信息的集合 返回的VO&#xff08;已经封装成统一的LearningLessonsVO&#xff09; 定义Controller RestController RequestMapping("/lessons") RequiredArgsConstructor public class Lear…...

业态即战场:零售平台的生意模型与系统设计解构

目录 一、当我们在电商买菜、点外卖时,其实是零售业态在进化 (一)从“商场选货”到“算法推货”:零售的时代已经不同 (二)“控货”和“卖场”——零售的两种基本商业模式 二、四种经典零售业态解析:控货 vs 卖场,地面 vs 线上 (一)地面控货零售:直营模式的黄金…...

微算法科技(NASDAQ:MLGO)基于信任的集成共识和灰狼优化(GWO)算法,搭建高信任水平的区块链网络

随着数字化转型的加速&#xff0c;区块链技术作为去中心化、透明且不可篡改的数据存储与交换平台&#xff0c;正逐步渗透到金融、供应链管理、物联网等多个领域&#xff0c;探索基于信任的集成共识机制&#xff0c;并结合先进的优化算法来提升区块链网络的信任水平&#xff0c;…...

全新Xsens Animate版本是迄今为止最大的软件升级,提供更清晰的数据、快捷的工作流程以及从录制开始就更直观的体验

我们整合了专业人士喜爱的 Xsens 动捕功能&#xff0c;并使其更加完善。全新Xsens Animate版本是我们迄今为止最大的软件升级&#xff0c;旨在提供更清晰的数据、更快捷的工作流程以及从录制开始就更直观的体验。 从制作游戏动画到流媒体直播头像或构建实时电影内容&#xff0…...

大语言模型评测体系全解析(下篇):工具链、学术前沿与实战策略

文章目录 一、评测工具链&#xff1a;从手工测试到自动化工程的效率革命&#xff08;一&#xff09;OpenCompass&#xff1a;开源评测框架的生态构建1. 技术架构&#xff1a;三层架构实现评测自动化2. 开发者赋能&#xff1a;从入门到进阶的工具矩阵 &#xff08;二&#xff09…...

python打卡day46@浙大疏锦行

知识点回顾&#xff1a; 不同CNN层的特征图&#xff1a;不同通道的特征图什么是注意力&#xff1a;注意力家族&#xff0c;类似于动物园&#xff0c;都是不同的模块&#xff0c;好不好试了才知道。通道注意力&#xff1a;模型的定义和插入的位置通道注意力后的特征图和热力图 内…...

C++.OpenGL (1/64) 创建窗口(Hello Window)

OpenGL 创建窗口(Hello Window) 步骤详解与代码实现 #mermaid-svg-436DlGvysFQogISc {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-436DlGvysFQogISc .error-icon{fill:#552222;}#mermaid-svg-436DlGvysFQogISc…...

Excel 发现此工作表中有一处或多处公式引用错误。请检查公式中的单元格引用、区域名称、已定义名称以及到其他工作簿的链接是否均正确无误。弹窗

Excel 提示“发现此工作表中有一处或多处公式引用错误”通常表示公式中存在无效引用。以下是系统化的检查步骤&#xff0c;帮助你定位和修复问题&#xff1a; 1. 检查单元格引用&#xff1a; 无效单元格引用&#xff1a;检查公式中的单元格地址&#xff08;如 A1、B10&…...

NVIDIA DRIVE AGX平台:引领智能驾驶安全新时代

随着科技的不断进步&#xff0c;汽车行业正迎来前所未有的变革&#xff0c;智能驾驶技术成为全球产业竞相布局的焦点之一。然而&#xff0c;这场技术革命的背后&#xff0c;最关键且被广泛关注的是安全性问题。近日&#xff0c;我认真研读了NVIDIA发布的《自动驾驶安全报告》白…...

推荐12个wordpress企业网站模板

WordPress企业网站模板是一种专为企业网站设计的WordPress主题&#xff0c;旨在帮助企业创建专业、美观且易于管理的网站。这些模板通常具备响应式设计、SEO优化、多语言支持等功能&#xff0c;能够满足不同行业和企业的需求。 WordPress企业网站模板的适用场景 企业官网&…...

沙市区举办资本市场赋能培训会 点赋科技分享智能消费新实践

荆州市沙市区&#xff0c;2025年6月5日—— 在沙市区政府主办的“发挥区域性股权市场功能&#xff0c;助力企业拥抱资本市场”专题培训会上&#xff0c;区委副书记、区长郭熙胜强调要充分发挥资本市场服务实体经济功能&#xff0c;推动本土创新企业高质量发展。区内重点企业点赋…...

Docker 容器化基础:镜像、容器与仓库的本质解析

Docker 概念与容器化技术 Docker 是一种容器化平台&#xff0c;能够将应用程序及其依赖项打包成一个容器&#xff0c;确保在任何环境中都能一致运行。容器化技术通过操作系统级别的虚拟化&#xff0c;为应用程序提供了一个独立的运行环境。 容器化技术的核心优势 一致性&…...

九.C++ 对引用的学习

一.基本概念 引用即内存的别名 int a 10; int& b a; 引用本身不占用内存&#xff0c;并非实体&#xff0c;对引用的所有操作都是在对目标内存进行操作 引用必须初始化&#xff0c;且不能更换对象 int c 5; b c; // 仅仅是在对引用的目标内存进行赋值 #include <ios…...

探秘鸿蒙 HarmonyOS NEXT:实战用 CodeGenie 构建鸿蒙应用页面

在开发鸿蒙应用时&#xff0c;你是否也曾为一个页面的布局反复调整&#xff1f;是否还在为查 API、写模板代码而浪费大量时间&#xff1f;今天带大家实战体验一下鸿蒙官方的 AI 编程助手——CodeGenie&#xff08;代码精灵&#xff09; &#xff0c;如何从 0 到 1 快速构建一个…...

art-pi2 上手记录(二)

功能比较庞杂&#xff0c;写得不好&#xff0c;抛砖引玉 预备知识 stm32 默认从主闪存0x08000000启动 art-pi2的psram 映射0x90000000 art-pi2的8线ospi flash 映射0x70000000 stm32h7比较灵活&#xff0c;通过修改选项字节&#xff0c;可以实现从 0x0000 0000 到 0x3FFF 0…...

数据库SQLite基础

SQLite的存储结构 --->B树 大型数据库 &#xff1a;Oracle 中型数据库 &#xff1a;Server是微软开发的数据库产品&#xff0c;主要支持windows平台 小型数据库 : MySQL是一个小型关系型数据库管理系统。开放源码 (嵌入式不需要存储太多数据) 一、SQLite基础 SQLite的源代码…...

1.3 古典概型和几何概型

文章目录 古典概型模型(等可能模型)几何概型 古典概型模型(等可能模型) 两个条件&#xff1a; 1) 有限个样本点 2) 等可能性 例题&#xff1a; 设有n个人&#xff0c;每个人都等可能地被分配到N个房间中的任一间(n≤N)&#xff0c; 求下列事件的概率: (1)某指定的n间房…...

html-pre标签

我们都知道在常见标签里面的文字的格式是不会显示的&#xff0c;比如你打了多个空格&#xff0c;但却不会显示&#xff0c;而pre标签会显示。 主要特点&#xff1a; 保留空格和换行&#xff1a;在 <pre> 标签内&#xff0c;HTML 会保留所有的空格、换行符和制表符等格式…...

【WPF】WPF 项目实战:用ObservableCollection构建一个可增删、排序的管理界面(含源码)

&#x1f4a1;WPF 项目实战&#xff1a;构建一个可增删、排序的光源类型管理界面&#xff08;含源码&#xff09; 在实际的图像处理项目中&#xff0c;我们经常需要对“光源类型”进行筛选或管理。今天我们来一步步构建一个实用的 WPF 界面&#xff0c;实现以下功能&#xff1…...

MCU_IO驱动LED

注意事项&#xff1a; 1、亮度要求较高的情况下&#xff0c;不能由IO直接驱动LED MCU_IO引脚输出的电压和电流较弱&#xff0c;如果对光的亮度有要求的话&#xff0c;需要使用三极管来驱动。 MCU_IO的电压一般为3.3V或者5V&#xff0c;输出电流一般10mA-25mA。 2、不同颜色…...