xiaohack's Blog - STM32
type: channel
link: https://blog.xiaohack.org/tag/stm32/
items: 锁存器、触发器、寄存器三者的区别
items: 51单片机都有哪些优缺点
items: 为什么基极和发射极要并联一个电阻
items: IIC总线的硬件部分的两个关键点：开漏输出+上拉电阻
items: 嵌入式就业到底选什么方向？
items: 达林顿管的基础知识
items: 什么是三极管？
items: 什么是MOS管？

锁存器、触发器、寄存器三者的区别
type: item
date: 2026-02-05T10:26:57+08:00
description: 大家好，我是良许。在嵌入式开发中，我们经常会接触到锁存器（Latch）、触发器（Flip-Flop）和寄存器（Register）这三个概念。很多初学者容易把它们混淆，甚至认为它们是同一种东西。实际上，虽然它们都是用于存储数据的数字电路元件，但在工作原理、应用场景和设计考量上存在着本质的区别。今天我就来详细聊聊这三者的区别，帮助大家彻底理解它们。1. 锁存器（Latch）：电平触发的存储单元1.1 基本工作原理锁存器是最基础的存储单元，它的特点是电平触发。什么意思呢?就是说只要使能信号（Enable）处于有效电平期间，锁存器的输出就会跟随输入变化。一旦使能信号变为无效，锁存器就会"锁存"当前的数据状态，保持输出不变。最常见的锁存器是 D 锁存器（Data Latch）。当使能信号 EN 为高电平时，输出 Q 跟随输入 D 变化；当 EN 变为低电平时，Q 保持 EN 变为低电平前一刻 D 的值。这就像一个透明的窗口，使能信号打开窗口时，数据可以自由通过；使能信号关闭窗口时，数据就被"锁"在里面了。1.2 锁存器的问题锁存器虽然结构简单，但在实际应用中存在一个严重的问题——透明性导致的不稳定。在使能信号有效期间，如果输入信号发生毛刺或者抖动，这些干扰都会直接传递到输出端，造成系统不稳定。举个例子，假设我们在 STM32 中使用 GPIO 模拟一个锁存器的行为：// 模拟锁存器行为（仅作演示，实际不推荐这样做） uint8_t latch_data = 0; uint8_t enable_signal = 0; ​ void Latch_Process(uint8_t input_data) { if(enable_signal == 1) // 使能信号有效 { latch_data = input_data; // 输出跟随输入 } // 使能信号无效时，latch_data保持不变 } ​ // 在主循环中 while(1) { enable_signal = HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_0); uint8_t input = HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_1); Latch_Process(input); // 只要enable_signal为高，input的任何变化都会立即反映到latch_data }在这段代码中可以看到，只要使能信号为高电平期间，输入的任何变化都会立即更新到锁存器中。这在某些场景下是致命的，比如在数据传输过程中，如果使能信号持续时间过长，可能会采样到错误的中间状态。1.3 锁存器的应用场景尽管有这些问题，锁存器在某些特定场景下仍然有用武之地。比如在地址锁存、总线保持、异步电路设计等场合。在 8051 单片机中，就使用了地址锁存器来复用地址/数据总线。另外，在 FPGA 设计中，有时为了降低资源消耗，也会在特定条件下使用锁存器。2. 触发器（Flip-Flop）：边沿触发的改进方案2.1 触发器的核心改进触发器是为了解决锁存器的透明性问题而设计的，它的核心特点是边沿触发。什么是边沿触发呢?就是说触发器只在时钟信号的上升沿（或下降沿）这一瞬间采样输入数据，其他时间输入信号如何变化都不会影响输出。最常用的是 D 触发器（D Flip-Flop）。它在时钟信号的上升沿（或下降沿）时刻，将输入 D 的值传递到输出 Q，并保持到下一个时钟边沿到来。这就像拍照一样，只在按下快门的瞬间捕捉画面，其他时间场景如何变化都不影响已经拍下的照片。2.2 触发器的优势边沿触发的特性使得触发器具有很强的抗干扰能力。即使在时钟边沿之外的时间，输入信号有毛刺或抖动，也不会影响输出状态。这使得触发器成为同步数字电路的基础单元。我们可以用代码来模拟触发器的行为：// 模拟D触发器行为 typedef struct { uint8_t Q; // 输出 uint8_t last_clk; // 上一次的时钟状态 } DFlipFlop_t; ​ DFlipFlop_t dff = {0, 0}; ​ void DFlipFlop_Process(uint8_t D, uint8_t clk) { // 检测上升沿 if(clk == 1 && dff.last_clk == 0) // 上升沿触发 { dff.Q = D; // 只在上升沿采样输入 } dff.last_clk = clk; // 记录当前时钟状态 } ​ // 在定时器中断中使用 void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim) { if(htim->Instance == TIM2) { static uint8_t clk_s…

51单片机都有哪些优缺点
type: item
date: 2026-02-04T10:59:22+08:00
description: 大家好，我是良许。今天咱们来聊聊 51 单片机。作为嵌入式开发领域的"老前辈"，51 单片机陪伴了无数工程师走过了学习和工作的岁月。虽然现在 STM32、ESP32 等新一代单片机层出不穷，但 51 单片机依然在某些场景下发挥着不可替代的作用。那么，51 单片机到底有哪些优缺点呢？今天我就从实际开发的角度，给大家详细分析一下。1. 51 单片机的主要优点1.1 学习门槛低，上手快51 单片机最大的优点就是简单易学。它的指令集只有 111 条，相比 ARM Cortex-M 系列动辄上百条指令，学习负担要轻很多。对于刚入门的同学来说，不需要掌握太多复杂的概念就能开始写程序。我记得当年读大学的时候，第一次接触单片机就是从 51 开始的。那时候用 Keil C51 编译器，写个流水灯程序也就几十行代码，调试起来也很直观。这种"所见即所得"的学习体验，让我很快就建立了对嵌入式开发的信心。#include <reg51.h> ​ void delay(unsigned int ms) { unsigned int i？ j; for(i = 0; i < ms; i++) for(j = 0; j < 120; j++); } ​ void main() { unsigned char led = 0xFE; // 初始状态:P0.0点亮 while(1) { P0 = led; // 输出到P0口 delay(500); // 延时500ms led = (led << 1) | 0x01; // 左移一位 if(led == 0xFF) // 全灭后重新开始 led = 0xFE; } }这段流水灯代码非常简单，即使是零基础的同学看几遍也能理解。这就是 51 单片机的魅力所在——它不会让你在一开始就被复杂的寄存器配置、时钟树、中断向量表等概念搞晕。1.2 资料丰富，社区成熟51 单片机诞生于 1980 年代，经过几十年的发展，相关的学习资料、开发工具、例程代码可以说是铺天盖地。无论你遇到什么问题，基本上都能在网上找到解决方案。这对于自学者来说是非常友好的。我在做嵌入式开发的这些年里，经常会在一些论坛、贴吧看到关于 51 单片机的讨论。即使是十几年前的帖子，里面的技术方案现在依然适用。这种技术的延续性和稳定性，是很多新兴平台无法比拟的。而且，51 单片机的开发板、仿真器价格都非常便宜。一套完整的学习套件可能只需要几十块钱，这对于学生党来说非常友好。我当年买的第一块 51 开发板才 35 块钱，上面集成了 LED、数码管、按键、蜂鸣器等常用外设，足够完成大部分基础实验了。1.3 成本低廉，适合批量生产在商业应用中，成本控制是非常重要的考量因素。51 单片机的价格通常在几毛钱到几块钱之间，这对于需要大批量生产的产品来说是个巨大的优势。比如说，一些简单的家电控制器、玩具、小家电等产品，功能需求并不复杂，用 51 单片机完全可以满足。我之前接触过一个做电动车仪表盘的项目，客户最终选择了 STC89C52 作为主控芯片，原因就是成本低、供货稳定。这个项目每年的出货量在几十万台，单片机成本每降低 1 毛钱，一年就能省下好几万。1.4 功耗较低，适合电池供电场景51 单片机的功耗相对较低，特别是国产的 STC 系列，在休眠模式下电流可以降到微安级别。这使得它非常适合一些需要电池供电的场景，比如遥控器、无线传感器节点等。#include <STC89C5xRC.h> ​ void enter_power_down() { EA = 0; // 关闭总中断 PCON |= 0x02; // 进入掉电模式 _nop_(); _nop_(); } ​ void main() { // 初始化配置 P1 = 0xFF; // 设置P1口为高电平 while(1) { // 执行一些任务 // ... // 进入低功耗模式 enter_power_down(); // 被外部中断唤醒后继续执行 } }通过合理的电源管理，51 单片机可以在电池供电的情况下工作很长时间。我曾经做过一个无线温度采集器的项目，使用两节 AA 电池，通过让单片机大部分时间处于休眠状态，只在需要采集数据时唤醒，最终实现了一年以上的续航时间。1.5 结构简单，便于理解底层原理51 单片机的内部结构相对简单，包括 CPU、RAM、ROM、定时器、串口等基本模块。这种简单的架构非常适合用来学习计算机组成原理和嵌入式系统的基本概念。通过学习 51 单片机，你可以清楚地了解到程序是如何在硬件上运行的，寄存器是如何控制外设的，中断机制是如何工作的。这些底层知识对于后续学习更复杂的 ARM、RISC-V 等架构都有很大帮助。2. 51 单片机的主要缺点2.1 性能有限，处理能力较弱51 单片机的主频通…

为什么基极和发射极要并联一个电阻
type: item
date: 2026-01-31T10:51:20+08:00
description: 大家好，我是良许。在嵌入式电路设计中，我们经常会看到三极管的基极和发射极之间并联了一个电阻，这个电阻通常被称为"下拉电阻"或"偏置电阻"。很多初学者对这个电阻的作用感到困惑，今天我就来详细讲解一下为什么要加这个电阻，以及它在实际电路中的重要作用。1. 基本原理回顾在深入讨论之前，我们先简单回顾一下三极管的工作原理。三极管有三个极：基极（Base）、发射极（Emitter）和集电极（Collector）。对于NPN型三极管来说，当基极-发射极之间的电压VBE大于约0.7V时，三极管就会导通，允许电流从集电极流向发射极。这里有一个关键点：三极管的导通与否，完全取决于基极-发射极之间的电压。如果基极处于悬空状态或者受到干扰，三极管的状态就会变得不可控，这正是我们需要在基极和发射极之间加电阻的主要原因之一。2. 基极-发射极并联电阻的主要作用2.1 防止基极悬空这是最重要的作用。在实际电路中，当控制三极管的信号源处于高阻态时（比如单片机的GPIO引脚配置为输入模式，或者电路断电），基极就会处于悬空状态。悬空的基极就像一个天线，会拾取周围的电磁干扰信号，这些干扰可能导致三极管意外导通。举个实际的例子，在STM32控制的继电器电路中，如果没有基极-发射极电阻，当STM32复位或者GPIO引脚未初始化时，继电器可能会因为干扰而误动作。这在工业控制场合是非常危险的。通过在基极和发射极之间并联一个电阻（通常是10kΩ到100kΩ），我们为基极提供了一个确定的低电平通路。当控制信号断开时，这个电阻会将基极电压拉到与发射极相同的电位，确保三极管可靠截止。2.2 提供泄放通路三极管的基极-发射极结本质上是一个PN结，具有一定的结电容。当基极从高电平切换到低电平时，这个结电容上存储的电荷需要有一个释放通路。如果没有基极-发射极电阻，电荷只能通过控制电路缓慢泄放，导致三极管关断速度变慢。加上这个电阻后，存储的电荷可以快速通过电阻泄放到发射极，大大提高了三极管的关断速度。这在高频开关电路中尤为重要。例如，在PWM控制的LED驱动电路中，如果三极管关断速度太慢，就会导致LED在应该熄灭时仍有微弱发光，影响调光效果。2.3 增强抗干扰能力在嵌入式系统中，电磁干扰是一个常见问题。PCB板上的高频信号、电源纹波、外部电磁场等都可能在基极引入干扰信号。基极-发射极电阻相当于为基极提供了一个低阻抗的接地路径，可以有效地将这些干扰信号旁路到地，提高电路的抗干扰能力。这个电阻的阻值选择很有讲究。阻值太小会增加控制电路的负担，阻值太大则起不到良好的抗干扰效果。一般来说，10kΩ到47kΩ是比较常用的取值范围。3. 实际应用案例让我给大家展示一个典型的STM32控制继电器的电路设计案例，这样可以更直观地理解这个电阻的作用。// STM32 HAL库控制继电器的代码示例 // 硬件连接：PA5 -> 基极限流电阻 -> 三极管基极 // 三极管基极-发射极之间并联10kΩ电阻 // 三极管集电极 -> 继电器线圈 -> VCC // 发射极 -> GND #include "main.h" // 初始化GPIO void Relay_Init(void) { GPIO_InitTypeDef GPIO_InitStruct = {0}; // 使能GPIOA时钟 __HAL_RCC_GPIOA_CLK_ENABLE(); // 配置PA5为推挽输出 GPIO_InitStruct.Pin = GPIO_PIN_5; 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); // 初始化为低电平，确保继电器关闭 HAL_GPIO_WritePin(GPIOA, GPIO_PIN_5, GPIO_PIN_RESET); } // 控制继电器开关 void Relay_Control(uint8_t state) { if(state) { HAL_GPIO_WritePin(GPIOA, GPIO_PIN_5, GPIO_PIN_SET); // 继电器吸合 } else { HAL_GPIO_WritePin(GPIOA, GPIO_PIN_5, GPIO_PIN_RESET); // 继电器释放 } } // 主函数示例 int main(void) { HAL_Init(); SystemClock_Config(); Relay_Init(); while(1) { Relay_Control(1); //…

IIC总线的硬件部分的两个关键点：开漏输出+上拉电阻
type: item
date: 2026-01-30T10:18:00+08:00
description: 大家好，我是良许。在嵌入式开发中，IIC（I2C）总线可以说是最常用的通信协议之一了。无论是读取传感器数据、控制EEPROM存储器，还是与各种外设进行通信，IIC总线都扮演着重要角色。但很多初学者在使用IIC时，往往只关注软件层面的时序和协议，却忽略了硬件层面的关键设计。今天我就来聊聊IIC总线硬件部分的两个核心要点：开漏输出和上拉电阻。理解了这两点，你才能真正掌握IIC总线的精髓。1. IIC总线的基本结构在深入讲解之前，我们先简单回顾一下IIC总线的基本构成。IIC总线只需要两根信号线就能实现多主机、多从机之间的通信，这两根线分别是：SCL（Serial Clock）：时钟线，由主机产生时钟信号SDA（Serial Data）：数据线，用于主从设备之间的数据传输一条IIC总线上可以挂载多个设备，每个设备都有唯一的地址。这种简洁的设计让IIC总线在嵌入式系统中广受欢迎，特别是在PCB布线空间有限的场景下。但问题来了：多个设备共用同一根数据线和时钟线，它们是如何避免冲突的呢？这就要说到IIC总线硬件设计的核心机制了。2. 开漏输出：IIC总线的灵魂2.1 什么是开漏输出开漏输出（Open-Drain）是IIC总线最核心的硬件特性。要理解开漏输出，我们先来看看常见的GPIO输出模式。在普通的推挽输出（Push-Pull）模式下，GPIO引脚可以主动输出高电平（通过上管导通）或低电平（通过下管导通）。这种模式下，引脚能够提供较强的驱动能力，但有个致命问题：如果两个推挽输出的引脚连接在一起，一个输出高电平，另一个输出低电平，就会造成短路，可能烧毁芯片。而开漏输出则不同，它的内部结构只有一个下拉的NMOS管，没有上拉的PMOS管。这意味着：当GPIO输出低电平时，NMOS管导通，引脚被拉到地（GND），呈现低电平当GPIO输出高电平时，NMOS管截止，引脚呈现高阻态（既不输出高也不输出低）这种"只能拉低，不能拉高"的特性，正是开漏输出的精髓所在。2.2 开漏输出的优势你可能会问：只能拉低不能拉高，这不是很鸡肋吗？恰恰相反，这正是IIC总线能够实现多设备共享总线的关键。第一个优势：线与逻辑多个开漏输出连接在同一根线上时，会形成"线与"（Wired-AND）逻辑。只要有任何一个设备输出低电平，整条总线就是低电平；只有当所有设备都输出高阻态时，总线才能被上拉电阻拉到高电平。这种特性在IIC总线中至关重要。比如在多主机系统中，如果两个主机同时发送数据产生冲突，通过检测总线电平，主机可以发现冲突并进行仲裁。发送"1"的主机如果检测到总线为"0"，就知道有其他主机在发送数据，会主动放弃总线控制权。第二个优势：电平转换开漏输出配合上拉电阻，可以轻松实现不同电压域之间的电平转换。比如一个3.3V的MCU和一个5V的传感器通信，只需要将上拉电阻接到5V电源，就能实现电平匹配。3.3V的MCU输出低电平时可以将总线拉低，输出高阻态时总线被上拉到5V，这个5V电平不会损坏MCU（因为MCU引脚是高阻态，没有电流流入）。第三个优势：避免总线冲突在推挽输出模式下，如果两个设备同时驱动总线，一个输出高一个输出低，就会造成短路。而开漏输出永远不会主动输出高电平，最多只是高阻态，因此不会产生短路风险。2.3 STM32中的开漏配置在STM32中配置IIC引脚为开漏输出非常简单。使用HAL库的话，代码如下：void MX_I2C1_Init(void) { GPIO_InitTypeDef GPIO_InitStruct = {0}; /* 使能GPIOB时钟 */ __HAL_RCC_GPIOB_CLK_ENABLE(); /* 配置IIC引脚：PB6(SCL), PB7(SDA) */ GPIO_InitStruct.Pin = GPIO_PIN_6 | GPIO_PIN_7; GPIO_InitStruct.Mode = GPIO_MODE_AF_OD; // 复用开漏输出 GPIO_InitStruct.Pull = GPIO_NOPULL; // 不使用内部上下拉 GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH; GPIO_InitStruct.Alternate = GPIO_AF4_I2C1; HAL_GPIO_Init(GPIOB, &GPIO_InitStruct); /* 配置IIC外设 */ hi2c1.Instance = I2C1; hi2c1.Init.ClockSpeed = 100000; // 100kHz标准速率 hi2c1.Init.DutyCycle = I2C_DUTYCYCLE_2; hi2c1.Init.OwnAddress1 = 0; hi2c1.Init.AddressingM…

嵌入式就业到底选什么方向？
type: item
date: 2026-01-29T10:56:55+08:00
description: 大家好，我是良许。最近收到不少粉丝的私信，问得最多的就是："良许，嵌入式方向这么多，我到底该选哪个？"说实话，这个问题我当年也纠结过。今天就结合我这些年的经验，跟大家好好聊聊嵌入式就业方向的选择问题。1. 嵌入式领域的主流方向1.1 单片机开发方向这是我入行时的第一个方向。单片机开发主要是基于STM32、51单片机、PIC等芯片进行底层开发，通常应用在智能家居、工业控制、医疗设备等领域。这个方向的特点是门槛相对较低，但要做精也不容易。你需要掌握C语言、硬件电路知识、各种外设驱动（GPIO、UART、SPI、I2C等）。举个例子，用STM32的HAL库点个灯看起来简单：// 初始化GPIO void LED_Init(void) { GPIO_InitTypeDef GPIO_InitStruct = {0}; __HAL_RCC_GPIOA_CLK_ENABLE(); GPIO_InitStruct.Pin = GPIO_PIN_5; 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); } // 主循环控制LED闪烁 int main(void) { HAL_Init(); LED_Init(); while(1) { HAL_GPIO_WritePin(GPIOA, GPIO_PIN_5, GPIO_PIN_SET); HAL_Delay(500); HAL_GPIO_WritePin(GPIOA, GPIO_PIN_5, GPIO_PIN_RESET); HAL_Delay(500); } }但实际项目中，你要处理的是复杂的通信协议、实时性要求、功耗优化、抗干扰设计等问题。这个方向的薪资在一线城市应届生大概8K-12K，3年经验能到15K-20K。1.2 嵌入式Linux应用开发这是我27岁进入外企后的主要方向，也是目前市场需求最大的方向之一。主要工作是在Linux系统上开发应用程序，涉及文件IO、进程线程、网络编程、数据库操作等。这个方向需要你熟悉Linux系统编程、Shell脚本、网络协议栈、多线程编程等。比如一个简单的多线程读取传感器数据的例子：#include <pthread.h> #include <stdio.h> #include <unistd.h> void* sensor_read_thread(void* arg) { int sensor_id = *(int*)arg; while(1) { // 模拟读取传感器数据 printf("Sensor %d: Reading data...\n", sensor_id); sleep(1); } return NULL; } int main() { pthread_t thread1, thread2; int sensor1 = 1, sensor2 = 2; pthread_create(&thread1, NULL, sensor_read_thread, &sensor1); pthread_create(&thread2, NULL, sensor_read_thread, &sensor2); pthread_join(thread1, NULL); pthread_join(thread2, NULL); return 0; }这个方向在汽车电子、智能设备、工业互联网等领域应用广泛。薪资方面，应届生大概10K-15K，3年经验能达到20K-30K，在外企或大厂甚至更高。1.3 嵌入式Linux驱动开发这是嵌入式领域的高端方向，主要负责编写Linux内核驱动程序，让硬件设备能够在Linux系统上正常工作。需要深入理解Linux内核机制、硬件原理、驱动框架等。驱动开发的难度比较大，需要掌握内核模块编程、设备树、中断处理、DMA等知识。一个简单的字符设备驱动框架：#include <linux/module.h> #include <linux/fs.h> #include <linux/cdev.h> static dev_t dev_num; static struct cdev my_cdev; static int my_open(struct inode *inode, struct file *file) { printk("Device opened\n"); return 0; } static ssize_t my_read(struct file …

达林顿管的基础知识
type: item
date: 2026-01-28T10:31:28+08:00
description: 达林顿管的基础知识大家好，我是良许。在嵌入式开发中，我们经常需要驱动各种负载，比如继电器、电机、LED灯带等。这些负载往往需要较大的电流，而单片机的IO口输出能力有限，这时候就需要用到功率放大电路。达林顿管（Darlington Transistor）就是一种非常实用的功率放大器件，它能够提供极高的电流增益，让我们用很小的基极电流就能控制很大的负载电流。今天我就来详细聊聊达林顿管的相关知识。1. 什么是达林顿管1.1 达林顿管的结构达林顿管，又称达林顿晶体管或复合管，是由两个或多个三极管按照特定方式连接而成的复合器件。最常见的是由两个NPN型或PNP型三极管组成。其基本连接方式是：第一个三极管（称为驱动管）的发射极直接连接到第二个三极管（称为输出管）的基极，而两个三极管的集电极连接在一起作为复合管的集电极。这种连接方式使得第一个三极管的输出电流成为第二个三极管的输入电流，从而实现了电流的二次放大。如果第一个三极管的电流增益是β1，第二个三极管的电流增益是β2，那么整个达林顿管的总电流增益约为β1×β2，通常可以达到几百甚至上千。1.2 达林顿管的符号在电路图中，达林顿管有专门的符号表示。对于NPN型达林顿管，符号看起来像一个普通的NPN三极管，但在内部会画出两个三极管的连接关系。有些封装好的达林顿管芯片，比如ULN2003、TIP120等，在电路图中可能直接用一个三角形加箭头表示，并标注型号。1.3 常见的达林顿管型号在实际应用中，常见的达林顿管型号包括：TIP120/TIP121/TIP122：NPN型达林顿管，最大电流5A，常用于中等功率场合TIP125/TIP126/TIP127：PNP型达林顿管，与TIP120系列互补ULN2003/ULN2803：集成了7路/8路达林顿管阵列的芯片，内置续流二极管，特别适合驱动继电器、步进电机等感性负载BD681/BD682：大功率达林顿管，最大电流可达4A2. 达林顿管的工作原理2.1 电流放大过程达林顿管的核心优势在于其超高的电流放大能力。让我们详细分析一下电流是如何被放大的。假设我们有一个由Q1和Q2组成的NPN型达林顿管，当基极B输入一个微小的电流Ib时，这个电流首先流入Q1的基极。根据三极管的放大原理，Q1的集电极电流Ic1=β1×Ib，发射极电流Ie1=(β1+1)×Ib。由于Q1的发射极连接到Q2的基极，因此Ie1就成为了Q2的基极电流。Q2再次进行电流放大，其集电极电流Ic2=β2×Ie1=β2×(β1+1)×Ib。最终，达林顿管的总集电极电流Ic=Ic1+Ic2≈β1×β2×Ib（当β1和β2都远大于1时）。这就是达林顿管能够实现超高电流增益的原因。2.2 导通压降达林顿管有一个需要注意的特点，就是它的基极-发射极导通压降（Vbe）比普通三极管要高。普通三极管的Vbe约为0.7V，而达林顿管的Vbe约为1.4V（两个三极管的Vbe相加）。这意味着在设计电路时，我们需要确保基极电压至少比发射极高1.4V以上，达林顿管才能可靠导通。同样，集电极-发射极的饱和压降（Vce(sat)）也会比普通三极管略高，通常在0.9V到2V之间。2.3 开关速度由于达林顿管是两级放大，其开关速度相对较慢。这是因为关断时需要等待两个三极管的存储电荷都消散完毕。因此，达林顿管不太适合用于高频开关场合，更适合用于低频或直流驱动应用。3. 达林顿管的典型应用3.1 驱动继电器继电器是嵌入式系统中常用的执行器件，但其线圈电流通常在几十到上百毫安，远超单片机IO口的驱动能力。使用达林顿管可以轻松解决这个问题。以STM32驱动继电器为例，我们可以使用TIP120达林顿管。电路连接方式是：STM32的GPIO通过一个限流电阻（比如10kΩ）连接到TIP120的基极，继电器线圈一端接电源正极，另一端接TIP120的集电极，发射极接地。继电器线圈两端还需要并联一个续流二极管（如1N4007），防止关断时的反向电动势损坏达林顿管。下面是一个简单的HAL库代码示例：// 初始化GPIO void Relay_Init(void) { GPIO_InitTypeDef GPIO_InitStruct = {0}; // 使能GPIOA时钟 __HAL_RCC_GPIOA_CLK_ENABLE(); // 配置PA5为输出模式 GPIO_InitStruct.Pin = GPIO_PIN_5; 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)…

什么是三极管？
type: item
date: 2026-01-21T10:30:50+08:00
description: 大家好，我是良许说到三极管，可能很多刚入门的朋友会觉得这个名字有点陌生，但如果你接触过电子电路或者嵌入式开发，那你一定见过它的身影。三极管可以说是电子世界里最基础、最重要的元器件之一，几乎所有的电子设备里都能找到它的踪迹。今天咱们就来聊聊三极管到底是什么，它有什么用，以及在实际开发中我们该怎么使用它。1. 三极管的基本概念1.1 三极管是什么三极管，全称叫做"半导体三极管"，英文名是 Transistor，有时候也叫做晶体管。从名字就能看出来，它有三个电极，这也是"三极管"名字的由来。这三个电极分别叫做：基极（Base，简称 B）、集电极（Collector，简称 C）和发射极（Emitter，简称 E）。三极管本质上是一种半导体器件，它是由两个 PN 结组成的。根据这两个 PN 结的排列方式不同，三极管可以分为 NPN 型和 PNP 型两种。NPN 型就是中间是 P 型半导体，两边是 N 型半导体；PNP 型则相反，中间是 N 型半导体，两边是 P 型半导体。在实际应用中，NPN 型三极管使用得更多一些。1.2 三极管的工作原理三极管最神奇的地方在于，它可以用一个很小的电流去控制一个很大的电流。具体来说，就是通过控制基极和发射极之间的电流（基极电流，记作IB​），来控制集电极和发射极之间的电流（集电极电流，记作IC）。这个过程就像是用一个小水龙头去控制一个大水龙头的开关一样。这里有一个很重要的参数，叫做电流放大倍数，用希腊字母β（贝塔）来表示。这个β值表示的是集电极电流和基极电流的比值，也就是：$$ \beta = \frac{I_C}{I_B} $$一般来说，普通三极管的β值在几十到几百之间。比如说，如果一个三极管的β值是 100，那么当基极电流是 1mA 的时候，集电极电流就可以达到 100mA。这就是三极管的放大作用。1.3 三极管的三种工作状态三极管在电路中有三种基本的工作状态：截止状态、放大状态和饱和状态。截止状态：当基极电流为零或者很小的时候，三极管就处于截止状态。这时候集电极电流也基本为零，三极管相当于一个断开的开关。放大状态：当基极电流在一个合适的范围内时，三极管就工作在放大状态。这时候集电极电流和基极电流成正比关系，也就是IC​=β×IB。这个状态主要用于模拟电路中的信号放大。饱和状态：当基极电流足够大的时候，三极管就进入了饱和状态。这时候集电极电流不再随基极电流的增加而增加，三极管相当于一个闭合的开关。在数字电路中，我们经常让三极管工作在饱和状态或截止状态，用来实现开关功能。2. 三极管的实际应用2.1 三极管作为开关使用在嵌入式开发中，我们最常用三极管来做的事情就是当开关用。比如说，STM32 的 GPIO 口输出电流一般只有几十毫安，如果我们要驱动一个需要几百毫安电流的负载（比如继电器、电机等），直接用 GPIO 口是不行的，这时候就需要用三极管来做电流放大。举个具体的例子，假设我们要用 STM32 控制一个 12V 的继电器，这个继电器的线圈电流是 100mA。我们可以这样设计电路：用 STM32 的 GPIO 口控制三极管的基极，三极管的集电极接继电器线圈，发射极接地。当 GPIO 口输出高电平时，三极管导通，继电器得电工作；当 GPIO 口输出低电平时，三极管截止，继电器断电。下面是一个简单的 HAL 库代码示例：// 初始化GPIO void Relay_GPIO_Init(void) { GPIO_InitTypeDef GPIO_InitStruct = {0}; // 使能GPIOA时钟 __HAL_RCC_GPIOA_CLK_ENABLE(); // 配置PA5为输出模式 GPIO_InitStruct.Pin = GPIO_PIN_5; 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); // 初始状态设为低电平，继电器断电 HAL_GPIO_WritePin(GPIOA, GPIO_PIN_5, GPIO_PIN_RESET); } ​ // 控制继电器开 void Relay_On(void) { HAL_GPIO_WritePin(GPIOA, GPIO_PIN_5, GPIO_PIN_SET); } ​ // 控制继电器关 void Relay_Off(void) { HAL_GPIO_WritePin(GPIOA, GPIO_PIN_5, GPIO_PIN_RESET); }在这个应用…

什么是MOS管？
type: item
date: 2026-01-20T10:03:45+08:00
description: 什么是 MOS 管？大家好，我是良许。最近在做一个电源管理的项目，需要用到 MOS 管来控制大电流的开关。很多刚入门的朋友可能对 MOS 管不太了解，今天我就来详细聊聊这个在电子电路中非常重要的元器件。1. MOS 管的基本概念1.1 MOS 管的全称与结构MOS 管的全称是 Metal-Oxide-Semiconductor Field-Effect Transistor，中文叫做金属-氧化物-半导体场效应晶体管，简称 MOSFET 或者 MOS 管。从名字就能看出来，它主要由三种材料构成：金属栅极、氧化物绝缘层和半导体衬底。MOS 管有三个引脚，分别是栅极（Gate，简称 G）、漏极（Drain，简称 D）和源极（Source，简称 S）。这三个引脚的作用各不相同：栅极用来控制开关，漏极和源极之间形成导电通道。当我们在栅极施加一定的电压时，就可以控制漏极和源极之间是否导通，这就是 MOS 管最核心的工作原理。1.2 MOS 管的分类MOS 管主要分为两大类：N 沟道 MOS 管（NMOS）和 P 沟道 MOS 管（PMOS）。这两种管子的工作原理类似，但是导通条件相反。对于 NMOS 管来说，当栅极电压高于源极电压一定程度（超过阈值电压）时，漏极和源极之间就会导通。而 PMOS 管则相反，当栅极电压低于源极电压一定程度时才会导通。在实际应用中，NMOS 管使用得更多一些，因为它的导通电阻更小，开关速度更快。此外，根据工作模式的不同，MOS 管还可以分为增强型和耗尽型。增强型 MOS 管在栅极没有电压时是截止的，需要施加电压才能导通，这是最常用的类型。耗尽型 MOS 管则相反，在栅极没有电压时就是导通的，需要施加反向电压才能截止，这种类型比较少见。2. MOS 管的工作原理2.1 电场效应控制MOS 管之所以叫做场效应晶体管，是因为它是通过电场来控制电流的。当我们在栅极施加电压时，会在氧化层下方的半导体表面产生一个电场。这个电场会吸引或排斥半导体中的载流子（电子或空穴），从而在漏极和源极之间形成或消除导电沟道。以 NMOS 管为例，当栅极电压为 0V 时，漏极和源极之间是 P 型半导体，不导电。当栅极施加正电压时，电场会把 P 型半导体表面的空穴排斥走，同时吸引电子过来。当电子浓度足够高时，就会在表面形成一个 N 型导电沟道，这时漏极和源极之间就导通了。2.2 三个工作区域MOS 管在工作时有三个主要区域：截止区、线性区（也叫欧姆区）和饱和区。在截止区时，栅极电压小于阈值电压，漏极和源极之间不导通，相当于一个开关断开的状态。这时 MOS 管的漏极电流几乎为零，只有很小的漏电流。在线性区时，栅极电压大于阈值电压，且漏极电压较小，此时漏极电流与漏源电压成正比关系，MOS 管表现得像一个可变电阻。在这个区域，我们可以通过改变栅极电压来调节导通电阻的大小。在饱和区时，栅极电压大于阈值电压，且漏极电压较大，此时漏极电流基本不随漏源电压变化，而是由栅极电压决定。这个区域主要用于放大电路。2.3 阈值电压的重要性阈值电压（$$V\_{th}$$）是 MOS 管的一个重要参数，它决定了 MOS 管从截止到导通需要多大的栅极电压。对于 NMOS 管，阈值电压通常在 1V 到 4V 之间，对于 PMOS 管则是负值。在实际应用中，我们需要确保栅极电压足够大，通常要比阈值电压高出几伏，这样才能保证 MOS 管完全导通，降低导通电阻。3. MOS 管在嵌入式系统中的应用3.1 开关电路在嵌入式系统中，MOS 管最常见的应用就是做开关。比如我们要用单片机控制一个 12V 的电机，单片机的 IO 口只能输出 3.3V 或 5V 的电压，而且驱动能力很弱，这时就需要用 MOS 管来做开关。下面是一个使用 STM32 控制 NMOS 管的简单例子：// 初始化GPIO用于控制MOS管 void MOS_GPIO_Init(void) { GPIO_InitTypeDef GPIO_InitStruct = {0}; // 使能GPIOA时钟 __HAL_RCC_GPIOA_CLK_ENABLE(); // 配置PA5为输出模式 GPIO_InitStruct.Pin = GPIO_PIN_5; 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); // 初始状态设为低电平，MOS管截止 HAL_GPIO_WritePin(GPIOA, GPIO_PIN_5, GPIO_…